@curvenote/schema
Version:
Schema and markdown parser for @curvenote/editor
124 lines • 4.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformNumericalFootnotes = exports.convertToMdastSnippet = exports.convertToMdast = exports.nodeToMdast = void 0;
const prosemirror_model_1 = require("prosemirror-model");
const mystjs_1 = require("mystjs");
const document_1 = require("./document");
const types_1 = require("../../types");
const schemas_1 = require("../../schemas");
const utils_1 = require("../../utils");
/**
* This uses the DOMSerializer from prosemirror-model to serialize to html
* The document used is a fake one that is passed to react.
*/
function getSerializer(schema) {
const nodes = Object.fromEntries(Object.entries(schema.nodes)
.map(([k, nodeType]) => {
const { toDOM } = nodeType.spec;
if (!toDOM)
return undefined;
const wrapper = (node) => {
const spec = toDOM(node);
return [`${node.type.name} ${spec[0]}`, ...spec.slice(1)];
};
return [k, wrapper];
})
.filter((v) => v));
// We must include the text node!
if (!nodes.text)
nodes.text = (node) => node.text;
const marks = Object.fromEntries(Object.entries(schema.marks)
.map(([k, markType]) => {
const { toDOM } = markType.spec;
if (!toDOM)
return undefined;
const wrapper = (mark, inline) => {
const spec = toDOM(mark, inline);
return [`${mark.type.name} ${spec[0]}`, ...spec.slice(1)];
};
return [k, wrapper];
})
.filter((v) => v));
return new prosemirror_model_1.DOMSerializer(nodes, marks);
}
function nodeToMdast(fragment, schema, opts) {
if (fragment.length === 0)
return [];
return fragment.map((node) => {
if (node instanceof document_1.Node) {
const children = nodeToMdast(node.children, schema, opts);
const props = Object.assign(Object.assign({ key: node.id, tag: node.tag, name: node.name }, node.attrs), { children });
if (node.name in types_1.nodeNames) {
return schema.nodes[node.name].spec.toMyst(props, opts);
}
if (node.name in types_1.markNames) {
return schema.marks[node.name].spec.toMyst(props, opts);
}
throw new Error(`Node for "${node.name}" is not defined.`);
}
const textNode = { type: 'text', value: node.text };
return textNode;
});
}
exports.nodeToMdast = nodeToMdast;
function convertToMdast(node, opts) {
const schema = (0, schemas_1.getSchema)(opts.useSchema || 'full');
const serializer = getSerializer(schema);
const dom = serializer.serializeFragment(node.content, {
document: (0, document_1.createDocument)(),
});
const root = { type: 'root', children: nodeToMdast(dom.children, schema, opts) };
const footnotes = (0, mystjs_1.selectAll)('inlineFootnote', root);
const footnoteDefinitions = [];
footnotes.forEach((footnote) => {
const id = (0, utils_1.createId)();
footnoteDefinitions.push({
type: 'footnoteDefinition',
identifier: id,
label: id,
children: footnote.children,
});
delete footnote.children;
const ref = footnote;
ref.type = 'footnoteReference';
ref.identifier = id;
ref.label = id;
});
root.children.push(...footnoteDefinitions);
return root;
}
exports.convertToMdast = convertToMdast;
function convertToMdastSnippet(node, opts) {
var _a, _b;
if (node.type.name === 'doc') {
throw new Error('The requested mdast snippet is a document, use convertToMdast.');
}
// If the node is not a top level, wrap it in a document and return that!
const schema = (0, schemas_1.getSchema)(opts.useSchema || 'full');
const { doc } = schema.nodes;
const wrapped = doc.create({}, [node]);
return (_b = (_a = convertToMdast(wrapped, opts)) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b[0];
}
exports.convertToMdastSnippet = convertToMdastSnippet;
function transformNumericalFootnotes(root) {
const defLookup = {};
const defs = (0, mystjs_1.selectAll)('footnoteDefinition', root);
defs.forEach((def) => {
defLookup[def.identifier] = def;
});
const refs = (0, mystjs_1.selectAll)('footnoteReference', root);
refs.forEach((ref, index) => {
const refDef = defLookup[ref.identifier];
let id = String(index + 1);
if (refDef.identifier !== ref.identifier) {
id = refDef.identifier;
}
refDef.identifier = id;
refDef.label = id;
ref.identifier = id;
ref.label = id;
});
return root;
}
exports.transformNumericalFootnotes = transformNumericalFootnotes;
//# sourceMappingURL=convertToMdast.js.map
;