Zeta: Type MDX Plugins

This commit is contained in:
SonMooSans
2023-10-18 19:09:33 +08:00
parent a4a8120e44
commit 104353250b
8 changed files with 107 additions and 108 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'next-docs-zeta': patch
---
Type MDX Plugins
+12 -17
View File
@@ -22,9 +22,9 @@
"import": "./dist/toc/index.mjs",
"types": "./dist/toc/index.d.ts"
},
"./search": {
"import": "./dist/search/index.mjs",
"types": "./dist/search/index.d.ts"
"./search/*": {
"import": "./dist/search/*.mjs",
"types": "./dist/search/*.d.ts"
},
"./server": {
"import": "./dist/server/index.mjs",
@@ -50,13 +50,9 @@
"import": "./dist/mdx-plugins/index.mjs",
"types": "./dist/mdx-plugins/index.d.ts"
},
"./algolia": {
"import": "./dist/algolia/index.mjs",
"types": "./dist/algolia/index.d.ts"
},
"./search-algolia": {
"import": "./dist/search-algolia/index.mjs",
"types": "./dist/search-algolia/index.d.ts"
"./search-algolia/*": {
"import": "./dist/search-algolia/*.mjs",
"types": "./dist/search-algolia/*.d.ts"
}
},
"typesVersions": {
@@ -70,8 +66,8 @@
"toc": [
"./dist/toc/index.d.ts"
],
"search": [
"./dist/search/index.d.ts"
"search/*": [
"./dist/search/*.d.ts"
],
"server": [
"./dist/server/index.d.ts"
@@ -91,11 +87,8 @@
"middleware": [
"./dist/middleware/index.d.ts"
],
"algolia": [
"./dist/algolia/index.d.ts"
],
"search-algolia": [
"./dist/search-algolia/index.d.ts"
"search-algolia/*": [
"./dist/search-algolia/*.d.ts"
]
}
},
@@ -130,6 +123,8 @@
"devDependencies": {
"@algolia/client-search": "^4.20.0",
"@types/flexsearch": "0.7.4",
"@types/hast": "^2.3.5",
"@types/mdast": "^3.0.12",
"@types/negotiator": "^0.6.1",
"@types/react": "18.2.0",
"@types/react-dom": "18.2.1",
@@ -1,15 +1,17 @@
// @ts-nocheck
import Slugger from 'github-slugger'
import rehypePrettycode from 'rehype-pretty-code'
import type { Root } from 'hast'
import rehypePrettycode, {
type Options as RehypePrettyCodeOptions
} from 'rehype-pretty-code'
import type { Transformer } from 'unified'
import { flattenNode, visit } from './utils'
const slugger = new Slugger()
const headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
const customMetaRegex = /custom="([^"]+)"/
/**
* @type {import('rehype-pretty-code').Options}
*/
const rehypePrettyCodeOptions = {
const rehypePrettyCodeOptions: RehypePrettyCodeOptions = {
theme: 'css-variables',
defaultLang: {
block: 'text'
@@ -24,7 +26,7 @@ const rehypePrettyCodeOptions = {
/**
* Handle codeblocks and heading slugs
*/
export const rehypeNextDocs = () => async tree => {
export const rehypeNextDocs = (): Transformer<Root, Root> => async tree => {
slugger.reset()
visit(tree, ['pre', ...headings], node => {
@@ -1,6 +1,7 @@
import fs from 'fs'
import path from 'path'
import type { Plugin } from 'unified'
import type { Root } from 'mdast'
import type { Transformer } from 'unified'
import { visit } from 'unist-util-visit'
const regex = /^\|reference:(.+)\|/
@@ -10,6 +11,12 @@ type Options = {
cwd?: string
/** @default true */
trim?: boolean
/**
* Filter specific element types
* @default ['text','code']
* */
visit?: string[]
}
/**
@@ -18,18 +25,26 @@ type Options = {
* @example
* |reference:../path/to/file.ts|
*/
export function remarkDynamicContent(options: Options = {}): Plugin {
const { cwd = process.cwd(), trim = true } = options
export function remarkDynamicContent(
options: Options = {}
): Transformer<Root, Root> {
const {
cwd = process.cwd(),
trim = true,
visit: filter = ['text', 'code']
} = options
return tree => {
visit(tree, ['text', 'code'], node => {
visit(tree, filter, node => {
if (!('value' in node) || typeof node.value !== 'string') return
const result = regex.exec(node.value)
if (result && result[1]) {
const dest = path.resolve(cwd, result[1])
let value = fs.readFileSync(dest).toString()
if (trim) value = value.trim()
node.value = fs.readFileSync(dest).toString()
if (trim) node.value = node.value.trim()
node.value = value
}
})
}
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// @ts-nocheck
import Slugger from 'github-slugger'
import type { Node, Root } from 'mdast'
import { remark } from 'remark'
import remarkGfm from 'remark-gfm'
import remarkMdx from 'remark-mdx'
import type { PluggableList } from 'unified'
import type { PluggableList, Transformer } from 'unified'
import { visit } from 'unist-util-visit'
type Heading = {
@@ -36,8 +37,8 @@ type Options = {
const slugger = new Slugger()
const textTypes = ['text', 'inlineCode']
function flattenNode(node: any) {
const p: any[] = []
function flattenNode(node: Node) {
const p: string[] = []
visit(node, textTypes, node => {
if (typeof node.value !== 'string') return
p.push(node.value)
@@ -45,9 +46,10 @@ function flattenNode(node: any) {
return p.join(``)
}
const structurize =
({ types = ['paragraph', 'blockquote', 'heading'] }: Options = {}) =>
(node: any, file: any) => {
function structurize({
types = ['paragraph', 'blockquote', 'heading']
}: Options = {}): Transformer<Root, Root> {
return (node, file) => {
slugger.reset()
const data: StructuredData = { contents: [], headings: [] }
let lastHeading: string | undefined = ''
@@ -76,6 +78,7 @@ const structurize =
file.data = data
}
}
/**
* Extract data from markdown/mdx content
@@ -92,5 +95,5 @@ export function structure(
.use([structurize, options])
.processSync(content)
return result.data as StructuredData
return result.data
}
@@ -1,71 +0,0 @@
/**
* @typedef {import('hast').Nodes} Nodes
* @typedef {import('hast').Parents} Parents
*/
/**
* Visit a node with filtered tag names
*
* @param {Nodes} node
* Node to visit.
* @param {Array<string>} tagNames
* @param {(node: Nodes) => void} handler
*/
export function visit(node, tagNames, handler) {
if (tagNames.includes(node.tagName)) {
handler(node)
return
}
node.children?.forEach(n => visit(n, tagNames, handler))
}
/**
* Get the plain-text value of a hast node.
*
* @param {Nodes} node
* Node to serialize.
* @returns {string}
* Serialized node.
*/
export function flattenNode(node) {
// “The concatenation of data of all the Text node descendants of the context
// object, in tree order.”
if ('children' in node) {
return all(node)
}
// “Context object’s data.”
return 'value' in node ? node.value : ''
}
/**
* @param {Nodes} node
* Node.
* @returns {string}
* Serialized node.
*/
function one(node) {
if (node.type === 'text') {
return node.value
}
return 'children' in node ? all(node) : ''
}
/**
* @param {Parents} node
* Node.
* @returns {string}
* Serialized node.
*/
function all(node) {
/** @type {Array<string>} */
const result = []
for (let i = 0; i < node.children.length; i++) {
result[i] = one(node.children[i])
}
return result.join('')
}
@@ -0,0 +1,44 @@
// @ts-nocheck
import type { Node } from 'hast'
/**
* Visit a node with filtered tag names
*/
export function visit(
node: Node,
tagNames: string[],
handler: (node: Node) => void
) {
if (tagNames.includes(node.tagName)) {
handler(node)
return
}
node.children?.forEach(n => visit(n, tagNames, handler))
}
export function flattenNode(node: Node): string {
if ('children' in node) {
return all(node)
}
return 'value' in node ? node.value : ''
}
function one(node: Node): string {
if (node.type === 'text') {
return node.value
}
return 'children' in node ? all(node) : ''
}
function all(node: Node) {
const result: string[] = []
for (let i = 0; i < node.children.length; i++) {
result[i] = one(node.children[i])
}
return result.join('')
}
+6
View File
@@ -286,6 +286,12 @@ importers:
'@types/flexsearch':
specifier: 0.7.4
version: 0.7.4
'@types/hast':
specifier: ^2.3.5
version: 2.3.5
'@types/mdast':
specifier: ^3.0.12
version: 3.0.12
'@types/negotiator':
specifier: ^0.6.1
version: 0.6.1