Przeglądaj źródła

move to src folder and remove redundant visitor type

Timothy Lin 4 lat temu
rodzic
commit
8e68fb5d9b
6 zmienionych plików z 8517 dodań i 280 usunięć
  1. 3 278
      index.js
  2. 8226 1
      package-lock.json
  3. 13 0
      src/all.js
  4. 13 0
      src/common.js
  5. 261 0
      src/generator.js
  6. 1 1
      tsconfig.json

+ 3 - 278
index.js

@@ -1,281 +1,6 @@
-/**
- * @typedef {import('hast').Node & {properties: Object<any, any>}} Node
- * @typedef {import('hast').Parent & {properties: Object<any, any>}} Parent
- * @typedef {import('hast').Root} Root
- * @typedef {import('unist-util-visit').Visitor<Node>} Visitor
- * @typedef Options options
- *   Configuration.
- * @property {boolean} [showLineNumbers]
- *   Set `showLineNumbers` to `true` to always display line number
- * @property {boolean} [ignoreMissing]
- *   Set `ignoreMissing` to `true` to ignore unsupported languages and line highlighting when no language is specified
- */
-
-import { visit } from 'unist-util-visit'
-import { toString } from 'hast-util-to-string'
-import { refractor as refractorAll } from 'refractor/lib/all.js'
-import { refractor as refractorCommon } from 'refractor/lib/common.js'
-import { toHtml } from 'hast-util-to-html'
-import { filter } from 'unist-util-filter'
-import { unified } from 'unified'
-import parse from 'rehype-parse'
-import rangeParser from 'parse-numeric-range'
-
-/**
- * @param {Node} node
- * @return {string|null}
- */
-const getLanguage = (node) => {
-  const className = node.properties.className || []
-
-  for (const classListItem of className) {
-    if (classListItem.slice(0, 9) === 'language-') {
-      return classListItem.slice(9).toLowerCase()
-    }
-  }
-  return null
-}
-
-/**
- * Create a closure that determines if we have to highlight the given index
- *
- * @param {string} meta
- * @return { (index:number) => boolean }
- */
-const calculateLinesToHighlight = (meta) => {
-  const RE = /{([\d,-]+)}/
-  // Remove space between {} e.g. {1, 3}
-  const parsedMeta = meta
-    .split(',')
-    .map((str) => str.trim())
-    .join()
-  if (RE.test(parsedMeta)) {
-    const strlineNumbers = RE.exec(parsedMeta)[1]
-    const lineNumbers = rangeParser(strlineNumbers)
-    return (index) => lineNumbers.includes(index + 1)
-  } else {
-    return () => false
-  }
-}
-
-/**
- * Check if we want to start the line numbering from a given number or 1
- * showLineNumbers=5, will start the numbering from 5
- * @param {string} meta
- * @returns {number}
- */
-const calculateStartingLine = (meta) => {
-  const RE = /showLineNumbers=(?<lines>\d+)/i
-  // pick the line number after = using a named capturing group
-  if (RE.test(meta)) {
-    const {
-      groups: { lines },
-    } = RE.exec(meta)
-    return Number(lines)
-  }
-  return 1
-}
-
-/**
- * Split line to div node with className `code-line`
- *
- * @param {string} text
- * @return {Node[]}
- */
-const splitLine = (text) => {
-  // Xdm Markdown parser every code line with \n
-  const textArray = text.split(/\n/)
-
-  // Remove last line \n which results in empty array
-  if (textArray[textArray.length - 1].trim() === '') {
-    textArray.pop()
-  }
-
-  // Empty array are actually line segments so we convert them back to newlines
-  return textArray.map((line) => {
-    return {
-      type: 'element',
-      tagName: 'span',
-      properties: { className: ['code-line'] },
-      children: [{ type: 'text', value: line }],
-    }
-  })
-}
-
-/**
- * Split line to div node with className `code-line`
- *
- * @param {import('refractor').RefractorRoot} ast
- * @return {Root}
- */
-const getNodePosition = (ast) => {
-  // @ts-ignore
-  let html = toHtml(ast)
-  const hast = unified().use(parse, { emitParseErrors: true, fragment: true }).parse(html)
-  return hast
-}
-
-/**
- * Split multiline text nodes into individual nodes with positioning
- *
- * @param {Parent['children']} ast
- * @return {Parent['children']}
- */
-const splitTextByLine = (ast) => {
-  //@ts-ignore
-  return ast.reduce((result, node) => {
-    if (node.type === 'text') {
-      if (node.value.indexOf('\n') === -1) {
-        result.push(node)
-        return result
-      }
-
-      const lines = node.value.split('\n')
-      for (const [i, line] of lines.entries()) {
-        result.push({
-          type: 'text',
-          value: i === lines.length - 1 ? line : line + '\n',
-          position: {
-            start: { line: node.position.start.line + i },
-            end: { line: node.position.start.line + i },
-          },
-        })
-      }
-
-      return result
-    }
-
-    if (node.children) {
-      // @ts-ignore
-      node.children = splitTextByLine(node.children)
-      result.push(node)
-      return result
-    }
-
-    result.push(node)
-    return result
-  }, [])
-}
-
-/**
- * Rehype prism plugin generator that highlights code blocks with refractor (prismjs)
- *
- * Pass in your own refractor object with the required languages registered:
- * https://github.com/wooorm/refractor#refractorregistersyntax
- *
- * @param {import('refractor/lib/core').Refractor} refractor
- * @return {import('unified').Plugin<[Options?], Root>}
- */
-const rehypePrismGenerator = (refractor) => {
-  return (options = {}) => {
-    return (tree) => {
-      // @ts-ignore
-      visit(tree, 'element', visitor)
-    }
-
-    /**
-     * @param {Node} node
-     * @param {number} index
-     * @param {Parent} parent
-     */
-    function visitor(node, index, parent) {
-      if (!parent || parent.tagName !== 'pre' || node.tagName !== 'code') {
-        return
-      }
-
-      const lang = getLanguage(node)
-
-      /** @type {string} */
-      // @ts-ignore
-      let meta = node.data && node.data.meta ? node.data.meta : ''
-      node.properties.className = node.properties.className || []
-      node.properties.className.push('code-highlight')
-
-      let refractorRoot
-      let langError = false
-
-      // Syntax highlight
-      if (lang) {
-        try {
-          // @ts-ignore
-          refractorRoot = refractor.highlight(toString(node), lang)
-          parent.properties.className = (parent.properties.className || []).concat(
-            'language-' + lang
-          )
-        } catch (err) {
-          if (options.ignoreMissing && /Unknown language/.test(err.message)) {
-            langError = true
-            refractorRoot = node.children
-          } else {
-            throw err
-          }
-        }
-      } else {
-        refractorRoot = node.children
-      }
-
-      // @ts-ignore
-      refractorRoot = getNodePosition(refractorRoot)
-      refractorRoot.children = splitTextByLine(refractorRoot.children)
-
-      const shouldHighlightLine = calculateLinesToHighlight(meta)
-      const startingLineNumber = calculateStartingLine(meta)
-      // @ts-ignore
-      const codeLineArray = splitLine(toString(node))
-
-      for (const [i, line] of codeLineArray.entries()) {
-        // Code lines
-        if (
-          meta.toLowerCase().includes('showLineNumbers'.toLowerCase()) ||
-          options.showLineNumbers
-        ) {
-          line.properties.line = [(i + startingLineNumber).toString()]
-          line.properties.className.push('line-number')
-        }
-
-        // Line highlight
-        if (shouldHighlightLine(i)) {
-          line.properties.className.push('highlight-line')
-        }
-
-        // @ts-ignore
-        if (lang === 'diff' && toString(line).substring(0, 1) === '-') {
-          line.properties.className.push('deleted')
-          // @ts-ignore
-        } else if (lang === 'diff' && toString(line).substring(0, 1) === '+') {
-          line.properties.className.push('inserted')
-        }
-
-        // Syntax highlight
-        const treeExtract = filter(
-          refractorRoot,
-          (node) => node.position.start.line <= i + 1 && node.position.end.line >= i + 1
-        )
-        line.children = treeExtract.children
-      }
-
-      node.children = codeLineArray
-    }
-  }
-}
-
-/**
- * Rehype prism plugin that highlights code blocks with refractor (prismjs)
- * This supports all the languages and should be used on the server side.
- *
- * Consider using rehypePrismCommon or rehypePrismGenerator to generate a plugin
- * that supports your required languages.
- */
-const rehypePrism = rehypePrismGenerator(refractorAll)
-
-/**
- * Rehype prism plugin that highlights code blocks with refractor (prismjs)
- * Supported languages: https://github.com/wooorm/refractor#data
- *
- * Consider using rehypePrismGenerator to generate a plugin
- * that supports your required languages.
- */
-const rehypePrismCommon = rehypePrismGenerator(refractorCommon)
+import rehypePrismGenerator from './src/generator.js'
+import rehypePrismCommon from './src/common.js'
+import rehypePrism from './src/all.js'
 
 export { rehypePrismGenerator, rehypePrismCommon }
 export default rehypePrism

Plik diff jest za duży
+ 8226 - 1
package-lock.json


+ 13 - 0
src/all.js

@@ -0,0 +1,13 @@
+import { refractor as refractorAll } from 'refractor/lib/all.js'
+import rehypePrismGenerator from './generator.js'
+
+/**
+ * Rehype prism plugin that highlights code blocks with refractor (prismjs)
+ * This supports all the languages and should be used on the server side.
+ *
+ * Consider using rehypePrismCommon or rehypePrismGenerator to generate a plugin
+ * that supports your required languages.
+ */
+const rehypePrismAll = rehypePrismGenerator(refractorAll)
+
+export default rehypePrismAll

+ 13 - 0
src/common.js

@@ -0,0 +1,13 @@
+import { refractor as refractorCommon } from 'refractor/lib/common.js'
+import rehypePrismGenerator from './generator.js'
+
+/**
+ * Rehype prism plugin that highlights code blocks with refractor (prismjs)
+ * Supported languages: https://github.com/wooorm/refractor#data
+ *
+ * Consider using rehypePrismGenerator to generate a plugin
+ * that supports your required languages.
+ */
+const rehypePrismCommon = rehypePrismGenerator(refractorCommon)
+
+export default rehypePrismCommon

+ 261 - 0
src/generator.js

@@ -0,0 +1,261 @@
+/**
+ * @typedef {import('hast').Node & {properties: Object<any, any>}} Node
+ * @typedef {import('hast').Parent & {properties: Object<any, any>}} Parent
+ * @typedef {import('hast').Root} Root
+ * @typedef Options options
+ *   Configuration.
+ * @property {boolean} [showLineNumbers]
+ *   Set `showLineNumbers` to `true` to always display line number
+ * @property {boolean} [ignoreMissing]
+ *   Set `ignoreMissing` to `true` to ignore unsupported languages and line highlighting when no language is specified
+ */
+
+import { visit } from 'unist-util-visit'
+import { toString } from 'hast-util-to-string'
+import { toHtml } from 'hast-util-to-html'
+import { filter } from 'unist-util-filter'
+import { unified } from 'unified'
+import parse from 'rehype-parse'
+import rangeParser from 'parse-numeric-range'
+
+/**
+ * @param {Node} node
+ * @return {string|null}
+ */
+const getLanguage = (node) => {
+  const className = node.properties.className || []
+
+  for (const classListItem of className) {
+    if (classListItem.slice(0, 9) === 'language-') {
+      return classListItem.slice(9).toLowerCase()
+    }
+  }
+  return null
+}
+
+/**
+ * Create a closure that determines if we have to highlight the given index
+ *
+ * @param {string} meta
+ * @return { (index:number) => boolean }
+ */
+const calculateLinesToHighlight = (meta) => {
+  const RE = /{([\d,-]+)}/
+  // Remove space between {} e.g. {1, 3}
+  const parsedMeta = meta
+    .split(',')
+    .map((str) => str.trim())
+    .join()
+  if (RE.test(parsedMeta)) {
+    const strlineNumbers = RE.exec(parsedMeta)[1]
+    const lineNumbers = rangeParser(strlineNumbers)
+    return (index) => lineNumbers.includes(index + 1)
+  } else {
+    return () => false
+  }
+}
+
+/**
+ * Check if we want to start the line numbering from a given number or 1
+ * showLineNumbers=5, will start the numbering from 5
+ * @param {string} meta
+ * @returns {number}
+ */
+const calculateStartingLine = (meta) => {
+  const RE = /showLineNumbers=(?<lines>\d+)/i
+  // pick the line number after = using a named capturing group
+  if (RE.test(meta)) {
+    const {
+      groups: { lines },
+    } = RE.exec(meta)
+    return Number(lines)
+  }
+  return 1
+}
+
+/**
+ * Split line to div node with className `code-line`
+ *
+ * @param {string} text
+ * @return {Node[]}
+ */
+const splitLine = (text) => {
+  // Xdm Markdown parser every code line with \n
+  const textArray = text.split(/\n/)
+
+  // Remove last line \n which results in empty array
+  if (textArray[textArray.length - 1].trim() === '') {
+    textArray.pop()
+  }
+
+  // Empty array are actually line segments so we convert them back to newlines
+  return textArray.map((line) => {
+    return {
+      type: 'element',
+      tagName: 'span',
+      properties: { className: ['code-line'] },
+      children: [{ type: 'text', value: line }],
+    }
+  })
+}
+
+/**
+ * Split line to div node with className `code-line`
+ *
+ * @param {import('refractor').RefractorRoot} ast
+ * @return {Root}
+ */
+const getNodePosition = (ast) => {
+  // @ts-ignore
+  let html = toHtml(ast)
+  const hast = unified().use(parse, { emitParseErrors: true, fragment: true }).parse(html)
+  return hast
+}
+
+/**
+ * Split multiline text nodes into individual nodes with positioning
+ *
+ * @param {Parent['children']} ast
+ * @return {Parent['children']}
+ */
+const splitTextByLine = (ast) => {
+  //@ts-ignore
+  return ast.reduce((result, node) => {
+    if (node.type === 'text') {
+      if (node.value.indexOf('\n') === -1) {
+        result.push(node)
+        return result
+      }
+
+      const lines = node.value.split('\n')
+      for (const [i, line] of lines.entries()) {
+        result.push({
+          type: 'text',
+          value: i === lines.length - 1 ? line : line + '\n',
+          position: {
+            start: { line: node.position.start.line + i },
+            end: { line: node.position.start.line + i },
+          },
+        })
+      }
+
+      return result
+    }
+
+    if (node.children) {
+      // @ts-ignore
+      node.children = splitTextByLine(node.children)
+      result.push(node)
+      return result
+    }
+
+    result.push(node)
+    return result
+  }, [])
+}
+
+/**
+ * Rehype prism plugin generator that highlights code blocks with refractor (prismjs)
+ *
+ * Pass in your own refractor object with the required languages registered:
+ * https://github.com/wooorm/refractor#refractorregistersyntax
+ *
+ * @param {import('refractor/lib/core').Refractor} refractor
+ * @return {import('unified').Plugin<[Options?], Root>}
+ */
+const rehypePrismGenerator = (refractor) => {
+  return (options = {}) => {
+    return (tree) => {
+      // @ts-ignore
+      visit(tree, 'element', visitor)
+    }
+
+    /**
+     * @param {Node} node
+     * @param {number} index
+     * @param {Parent} parent
+     */
+    function visitor(node, index, parent) {
+      if (!parent || parent.tagName !== 'pre' || node.tagName !== 'code') {
+        return
+      }
+
+      const lang = getLanguage(node)
+
+      /** @type {string} */
+      // @ts-ignore
+      let meta = node.data && node.data.meta ? node.data.meta : ''
+      node.properties.className = node.properties.className || []
+      node.properties.className.push('code-highlight')
+
+      let refractorRoot
+      let langError = false
+
+      // Syntax highlight
+      if (lang) {
+        try {
+          // @ts-ignore
+          refractorRoot = refractor.highlight(toString(node), lang)
+          parent.properties.className = (parent.properties.className || []).concat(
+            'language-' + lang
+          )
+        } catch (err) {
+          if (options.ignoreMissing && /Unknown language/.test(err.message)) {
+            langError = true
+            refractorRoot = node.children
+          } else {
+            throw err
+          }
+        }
+      } else {
+        refractorRoot = node.children
+      }
+
+      console.dir(refractorRoot, { depth: null })
+      // @ts-ignore
+      refractorRoot = getNodePosition(refractorRoot)
+      console.dir(refractorRoot, { depth: null })
+      refractorRoot.children = splitTextByLine(refractorRoot.children)
+
+      const shouldHighlightLine = calculateLinesToHighlight(meta)
+      const startingLineNumber = calculateStartingLine(meta)
+      // @ts-ignore
+      const codeLineArray = splitLine(toString(node))
+
+      for (const [i, line] of codeLineArray.entries()) {
+        // Code lines
+        if (
+          meta.toLowerCase().includes('showLineNumbers'.toLowerCase()) ||
+          options.showLineNumbers
+        ) {
+          line.properties.line = [(i + startingLineNumber).toString()]
+          line.properties.className.push('line-number')
+        }
+
+        // Line highlight
+        if (shouldHighlightLine(i)) {
+          line.properties.className.push('highlight-line')
+        }
+
+        // @ts-ignore
+        if (lang === 'diff' && toString(line).substring(0, 1) === '-') {
+          line.properties.className.push('deleted')
+          // @ts-ignore
+        } else if (lang === 'diff' && toString(line).substring(0, 1) === '+') {
+          line.properties.className.push('inserted')
+        }
+
+        // Syntax highlight
+        const treeExtract = filter(
+          refractorRoot,
+          (node) => node.position.start.line <= i + 1 && node.position.end.line >= i + 1
+        )
+        line.children = treeExtract.children
+      }
+
+      node.children = codeLineArray
+    }
+  }
+}
+
+export default rehypePrismGenerator

+ 1 - 1
tsconfig.json

@@ -1,5 +1,5 @@
 {
-  "include": ["index.js"],
+  "include": ["index.js", "src/*"],
   "compilerOptions": {
     "target": "ES2020",
     "lib": ["ES2020"],

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików