@curvenote/schema
Version:
Schema and markdown parser for @curvenote/editor
82 lines • 3.39 kB
JavaScript
import { nodeNames } from '../types';
import { createId } from '../utils';
import { determineCaptionKind } from './utils';
export function modifyTransactionToValidDocState(tr) {
const transactions = [];
function deleteNode(node, pos) {
transactions.push((next) => next.delete(pos, pos + node.nodeSize));
}
// State for walk
const takenIds = {};
const captionState = {
deleteNext: false,
kind: null,
};
// This checks if the ID has been seen or is invalid, and gives a replacement
function ensureIdIsValidOrCreateId(id) {
const taken = id ? takenIds[id] : true;
if (!id || taken)
return { replace: true, id: createId() };
takenIds[id] = true;
return { replace: false, id };
}
tr.doc.content.descendants((node, pos) => {
switch (node.type.name) {
case nodeNames.figure: {
captionState.deleteNext = false;
captionState.kind = determineCaptionKind(node);
if (node.childCount === 0) {
// Delete the empty figure!
deleteNode(node, pos);
return false;
}
// Check that the ID works
const { id } = node.attrs;
const nextId = ensureIdIsValidOrCreateId(id);
if (nextId.replace) {
transactions.push((next) => next.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { id: nextId.id })));
}
return true;
}
case nodeNames.figcaption: {
if (captionState.deleteNext) {
// Delete the second figure caption
transactions.push((next) => next.delete(pos, pos + node.nodeSize));
}
else {
const { kind } = node.attrs;
const { kind: nextKind } = captionState; // Need to get access to the **value**, not the reference
if (kind !== nextKind) {
// Change the kind and id of the caption
transactions.push((next) => next.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { kind: nextKind })));
}
}
captionState.deleteNext = true;
return false;
}
case nodeNames.heading:
case nodeNames.equation: {
const { id } = node.attrs;
const nextId = ensureIdIsValidOrCreateId(id);
if (nextId.replace) {
transactions.push((next) => next.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { id: nextId.id })));
}
return false;
}
case nodeNames.table: {
if (node.childCount === 0)
deleteNode(node, pos);
return false;
}
// Continue to search
case nodeNames.aside:
case nodeNames.callout:
return true;
default:
return false;
}
});
const modified = transactions.reverse().reduce((next, chain) => chain(next), tr);
return modified;
}
//# sourceMappingURL=modifyTransactions.js.map