UNPKG

@curvenote/schema

Version:

Schema and markdown parser for @curvenote/editor

182 lines 6.96 kB
import { DEFAULT_IMAGE_WIDTH } from '../defaults'; import { nodeNames } from '../types'; import { clamp, createId } from '../utils'; export const getImageWidth = (width) => { if (typeof width === 'number') { return clamp(width, 10, 100); } const widthNum = Number.parseInt((width !== null && width !== void 0 ? width : String(DEFAULT_IMAGE_WIDTH)).replace('%', ''), 10); return clamp(widthNum || DEFAULT_IMAGE_WIDTH, 10, 100); }; export 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; } export function readBooleanDomAttr(dom, attr) { return readBooleanAttr(dom.getAttribute(attr)); } export function convertToBooleanAttribute(value) { return value ? '' : undefined; } export const getNumberedDefaultAttrs = () => ({ id: { default: null }, label: { default: null }, numbered: { default: false }, }); export function getAttr(dom, name, defaultValue = '') { var _a; return (_a = dom.getAttribute(name)) !== null && _a !== void 0 ? _a : defaultValue; } export 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, }; } export function setNumberedAttrs(attrs) { return { id: attrs.id || undefined, numbered: convertToBooleanAttribute(attrs.numbered), label: attrs.label || undefined, }; } /** * @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 */ export 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; } // TODO query the table node for it's width export const TOTAL_TABLE_WIDTH = 886; export function renderPColumn(width) { if (width === 1) return `p{\\dimexpr \\linewidth-2\\tabcolsep}`; return `p{\\dimexpr ${width.toFixed(3)}\\linewidth-2\\tabcolsep}`; } /** * given a table node, return the column widths * * @param node - node.type.name === 'table' * @returns */ export 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 = 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 }; } /** 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. */ export function hasFancyTable(node) { let hasRowspan = false; let hasColspan = false; node.descendants((n) => { if (n.type.name === nodeNames.table_cell || n.type.name === 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; } export 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 : createId(); state.mdastSnippets[id] = state.mdastSerializer(node); return id; } export 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; } // TODO: this is directly from mystjs - we should export from there instead export function normalizeLabel(label) { if (!label) return undefined; const identifier = label .replace(/[\t\n\r ]+/g, ' ') .trim() .toLowerCase(); return { identifier, label }; } /** * Take a node and return a single flattened text value from value/children */ export function flattenValues(node) { const { value, children } = node; if (value != null) { return value; } if (children) { return children.reduce((out, child) => `${out}${flattenValues(child)}`, ''); } return ''; } //# sourceMappingURL=utils.js.map