@curvenote/schema
Version:
Schema and markdown parser for @curvenote/editor
201 lines • 8.17 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.flattenValues = exports.normalizeLabel = exports.writeMdastSnippet = exports.addMdastSnippet = exports.hasFancyTable = exports.getColumnWidths = exports.renderPColumn = exports.TOTAL_TABLE_WIDTH = exports.getFirstChildWithName = exports.setNumberedAttrs = exports.getNumberedAttrs = exports.getAttr = exports.getNumberedDefaultAttrs = exports.convertToBooleanAttribute = exports.readBooleanDomAttr = exports.readBooleanAttr = exports.getImageWidth = void 0;
const defaults_1 = require("../defaults");
const types_1 = require("../types");
const utils_1 = require("../utils");
const getImageWidth = (width) => {
if (typeof width === 'number') {
return (0, utils_1.clamp)(width, 10, 100);
}
const widthNum = Number.parseInt((width !== null && width !== void 0 ? width : String(defaults_1.DEFAULT_IMAGE_WIDTH)).replace('%', ''), 10);
return (0, utils_1.clamp)(widthNum || defaults_1.DEFAULT_IMAGE_WIDTH, 10, 100);
};
exports.getImageWidth = getImageWidth;
function readBooleanAttr(val) {
if (val == null)
return false;
if (typeof val === 'boolean')
return val;
if ((val === null || val === void 0 ? void 0 : val.toLowerCase()) === 'false')
return false;
return true;
}
exports.readBooleanAttr = readBooleanAttr;
function readBooleanDomAttr(dom, attr) {
return readBooleanAttr(dom.getAttribute(attr));
}
exports.readBooleanDomAttr = readBooleanDomAttr;
function convertToBooleanAttribute(value) {
return value ? '' : undefined;
}
exports.convertToBooleanAttribute = convertToBooleanAttribute;
const getNumberedDefaultAttrs = () => ({
id: { default: null },
label: { default: null },
numbered: { default: false },
});
exports.getNumberedDefaultAttrs = getNumberedDefaultAttrs;
function getAttr(dom, name, defaultValue = '') {
var _a;
return (_a = dom.getAttribute(name)) !== null && _a !== void 0 ? _a : defaultValue;
}
exports.getAttr = getAttr;
function getNumberedAttrs(dom) {
var _a, _b;
return {
id: (_a = dom.getAttribute('id')) !== null && _a !== void 0 ? _a : null,
numbered: readBooleanDomAttr(dom, 'numbered'),
label: (_b = dom.getAttribute('label')) !== null && _b !== void 0 ? _b : null,
};
}
exports.getNumberedAttrs = getNumberedAttrs;
function setNumberedAttrs(attrs) {
return {
id: attrs.id || undefined,
numbered: convertToBooleanAttribute(attrs.numbered),
label: attrs.label || undefined,
};
}
exports.setNumberedAttrs = setNumberedAttrs;
/**
* @param node ProsemirrorNode
* @param name Name of the node(s) to find
* @param descend go through all children of the node, default=false is only direct children
* @returns The first node with the name found
*/
function getFirstChildWithName(node, name, descend = false) {
const names = typeof name === 'string' ? new Set([name]) : new Set(name);
let child = null;
node.descendants((n) => {
if (!child && names.has(n.type.name)) {
child = n;
}
return descend;
});
return child;
}
exports.getFirstChildWithName = getFirstChildWithName;
// TODO query the table node for it's width
exports.TOTAL_TABLE_WIDTH = 886;
function renderPColumn(width) {
if (width === 1)
return `p{\\dimexpr \\linewidth-2\\tabcolsep}`;
return `p{\\dimexpr ${width.toFixed(3)}\\linewidth-2\\tabcolsep}`;
}
exports.renderPColumn = renderPColumn;
/**
* given a table node, return the column widths
*
* @param node - node.type.name === 'table'
* @returns
*/
function getColumnWidths(node) {
var _a, _b, _c;
// TODO: unsure about rowspans
let bestMaybeWidths = [];
let mostNonNulls = 0;
for (let i = 0; i < node.content.content.length; i += 1) {
const row = node.content.content[i];
const maybeWidths = row.content.content.reduce((acc, cell) => {
var _a, _b, _c;
const colwidth = new Array((_b = (_a = cell.attrs) === null || _a === void 0 ? void 0 : _a.colspan) !== null && _b !== void 0 ? _b : 1).fill(((_c = cell.attrs) === null || _c === void 0 ? void 0 : _c.colwidth) ? cell.attrs.colwidth / cell.attrs.colspan : null);
return [...acc, ...colwidth];
}, []);
const nonNulls = maybeWidths.filter((maybeWidth) => maybeWidth > 0).length;
if (i === 0 || nonNulls >= mostNonNulls) {
mostNonNulls = nonNulls;
bestMaybeWidths = maybeWidths;
if (mostNonNulls === maybeWidths.length) {
break;
}
}
}
let widths;
if (mostNonNulls === bestMaybeWidths.length) {
widths = bestMaybeWidths;
}
else {
// need to fill in the null colwidths
const totalDefinedWidths = bestMaybeWidths.reduce((acc, cur) => (cur == null ? acc : acc + cur), 0);
const remainingSpace = exports.TOTAL_TABLE_WIDTH - totalDefinedWidths;
const nullCells = bestMaybeWidths.length - mostNonNulls;
const defaultWidth = Math.floor(remainingSpace / nullCells);
widths = bestMaybeWidths.map((w) => (w == null || w === 0 ? defaultWidth : w));
}
const total = widths.reduce((acc, cur) => acc + cur, 0);
const fractionalWidths = widths.map((w) => w / total);
const columnSpec = fractionalWidths.map((w) => renderPColumn(w)).join('');
const numColumns = widths.length > 0 ? widths.length : (_c = (_b = (_a = node === null || node === void 0 ? void 0 : node.content) === null || _a === void 0 ? void 0 : _a.firstChild) === null || _b === void 0 ? void 0 : _b.content.childCount) !== null && _c !== void 0 ? _c : 0;
return { widths: fractionalWidths, columnSpec, numColumns };
}
exports.getColumnWidths = getColumnWidths;
/** Given a node, return true if there is a fancy table descendent
*
* "fancy" means there are table_cells or table_headers with
* colspan or rowspan > 1.
*/
function hasFancyTable(node) {
let hasRowspan = false;
let hasColspan = false;
node.descendants((n) => {
if (n.type.name === types_1.nodeNames.table_cell || n.type.name === types_1.nodeNames.table_header) {
hasRowspan = hasRowspan || (n.attrs.rowspan && Number(n.attrs.rowspan) > 1);
hasColspan = hasColspan || (n.attrs.colspan && Number(n.attrs.colspan) > 1);
}
});
return hasRowspan || hasColspan;
}
exports.hasFancyTable = hasFancyTable;
function addMdastSnippet(state, node) {
var _a, _b, _c;
if (!state.mdastSnippets)
state.mdastSnippets = {};
if (!state.mdastSerializer)
return false;
const id = (_c = (_b = (_a = state.options).createMdastImportId) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : (0, utils_1.createId)();
state.mdastSnippets[id] = state.mdastSerializer(node);
return id;
}
exports.addMdastSnippet = addMdastSnippet;
function writeMdastSnippet(state, node) {
const mdastId = addMdastSnippet(state, node);
if (mdastId === false) {
// If the mdast writer isn't defined (it usually is!)
state.write('No mdast writer attached.');
state.closeBlock(node);
return false; // maybe better?
}
state.write(`\`\`\`{mdast} ${mdastId}`);
state.ensureNewLine();
state.write('```');
state.closeBlock(node);
return true;
}
exports.writeMdastSnippet = writeMdastSnippet;
// TODO: this is directly from mystjs - we should export from there instead
function normalizeLabel(label) {
if (!label)
return undefined;
const identifier = label
.replace(/[\t\n\r ]+/g, ' ')
.trim()
.toLowerCase();
return { identifier, label };
}
exports.normalizeLabel = normalizeLabel;
/**
* Take a node and return a single flattened text value from value/children
*/
function flattenValues(node) {
const { value, children } = node;
if (value != null) {
return value;
}
if (children) {
return children.reduce((out, child) => `${out}${flattenValues(child)}`, '');
}
return '';
}
exports.flattenValues = flattenValues;
//# sourceMappingURL=utils.js.map
;