UNPKG

@curvenote/schema

Version:

Schema and markdown parser for @curvenote/editor

136 lines 4.98 kB
import { MarkdownSerializerState } from 'prosemirror-markdown'; import { isPlainURL, backticksFor, wrapMark } from './utils'; import * as nodes from '../../nodes'; import { cleanWhitespaceChars } from '../clean'; import { toMdastSnippet } from '../mdast'; function mdPostProcess(md) { // Replace trailing newlines in code fences const post = md.replace(/\n\n```($|\n)/g, '\n```\n').replace(/```\n$/g, '```'); return post; } const mdNodes = { text(state, node) { var _a; state.text(cleanWhitespaceChars((_a = node.text) !== null && _a !== void 0 ? _a : '')); }, paragraph(state, node) { state.renderInline(node); state.closeBlock(node); }, heading: nodes.Heading.toMarkdown, blockquote(state, node) { state.wrapBlock('> ', null, node, () => state.renderContent(node)); }, code_block: nodes.Code.toMarkdown, horizontal_rule(state, node) { state.write(node.attrs.markup || '---'); state.closeBlock(node); }, hard_break(state, node, parent, index) { for (let i = index + 1; i < parent.childCount; i += 1) { if (parent.child(i).type !== node.type) { state.write('\\\n'); return; } } }, ordered_list(state, node) { const start = node.attrs.order || 1; const maxW = String(start + node.childCount - 1).length; const space = state.repeat(' ', maxW + 2); state.renderList(node, space, (i) => { const nStr = String(start + i); return `${state.repeat(' ', maxW - nStr.length) + nStr}. `; }); }, bullet_list(state, node) { state.renderList(node, ' ', () => `${node.attrs.bullet || '-'} `); }, list_item(state, node) { state.renderInline(node); }, // Presentational image: nodes.Image.toMarkdown, figure: nodes.Figure.toMarkdown, figcaption: nodes.Figcaption.toMarkdown, footnote: nodes.Footnote.toMarkdown, iframe: nodes.IFrame.toMarkdown, time: nodes.Time.toMarkdown, callout: nodes.Callout.toMarkdown, aside: nodes.Aside.toMarkdown, link_block: nodes.LinkBlock.toMarkdown, // Technical math: nodes.Math.toMarkdown, equation: nodes.Equation.toMarkdown, cite: nodes.Cite.toMarkdown, cite_group: nodes.CiteGroup.toMarkdown, mention: nodes.Mention.toMarkdown, // Tables table: nodes.Table.toMarkdown, // Dynamic variable: nodes.Variable.toMarkdown, display: nodes.Display.toMarkdown, dynamic: nodes.Dynamic.toMarkdown, range: nodes.Range.toMarkdown, switch: nodes.Switch.toMarkdown, button: nodes.Button.toMarkdown, }; const mdMarks = { em: { open: '*', close: '*', mixable: true, expelEnclosingWhitespace: true, }, strong: { open: '**', close: '**', mixable: true, expelEnclosingWhitespace: true, }, link: { open(state, mark, parent, index) { var _a, _b; const { options } = state; const href = (_b = (_a = options.localizeLink) === null || _a === void 0 ? void 0 : _a.call(options, mark.attrs.href)) !== null && _b !== void 0 ? _b : mark.attrs.href; return isPlainURL(mark, href, parent, index, 1) ? '<' : '['; }, close(state, mark, parent, index) { var _a, _b; const { options } = state; const href = (_b = (_a = options.localizeLink) === null || _a === void 0 ? void 0 : _a.call(options, mark.attrs.href)) !== null && _b !== void 0 ? _b : mark.attrs.href; return isPlainURL(mark, href, parent, index, -1) ? '>' : `](${state.esc(mark.attrs.href)}${mark.attrs.title ? ` ${state.quote(mark.attrs.title)}` : ''})`; }, }, code: { open(state, mark, parent, index) { return backticksFor(parent.child(index), -1); }, close(state, mark, parent, index) { return backticksFor(parent.child(index - 1), 1); }, escape: false, }, abbr: wrapMark('abbr', (state, mark) => (mark.attrs.title ? ` (${mark.attrs.title})` : '')), subscript: wrapMark('sub'), superscript: wrapMark('sup'), strikethrough: wrapMark('strike'), underline: wrapMark('u'), }; export function toMyst(doc, opts) { var _a; const defualtOpts = { tightLists: true }; const state = new MarkdownSerializerState(mdNodes, mdMarks, Object.assign(Object.assign({}, defualtOpts), opts)); state.mdastSerializer = (d) => toMdastSnippet(d, opts); state.renderContent(doc); const post = mdPostProcess(state.out); return { content: post, mdastSnippets: (_a = state.mdastSnippets) !== null && _a !== void 0 ? _a : {} }; } // TODO: GFM, CommonMark, etc! export function toMarkdown(doc, opts) { const myst = toMyst(doc, opts); return myst.content; } //# sourceMappingURL=index.js.map