UNPKG

@curvenote/schema

Version:

Schema and markdown parser for @curvenote/editor

211 lines 9.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toTex = exports.toMarkdown = void 0; const utils_1 = require("../serialize/tex/utils"); const types_1 = require("./types"); const utils_2 = require("../process/utils"); const utils_3 = require("./utils"); const types_2 = require("../types"); const code_1 = require("./code"); const utils_4 = require("../serialize/markdown/utils"); const figure = { group: types_1.NodeGroups.block, content: types_1.NodeGroups.insideFigure, isolating: true, attrs: Object.assign(Object.assign({}, (0, utils_3.getNumberedDefaultAttrs)()), { align: { default: 'center' }, multipage: { default: false }, landscape: { default: false }, fullpage: { default: false } }), toDOM(node) { const { align, multipage, landscape, fullpage } = node.attrs; return [ 'figure', Object.assign(Object.assign({}, (0, utils_3.setNumberedAttrs)(node.attrs)), { align, multipage, landscape, fullpage }), 0, ]; }, parseDOM: [ { tag: 'figure', getAttrs(dom) { var _a; return Object.assign(Object.assign({}, (0, utils_3.getNumberedAttrs)(dom)), { align: (_a = dom.getAttribute('align')) !== null && _a !== void 0 ? _a : 'center', multipage: (0, utils_3.readBooleanDomAttr)(dom, 'multipage'), landscape: (0, utils_3.readBooleanDomAttr)(dom, 'landscape'), fullpage: (0, utils_3.readBooleanDomAttr)(dom, 'fullpage') }); }, }, ], attrsFromMyst: (token) => { var _a; const match = (_a = token.class) === null || _a === void 0 ? void 0 : _a.match(/align-(left|right|center)/); return { id: token.identifier || null, label: null, numbered: token.enumerated || false, align: (match ? match[1] : 'center'), multipage: false, landscape: false, fullpage: false, }; }, toMyst: (props, options) => { var _a, _b, _c, _d, _e; let containerKind = 'figure'; (_a = props.children) === null || _a === void 0 ? void 0 : _a.forEach((child) => { if (child.type === 'image' || child.type === 'table') { child.align = props.align || undefined; } if (child.type === 'table') { containerKind = 'table'; } }); const localizedId = (_e = (_d = (_b = options.localizeId) === null || _b === void 0 ? void 0 : _b.call(options, (_c = props.id) !== null && _c !== void 0 ? _c : '')) !== null && _d !== void 0 ? _d : props.id) !== null && _e !== void 0 ? _e : ''; return Object.assign(Object.assign({ type: 'container', kind: containerKind }, (0, utils_3.normalizeLabel)(localizedId)), { enumerated: (0, utils_3.readBooleanAttr)(props.numbered), class: props.align ? `align-${props.align}` : undefined, children: (props.children || []) }); }, }; const toMarkdown = (state, node, parent, index) => { var _a, _b, _c, _d, _e, _f, _g; state.ensureNewLine(); const kind = (0, utils_2.determineCaptionKind)(node); const { id } = node.attrs; // TODO: Translate between callout/admonition const caption = (0, utils_3.getFirstChildWithName)(node, types_2.nodeNames.figcaption); state.nextCaptionId = (_d = (_c = (_b = (_a = state.options).localizeId) === null || _b === void 0 ? void 0 : _b.call(_a, id !== null && id !== void 0 ? id : '')) !== null && _c !== void 0 ? _c : id) !== null && _d !== void 0 ? _d : undefined; switch (kind) { case types_1.CaptionKind.fig: { const image = (0, utils_3.getFirstChildWithName)(node, [types_2.nodeNames.image, types_2.nodeNames.iframe]); if (!image) return; const { src, align, width } = image === null || image === void 0 ? void 0 : image.attrs; const href = (_g = (_f = (_e = state.options).localizeImageSrc) === null || _f === void 0 ? void 0 : _f.call(_e, src)) !== null && _g !== void 0 ? _g : src; if (image.type.name === types_2.nodeNames.iframe) { state.render(image, parent, index); return; } state.write(`\`\`\`{figure} ${href}\n`); const opts = { name: state.nextCaptionId, align, width: `${width}%` }; (0, utils_4.writeDirectiveOptions)(state, opts); if (caption) { state.renderInline(caption); state.ensureNewLine(); } state.write('```'); state.closeBlock(node); return; } case types_1.CaptionKind.eq: { state.renderContent(node); return; } case types_1.CaptionKind.table: { const table = (0, utils_3.getFirstChildWithName)(node, [types_2.nodeNames.table]); if (table && (0, utils_3.hasFancyTable)(table)) { (0, utils_3.writeMdastSnippet)(state, node); return; } state.nextTableCaption = caption; if (table) state.render(table, parent, index); state.closeBlock(node); return; } case types_1.CaptionKind.code: { const code = (0, utils_3.getFirstChildWithName)(node, [types_2.nodeNames.code_block]); // TODO: add a figure caption for code if (code) (0, code_1.toMarkdown)(state, code, node, index); state.closeBlock(node); return; } default: console.log(`Unknown figure kind: "${kind}", id=${id}, children=${node.childCount}`); return; } }; exports.toMarkdown = toMarkdown; function nodeToCommand(node) { const kind = (0, utils_2.determineCaptionKind)(node); switch (kind) { case types_1.CaptionKind.fig: return node.attrs.fullpage ? 'figure*' : 'figure'; case types_1.CaptionKind.table: return node.attrs.fullpage ? 'table*' : 'table'; case types_1.CaptionKind.code: // TODO full width code return 'code'; case types_1.CaptionKind.eq: return 'figure'; // not sure what to do here. default: return 'figure'; } } function nodeToLaTeXOptions(node) { const kind = (0, utils_2.determineCaptionKind)(node); switch (kind) { case types_1.CaptionKind.fig: case types_1.CaptionKind.table: return '!htbp'; case types_1.CaptionKind.code: return 'H'; case types_1.CaptionKind.eq: default: return undefined; } } function figureContainsTable(node) { const table = node.content.content.find((n) => n.type.name === types_2.nodeNames.table); return table; } exports.toTex = (0, utils_1.createLatexStatement)((state, node) => { // if the figure is in a table, skip to child content if (state.isInTable) return null; // if figure contains a table, we need find out which table environment to use state.containsTable = false; const table = figureContainsTable(node); let tableInfo; if (table && node.attrs.multipage) { state.containsTable = true; tableInfo = (0, utils_3.getColumnWidths)(table); } let before; let after; if (node.attrs.landscape) { // requires pdflscape package to be loaded before = '\\begin{landscape}'; after = '\\end{landscape}'; } // TODO for longtable to work with two columns we need to flip out to single column first // and then back to multi column, if we were in multicolumn mode // Q: we can know if we are in a two column mode from the template we are using, but how is this made available at this level? return { command: state.containsTable && node.attrs.multipage ? 'longtable' : nodeToCommand(node), commandOpts: state.containsTable && tableInfo ? tableInfo.columnSpec : undefined, bracketOpts: state.containsTable ? undefined : nodeToLaTeXOptions(node), before, after, }; }, (state, node) => { var _a, _b, _c, _d; // if the figure is in a table, skip to child content if (state.isInTable) { state.renderContent(node); return; } const { numbered, id, multipage } = node.attrs; const localId = (_d = (_c = (_b = (_a = state.options).localizeId) === null || _b === void 0 ? void 0 : _b.call(_a, id !== null && id !== void 0 ? id : '')) !== null && _c !== void 0 ? _c : id) !== null && _d !== void 0 ? _d : undefined; // TODO: Based on align attr // may have to modify string returned by state.renderContent(n); // https://tex.stackexchange.com/questions/91566/syntax-similar-to-centering-for-right-and-left // centering does not work in a longtable environment if (!multipage || !state.containsTable) state.write('\\centering'); state.ensureNewLine(); // Pass the relevant information to the child nodes state.nextCaptionNumbered = numbered; state.nextCaptionId = localId; state.longFigure = multipage; state.renderContent(node); state.longFigure = undefined; state.containsTable = false; }); exports.default = figure; //# sourceMappingURL=figure.js.map