UNPKG

myst-to-docx

Version:

Export from a MyST Markdown document to Microsoft Word (*.docx)

81 lines (80 loc) 2.52 kB
import { RuleId, fileError, fileWarn } from 'myst-common'; import { Paragraph, TextRun } from 'docx'; import { defaultHandlers } from './schema.js'; export class DocxSerializer { file; data; handlers; options; children; numbering; footnotes = {}; current = []; frontmatter = {}; constructor(file, options, frontmatter) { this.file = file; this.data = {}; this.handlers = options.handlers ?? defaultHandlers; this.options = options ?? {}; this.children = []; this.numbering = []; this.frontmatter = frontmatter ?? {}; } render(node, parent) { if (!this.handlers[node.type]) { fileError(this.file, `Node of type "${node.type}" is not supported by docx renderer`, { node, source: 'myst-to-docx:render', ruleId: RuleId.docxRenders, }); return; } this.handlers[node.type](this, node, parent); } renderChildren(parent, paragraphOpts, runOpts) { if (!('children' in parent)) { const node = parent; fileWarn(this.file, `Expected children for node of type ${node.type}`, { node, ruleId: RuleId.docxRenders, }); return; } parent.children.forEach((node) => { if (paragraphOpts) this.addParagraphOptions(paragraphOpts); if (runOpts) this.addRunOptions(runOpts); this.render(node, parent); }); } addParagraphOptions(opts) { this.data.nextParagraphOpts = { ...this.data?.nextParagraphOpts, ...opts }; } addRunOptions(opts) { this.data.nextRunOpts = { ...this.data.nextRunOpts, ...opts }; } text(text, opts) { if (!text) return; this.current.push(new TextRun({ text, ...this.data.nextRunOpts, ...opts })); delete this.data.nextRunOpts; } closeBlock(props, force = false) { if (this.current.length === 0 && !props && !force) { delete this.data.nextParagraphOpts; return; } const paragraph = new Paragraph({ children: this.current, ...this.data.nextParagraphOpts, ...props, }); this.current = []; delete this.data.nextParagraphOpts; this.children.push(paragraph); } blankLine(props) { this.closeBlock(props, true); } }