VSCode를 사용하여 웹사이트의 코드 블록 강조 표시

20308 단어 tutorialjavascript
웹사이트에서 코드 블록을 강조 표시할 때 사용 가능한 옵션이 많지 않은 것처럼 보일 수 있습니다. 나는 웹사이트의 90%가 Prism 또는 HighlightJS을 사용한다고 확신합니다. 이러한 옵션은 좋지만 supporting new PHP syntax 또는 Laravel Blade 뷰를 올바르게 강조 표시하는 것과 같은 더 많은 틈새 사용 사례에 대한 표시를 놓치는 경우가 많습니다.

이 웹사이트의 코드 블록을 개선하기로 결정했을 때 첫 번째 아이디어는 VSCode Community Material theme 에서 영감을 받아 사용자 지정 Prism 테마를 만드는 것이었습니다. 그러나 almost 100 lines of hot-fixing Prism 이후에는 포기하고 대안을 찾기 시작했습니다. 나는 많은 희망이 없었지만 결국 holy grail of syntax highlighting을 찾았습니다. VSCode가 웹 사이트에서 VSCode 테마 및 확장을 지원하는 것과 동일한 형광펜을 사용하는 방법입니다.

이것을 사이트에 추가하는 방법을 시작하기 전에 함정이 있습니다. 이를 달성하는 데 사용되는 패키지는 서버에서 실행되어야 하므로 일종의 빌드 프로세스가 필요합니다(비록 there's an RFC open for browser support ). 간단한 노드 스크립트를 사용하여 이 작업을 수행하는 방법을 보여주겠지만 Next.js 및 Gatsby에서 성공적으로 작동하도록 했으며 다른 프레임워크에서도 작동하도록 하는 방법이 있다고 확신합니다. 그것은 방해가 되지 않고, 그것으로 들어가 보자!

먼저 마크다운을 가져와 HTML로 변환하는 노드 스크립트를 만들어야 합니다(나중에 웹사이트에서 에코할 수 있음). 이 예에서는 마크다운 파일로 가득 찬 posts 디렉토리와 html 파일이 있을 것으로 예상되는 build 디렉토리가 있다고 가정합니다.

const fs = require('fs')
const path = require('path')
const shiki = require('shiki')
const markdown = require('markdown-it')

shiki.getHighlighter().then(highlighter => {
    const md = markdown({
        html: true,
        highlight: (code, lang) => highlighter.codeToHtml(code, lang)
    })

    fs.readdirSync(path.join(process.cwd(), 'posts')).filter(slug => /\.mdx?$/.test(slug)).forEach(slug => {
        const content = fs.readFileSync(path.join(process.cwd(), 'posts', slug), 'utf-8')

        fs.writeFileSync(path.join(process.cwd(), 'build', slug.replace(/\.mdx?$/, '.html')), md.render(content))

        console.log(`${slug} => ${slug.replace(/\.mdx?$/, '.html')}`)
    })
})


이제 빌드 프로세스 중에 해당 스크립트를 실행하기만 하면 멋진 VSCode 기반 코드 블록을 얻을 수 있습니다!

Shiki는 plenty of languages by default 지원과 함께 제공되지만 모든 VSCode 확장에서 사용자 지정 언어를 추가할 수도 있습니다. 확장 소스에서 .tmLanguage 또는 .tmLanguage.json를 찾아 프로젝트에 복사하기만 하면 됩니다. 그런 다음 형광펜을 만들 때 추가 언어 배열을 shiki에 전달합니다.

const langs = [
    {
        id: 'blade',
        scopeName: 'text.html.php.blade',
        path: path.join(process.cwd(), 'vendor/blade.tmLanguage.json'),
        embeddedLanguages: {
            'source.php': 'php',
            'source.css': 'css',
            'source.js': 'javascript',
        },
    },
    {
        language: 'dotenv',
        scopeName: 'source.env',
        path: path.join(process.cwd(), 'vendor/env.tmLanguage'),
        aliases: ['env'],
    },
]

shiki.getHighlighter({ langs }).then(highlighter => {
    //
})


마지막으로 사용자 정의 테마는 어떻습니까? 다시 말하지만, shiki에는 many themes by default이 포함되어 있지만 소스에서 해당 테마에 대한 JSON 파일을 찾아서 직접 가져올 수 있습니다.

const theme = shiki.loadTheme(path.join(process.cwd(), 'vendor/material-theme.json')),

shiki.getHighlighter({ theme }).then(highlighter => {
    //
})


이것들은 기본이며 특정 설정에 적용할 수 있습니다. 다음은 Next.js 및 next-mdx-remote 를 사용하여 강조 표시하는 방법입니다.

import matter from 'gray-matter'
import visit from 'unist-util-visit'
import renderToString from 'next-mdx-remote/render-to-string'

export const getStaticProps = async ({ params: { slug } }) => {
    const source = fs.readFileSync(path.join(process.cwd(), 'content/posts', `${slug}.mdx`))
    const { content, data } = matter(source)

    const shiki = await import('shiki')
    const highlighter = await shiki.getHighlighter({
        theme: shiki.loadTheme(path.join(process.cwd(), 'vendor/material-theme.json')),
        langs: [{
            id: 'blade',
            scopeName: 'text.html.php.blade',
            path: path.join(process.cwd(), 'vendor/blade.tmLanguage.json'),
            embeddedLanguages: { 'source.php': 'php', 'source.css': 'css', 'source.js': 'javascript' },
        },],
    })

    const mdxSource = await renderToString(content, {
        mdxOptions: { remarkPlugins: [[remarkPlugin, { highlighter }]] },
        scope: data,
    })

    return { props: { slug, mdxSource, ...data } }
}

export const remarkPlugin = options => async tree => {
    visit(tree, 'code', node => {
        node.type = 'html'
        node.children = undefined
        node.value = options.highlighter.codeToHtml(node.value, node.lang).replace('<pre class="shiki"', `<pre class="shiki" language="${node.lang}" meta="${node.meta}"`)
    })
}


블로그에 shiki를 추가하셨나요? 코드를 강조하기 위해 다른 것을 사용하고 있습니까? 그리고 알려주세요!

좋은 웹페이지 즐겨찾기