@curvenote/schema
Version:
Schema and markdown parser for @curvenote/editor
153 lines • 6.43 kB
JavaScript
import { count as wordcount } from '@wordpress/wordcount';
import { ReferenceKind } from '../nodes/types';
import { nodeNames } from '../types';
import { toText } from '../serialize/text';
import { findChildrenWithName } from '../utils';
function push(counter, attrs, title, meta) {
const number = attrs.numbered ? counter.total + 1 : null;
counter.all.push({
id: attrs.id || null,
kind: counter.kind,
label: attrs.label || null,
title,
number,
numbered: attrs.numbered,
meta,
});
if (number) {
counter.total += 1;
}
}
const NO_CAPTION = { numbered: false, id: null, label: null };
export function countState(state) {
const counts = {
[ReferenceKind.sec]: { kind: ReferenceKind.sec, total: 0, all: [] },
[ReferenceKind.fig]: { kind: ReferenceKind.fig, total: 0, all: [] },
[ReferenceKind.eq]: { kind: ReferenceKind.eq, total: 0, all: [] },
[ReferenceKind.code]: { kind: ReferenceKind.code, total: 0, all: [] },
[ReferenceKind.table]: { kind: ReferenceKind.table, total: 0, all: [] },
[ReferenceKind.link]: { kind: ReferenceKind.link, total: 0, all: [] },
[ReferenceKind.cite]: { kind: ReferenceKind.cite, total: 0, all: [] },
};
let tableCounted = false;
state.doc.content.descendants((node) => {
switch (node.type.name) {
case nodeNames.cite: {
const { kind, key } = node.attrs;
if (kind === ReferenceKind.cite) {
const attrs = node.attrs;
push(counts.cite, { numbered: true, id: null, label: null }, attrs.title || '', {
key,
});
}
return false;
}
case nodeNames.image: {
const { src, alt } = node.attrs;
push(counts.fig, NO_CAPTION, alt, { src, alt });
return false;
}
case nodeNames.code_block: {
const { title, language } = node.attrs;
const code = toText(node);
push(counts.code, NO_CAPTION, title, { code, language });
return false;
}
case nodeNames.equation: {
const attrs = node.attrs;
const { title } = attrs;
const math = toText(node);
push(counts.eq, attrs, title, { math });
return false;
}
case nodeNames.heading: {
const attrs = node.attrs;
const { level } = node.attrs;
const title = toText(node);
push(counts.sec, attrs, title, { level, section: '' });
return true;
}
case nodeNames.table: {
if (!tableCounted)
push(counts.table, NO_CAPTION, '', {});
tableCounted = false;
// There are children of tables to be counted
return true;
}
// Continue to search
case nodeNames.figure: {
const child = findChildrenWithName(node, [
nodeNames.image,
nodeNames.iframe,
nodeNames.table,
nodeNames.code_block,
nodeNames.equation,
])[0];
if (!child)
return false;
const caption = findChildrenWithName(node, nodeNames.figcaption)[0];
const { numbered: isNumbered, id, label } = node.attrs;
const numbered = caption && isNumbered;
const captionText = (caption === null || caption === void 0 ? void 0 : caption.node) ? toText(caption.node) : '';
switch (child.node.type.name) {
case nodeNames.image: {
const { alt, src } = child.node.attrs;
push(counts.fig, { numbered, id, label }, captionText !== null && captionText !== void 0 ? captionText : alt, {
src,
alt,
});
return false;
}
case nodeNames.iframe: {
const { src } = child.node.attrs;
push(counts.fig, { numbered, id, label }, captionText, {
src,
alt: '',
});
return false;
}
case nodeNames.table: {
push(counts.table, { numbered, id, label }, captionText, {});
// There are children of tables to be counted
tableCounted = true;
return true;
}
case nodeNames.equation: {
const math = toText(child.node);
push(counts.eq, { numbered, id, label }, captionText, { math });
// There are children of tables to be counted
return false;
}
case nodeNames.code_block: {
const { title, language } = child.node.attrs;
const code = toText(child.node);
push(counts.code, { numbered, id, label }, captionText !== null && captionText !== void 0 ? captionText : title, {
code,
language,
});
// There are children of tables to be counted
return false;
}
default:
break;
}
return false;
}
default:
return true;
}
});
return counts;
}
export function countWords(state) {
const text = toText(state.doc);
const words = wordcount(text, 'words');
const characters_excluding_spaces = wordcount(text, 'characters_excluding_spaces');
const characters_including_spaces = wordcount(text, 'characters_including_spaces');
return {
words,
characters_excluding_spaces,
characters_including_spaces,
};
}
//# sourceMappingURL=countState.js.map