diff --git a/package.json b/package.json index 7385059..8ab5abe 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,16 @@ "rehype-slug": "^3.0.0", "rehype-stringify": "^8.0.0", "remark-breaks": "^1.0.5", + "remark-footnotes": "^1.0.0", "remark-frontmatter": "^2.0.0", "remark-math": "^2.0.1", "remark-parse": "^8.0.2", "remark-rehype": "^7.0.0", + "remark-shortcodes": "^0.3.1", "to-vfile": "^6.1.0", "unified": "^9.0.0", "unist-builder": "^2.0.3", + "unist-util-filter": "^2.0.2", "unist-util-inspect": "^6.0.0", "unist-util-remove": "^2.0.0", "unist-util-select": "^3.0.1", diff --git a/src/index.ts b/src/index.ts index a42fd87..7e9c626 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import unified, { Processor } from 'unified'; import { replace as handleReplace, ReplaceRule } from './plugins/replace'; import markdown from './revive-parse'; import html from './revive-rehype'; +import { debug } from './utils/debug'; export interface StringifyMarkdownOptions { style?: string | string[]; @@ -24,7 +25,10 @@ export function VFM({ language = 'en', replace = undefined, }: StringifyMarkdownOptions = {}): Processor { - const processor = unified().use(markdown).use(html); + const processor = unified() + .use(markdown) + .data('settings', { position: false }) + .use(html); if (replace) { processor.use(handleReplace, { rules: replace }); } @@ -41,6 +45,7 @@ export function stringify( options: StringifyMarkdownOptions = {}, ): string { const processor = VFM(options); - - return String(processor.processSync(markdownString)); + const vfile = processor.processSync(markdownString); + debug(vfile.data); + return String(vfile); } diff --git a/src/plugins/metadata.ts b/src/plugins/metadata.ts index 53b7000..e615320 100644 --- a/src/plugins/metadata.ts +++ b/src/plugins/metadata.ts @@ -1,18 +1,18 @@ -import {safeLoad as yaml} from 'js-yaml'; -import {FrontmatterContent} from 'mdast'; +import { safeLoad as yaml } from 'js-yaml'; +import { FrontmatterContent, Literal } from 'mdast'; import toString from 'mdast-util-to-string'; -import {Node} from 'unist'; -import {select} from 'unist-util-select'; +import { Node } from 'unist'; +import { select } from 'unist-util-select'; import visit from 'unist-util-visit'; -import {VFile} from 'vfile'; +import { VFile } from 'vfile'; interface File extends VFile { - data: {title: string}; + data: { title: string; toc: boolean }; } // https://github.com/Symbitic/remark-plugins/blob/master/packages/remark-meta/src/index.js -export function attacher() { +export function plugin() { return (tree: Node, file: File) => { const heading = select('heading', tree); if (heading) { @@ -25,5 +25,12 @@ export function attacher() { ...yaml(node.value), }; }); + + file.data.toc = false; + visit(tree, ['shortcode'], (node) => { + if (node.identifier !== 'toc') return; + console.log(node); + file.data.toc = true; + }); }; } diff --git a/src/plugins/toc.ts b/src/plugins/toc.ts new file mode 100644 index 0000000..46c147b --- /dev/null +++ b/src/plugins/toc.ts @@ -0,0 +1,13 @@ +import shortcodes from 'remark-shortcodes'; +import { Node } from 'unist'; +import remove from 'unist-util-remove'; + +const keepToC = () => (tree: Node) => { + remove(tree, { cascade: false }, (node: any) => { + return node.type === 'shortcode' && node.identifier !== 'toc'; + }); +}; + +export const plugin = { + plugins: [[shortcodes, { startBlock: '[[', endBlock: ']]' }], keepToC], +}; diff --git a/src/revive-parse.ts b/src/revive-parse.ts index 8f5cb83..8f3bedf 100644 --- a/src/revive-parse.ts +++ b/src/revive-parse.ts @@ -1,21 +1,25 @@ import breaks from 'remark-breaks'; +import footnotes from 'remark-footnotes'; import frontmatter from 'remark-frontmatter'; import math from 'remark-math'; import markdown from 'remark-parse'; import unified from 'unified'; import { attacher as code } from './plugins/code'; import { attacher as fencedBlock } from './plugins/fenced-block'; -import { attacher as metadata } from './plugins/metadata'; +import { plugin as metadata } from './plugins/metadata'; import { attacher as ruby } from './plugins/ruby'; +import { plugin as toc } from './plugins/toc'; import { inspect } from './utils/debug'; export default [ - [markdown, { commonmark: false, footnotes: true }], + [markdown, { gfm: true, commonmark: true }], fencedBlock, breaks, + [footnotes, { inlineNotes: true }], code, ruby, math, + toc, frontmatter, metadata, inspect('mdast'), diff --git a/types/remark.d.ts b/types/remark.d.ts index 49db7f4..bc2f55e 100644 --- a/types/remark.d.ts +++ b/types/remark.d.ts @@ -4,8 +4,6 @@ declare namespace NodeJS { } } -declare module 'remark-math'; -declare module 'remark-breaks'; declare module 'rehype-raw' { import { Plugin } from 'unified'; const plugin: Plugin; @@ -17,17 +15,21 @@ declare module 'rehype-stringify' { const plugin: Plugin; export default plugin; } -declare module 'rehype-mathjax'; -declare module 'unist-util-remove'; -declare module 'rehype-katex'; -declare module 'rehype-slug'; + +declare module 'hast-util-find-and-replace'; +declare module 'remark-shortcodes'; +declare module 'hast-util-is-element'; declare module 'hastscript'; declare module 'mdast-util-to-hast/lib/all'; declare module 'mdast-util-to-string'; -declare module 'hast-util-find-and-replace'; -declare module 'hast-util-is-element'; - +declare module 'rehype-katex'; +declare module 'rehype-mathjax'; +declare module 'rehype-slug'; +declare module 'remark-breaks'; +declare module 'remark-footnotes'; +declare module 'remark-math'; declare module 'to-vfile'; +declare module 'unist-util-remove'; interface Tokenizer { ( diff --git a/yarn.lock b/yarn.lock index 93567e2..206ad49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2493,6 +2493,11 @@ flat@^4.1.0: dependencies: is-buffer "~2.0.3" +flatmap@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4" + integrity sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ= + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -5400,6 +5405,11 @@ remark-breaks@^1.0.5: resolved "https://registry.yarnpkg.com/remark-breaks/-/remark-breaks-1.0.5.tgz#e9785f8b174f45c05af542fbeb18354b766e1139" integrity sha512-lr8+TlJI273NjEqL27eUthPYPTCgXEj4NaLbnazS3bQaQL2FySlsbtgo52gE36fE1gWeQgkn1VdmWsoT+uA7FA== +remark-footnotes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-1.0.0.tgz#9c7a97f9a89397858a50033373020b1ea2aad011" + integrity sha512-X9Ncj4cj3/CIvLI2Z9IobHtVi8FVdUrdJkCNaL9kdX8ohfsi18DXHsCVd/A7ssARBdccdDb5ODnt62WuEWaM/g== + remark-frontmatter@^1.2.0: version "1.3.3" resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-1.3.3.tgz#67ec63c89da5a84bb793ecec166e11b4eb47af10" @@ -5470,6 +5480,11 @@ remark-rehype@^7.0.0: dependencies: mdast-util-to-hast "^9.1.0" +remark-shortcodes@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/remark-shortcodes/-/remark-shortcodes-0.3.1.tgz#e18949471797084e20d97a527475cbcfdea05cde" + integrity sha512-ornwmR9xHDtalUndKIFcAM14Z+OoKr8CRIdJpc1YFDxTHmVBBAu8ORmE9oP5fDuOWEu+r6YLyb5fCKScc4Gung== + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -6522,6 +6537,14 @@ unist-builder@^2.0.0, unist-builder@^2.0.3: resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== +unist-util-filter@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unist-util-filter/-/unist-util-filter-2.0.2.tgz#b6cc310691d4b738782bdae3a7945f3d916a0e96" + integrity sha512-yHcR4YpvFzKx8EN9i2HhTORIR3zYC6YwsW6b2nuk8EI/3gps2YC008S+KJRyNuPViqScYQdrI67ceOryNL9EUQ== + dependencies: + flatmap "0.0.3" + unist-util-is "^4.0.0" + unist-util-find-after@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz#5c65fcebf64d4f8f496db46fa8fd0fbf354b43e6"