Skip to content

Commit

Permalink
feat: Change code highlighter to starry-night
Browse files Browse the repository at this point in the history
- starry-night 설치 및 highlight.js 제거
- highlight.js에서 사용하던 코드블럭 css 파일 제거
- starry-night rehype plugin 추가
- rehype plugin을 starry-night으로 대체
  • Loading branch information
paulcjy committed Dec 15, 2023
1 parent e4f3a2d commit 987a20b
Show file tree
Hide file tree
Showing 8 changed files with 480 additions and 275 deletions.
4 changes: 2 additions & 2 deletions contentlayer.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineDocumentType, makeSource } from 'contentlayer/source-files'
import rehypeHighlight from 'rehype-highlight'
import rehypeStarryNight from './lib/rehype-starry-night'

export const Post = defineDocumentType(() => ({
name: 'Post',
Expand Down Expand Up @@ -55,5 +55,5 @@ export const Post = defineDocumentType(() => ({
export default makeSource({
contentDirPath: 'posts',
documentTypes: [Post],
markdown: { rehypePlugins: [rehypeHighlight] },
markdown: { rehypePlugins: [rehypeStarryNight] },
})
87 changes: 87 additions & 0 deletions lib/rehype-starry-night.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* @typedef {import('@wooorm/starry-night').Grammar} Grammar
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('hast').Root} Root
*/

/**
* @typedef Options
* Configuration (optional)
* @property {Array<Grammar> | null | undefined} [grammars]
* Grammars to support (default: `common`).
*/

import { all, createStarryNight } from '@wooorm/starry-night'
import { toString } from 'hast-util-to-string'
import { visit } from 'unist-util-visit'

/**
* Highlight code with `starry-night`.
*
* @param {Options | null | undefined} [options]
* Configuration (optional).
* @returns
* Transform.
*/
export default function rehypeStarryNight(options) {
const settings = options || {}
const grammars = settings.grammars || all
const starryNightPromise = createStarryNight(grammars)
const prefix = 'language-'

/**
* Transform.
*
* @param {Root} tree
* Tree.
* @returns {Promise<undefined>}
* Nothing.
*/
return async function (tree) {
const starryNight = await starryNightPromise

visit(tree, 'element', function (node, index, parent) {
if (!parent || index === undefined || node.tagName !== 'pre') {
return
}

const head = node.children[0]

if (!head || head.type !== 'element' || head.tagName !== 'code') {
return
}

const classes = head.properties.className

if (!Array.isArray(classes)) return

const language = classes.find(function (d) {
return typeof d === 'string' && d.startsWith(prefix)
})

if (typeof language !== 'string') return

const scope = starryNight.flagToScope(language.slice(prefix.length))

// Maybe warn?
if (!scope) return

const fragment = starryNight.highlight(toString(head), scope)
const children = /** @type {Array<ElementContent>} */ fragment.children

parent.children.splice(index, 1, {
type: 'element',
tagName: 'div',
properties: {
className: [
'highlight',
'highlight-' + scope.replace(/^source\./, '').replace(/\./g, '-'),
],
},
children: [
{ type: 'element', tagName: 'pre', properties: {}, children },
],
})
})
}
}
Loading

0 comments on commit 987a20b

Please sign in to comment.