srs-document/node_modules/@unified-latex/unified-latex-ctan/package/systeme/index.js
2025-03-24 15:42:48 +07:00

332 lines
11 KiB
JavaScript

import { e, m } from "../../provides-yGf6-zdY.js";
import { match } from "@unified-latex/unified-latex-util-match";
import { decorateArrayForPegjs, SystemePegParser } from "@unified-latex/unified-latex-util-pegjs";
import { printRaw as printRaw$1 } from "@unified-latex/unified-latex-util-print-raw";
import { arrayJoin } from "@unified-latex/unified-latex-util-split";
import { s as structuredClone } from "../../index-NHd3tQDq.js";
import { deleteComments } from "@unified-latex/unified-latex-util-comments";
import { visit } from "@unified-latex/unified-latex-util-visit";
import { updateRenderInfo } from "@unified-latex/unified-latex-util-render-info";
import { getArgsContent } from "@unified-latex/unified-latex-util-arguments";
function createMatchers({
at = "@",
equals = "=",
equationSeparator = ",",
mathOperations = ["+", "-"],
whitelistedVariables
} = {}) {
let isVar = (node) => match.anyString(node) && !!node.content.match(/[a-zA-Z]/);
if (whitelistedVariables) {
whitelistedVariables = whitelistedVariables.map(
(v) => match.anyString(v) ? v.content : v
);
const macros = whitelistedVariables.filter(
(v) => match.anyMacro(v)
);
const strings = whitelistedVariables.filter(
(v) => typeof v === "string"
);
const macroHash = Object.fromEntries(macros.map((v) => [v.content, v]));
const stringHash = Object.fromEntries(strings.map((s) => [s, s]));
const macroMatcher = match.createMacroMatcher(macroHash);
isVar = (node) => macroMatcher(node) || match.anyString(node) && !!stringHash[node.content];
}
return {
isSep: (node) => match.string(node, equationSeparator),
isVar,
isOperation: (node) => mathOperations.some((op) => match.string(node, op)),
isEquals: (node) => match.string(node, equals),
isAt: (node) => match.string(node, at),
isSubscript: (node) => match.macro(node, "_") && node.escapeToken === "",
isWhitespace: match.whitespace,
isSameLineComment: (node) => match.comment(node) && node.sameline,
isOwnLineComment: (node) => match.comment(node) && !node.sameline
};
}
function parse(ast, options) {
if (!Array.isArray(ast)) {
throw new Error("You must pass an array of nodes");
}
ast = decorateArrayForPegjs([...ast]);
return SystemePegParser.parse(
ast,
createMatchers(options || {})
);
}
function printRaw(node, root = false) {
if (typeof node === "string") {
return node;
}
if (Array.isArray(node)) {
const sepToken = root ? " " : "";
return node.map((tok) => printRaw(tok)).join(sepToken);
}
switch (node.type) {
case "annotation":
return `${printRaw$1(node.marker)}${printRaw$1(
node.content
)}`;
case "item":
return `${node.op ? printRaw$1(node.op) : ""}${printRaw$1(
node.content
)}`;
case "equation":
const left = node.left.map((n) => printRaw(n)).join("");
const right = printRaw$1(node.right);
const equals = node.equals ? printRaw$1(node.equals) : "";
return `${left}${equals}${right}`;
case "line":
const equation = node.equation ? printRaw(node.equation) : "";
const annotation = node.annotation ? printRaw(node.annotation) : "";
const sep = node.sep ? printRaw$1(node.sep) : "";
const body = `${equation}${annotation}${sep}`;
if (node.trailingComment) {
return printRaw$1([body, node.trailingComment]);
}
return body;
default:
console.warn(
`Unknown node type "${node.type}" for node`,
node
);
return "";
}
}
const AMP = { type: "string", content: "&" };
const SEP = { type: "macro", content: "\\" };
const QUAD = { type: "macro", content: "quad" };
const PLUS = { type: "string", content: "+" };
const COLUMN_KERN_ADJUSTMENT = [
{ type: "string", content: "@" },
{
type: "group",
content: [
{ type: "macro", content: "mkern" },
{ type: "string", content: "5mu" }
]
}
];
function sortVariables(vars, whitelistedVariables) {
const varMap = new Map(vars.map((v) => [v, printRaw$1(v)]));
const varNames = Array.from(new Set(varMap.values()));
varNames.sort();
const nameToPos = whitelistedVariables ? new Map(whitelistedVariables.map((v, i) => [printRaw$1(v), i])) : new Map(varNames.map((name, i) => [name, i]));
return new Map(
Array.from(varMap.entries()).map(([variable, name]) => {
return [variable, nameToPos.get(name) ?? -1];
})
);
}
function processLine(line, numVars, varOrder, hasEquals, hasAnnotation) {
const ret = [];
if (line.equation) {
const nonVarItems = line.equation.left.filter(
(item) => item.variable == null
);
const varItems = line.equation.left.filter(
(item) => item.variable != null
);
let nonVarTerm = null;
if (nonVarItems.length === 1) {
nonVarTerm = nonVarItems[0];
} else if (nonVarItems.length > 1) {
nonVarTerm = {
...nonVarItems[0],
content: nonVarItems[0].content.concat(
nonVarItems.slice(1).flatMap((item) => {
if (item.op) {
return [item.op, ...item.content];
}
return [PLUS, ...item.content];
})
)
};
}
const allItems = nonVarTerm ? varItems.concat(nonVarTerm) : varItems;
const indexToItem = new Map(
allItems.map((item) => {
if (item.variable == null) {
return [numVars - 1, item];
}
return [varOrder.get(item.variable), item];
})
);
let isFirstItem = true;
for (let i = 0; i < numVars; i++) {
const item = indexToItem.get(i);
if (item) {
if (isFirstItem && (match.string(item.op, "+") || item.op == null)) {
ret.push([]);
ret.push(item.content);
} else {
ret.push([item.op || PLUS]);
ret.push(item.content);
}
isFirstItem = false;
} else {
ret.push([]);
ret.push([]);
}
}
if (hasEquals) {
const equalsPart = (line.equation.equals ? [line.equation.equals] : []).concat(line.equation.right);
ret.push(equalsPart);
}
}
if (hasAnnotation) {
ret.push(line.annotation ? line.annotation.content : []);
}
return ret;
}
function arraySpecToSpacedArraySpec(spec, hasAnnotation) {
const annotationSpec = hasAnnotation ? spec.charAt(spec.length - 1) : "";
const bodySpec = hasAnnotation ? spec.slice(0, spec.length - 1) : spec;
const bodyStrings = Array.from(bodySpec).map((x) => [
{ type: "string", content: x }
]);
const body = arrayJoin(bodyStrings, COLUMN_KERN_ADJUSTMENT);
return annotationSpec ? body.concat({ type: "string", content: annotationSpec }) : body;
}
function extractVariables(nodes) {
return nodes.flatMap((node) => {
if (node.type === "line" && node.equation) {
return extractVariables(node.equation.left);
}
if (node.type === "equation") {
return node.left.flatMap(
(item) => item.variable ? [item.variable] : []
);
}
if (node.type === "item") {
return node.variable ? [node.variable] : [];
}
return [];
});
}
function normalizeVariableWhitelist(vars) {
if (!vars) {
return null;
}
const normalized = vars.map(
(v) => typeof v === "string" ? { type: "string", content: v } : v
);
const ret = normalized.filter(
(v) => (match.anyMacro(v) || match.anyString(v)) && !match.string(v, " ") && !match.whitespace(v)
);
return ret;
}
function systemeContentsToArray(nodes, options) {
nodes = structuredClone(nodes);
deleteComments(nodes);
const { properSpacing = true, whitelistedVariables } = options || {};
const coercedWhitelistedVariables = normalizeVariableWhitelist(whitelistedVariables);
const systemeAst = parse(nodes, { whitelistedVariables });
const vars = extractVariables(systemeAst);
const varOrder = sortVariables(vars, coercedWhitelistedVariables);
let numVars = coercedWhitelistedVariables ? coercedWhitelistedVariables.length : Math.max(...Array.from(varOrder.values())) + 1;
if (systemeAst.some((line) => {
if (line.equation) {
return line.equation.left.some((item) => item.variable == null);
}
})) {
numVars += 1;
}
const hasEquals = systemeAst.some(
(line) => line.equation && line.equation.equals
);
const hasAnnotation = systemeAst.some((line) => line.annotation);
let rows = systemeAst.map(
(line) => processLine(line, numVars, varOrder, hasEquals, hasAnnotation)
);
const noLeadingOperation = rows.every((row) => row[0].length === 0);
let arraySignature = Array.from({ length: numVars }, () => "cr").join("");
if (noLeadingOperation) {
arraySignature = arraySignature.slice(1);
rows = rows.map((row) => row.slice(1));
}
if (hasEquals) {
arraySignature += "l";
}
if (hasAnnotation) {
arraySignature += "l";
rows = rows.map((row) => {
if (row[row.length - 1].length === 0) {
return row;
}
return [
...row.slice(0, row.length - 1),
[QUAD, { type: "whitespace" }, ...row[row.length - 1]]
];
});
}
const arraySignatureWithSpacing = properSpacing ? arraySpecToSpacedArraySpec(arraySignature, hasAnnotation) : [{ type: "string", content: arraySignature }];
const bodyRows = rows.map((row) => arrayJoin(row, AMP));
const body = arrayJoin(bodyRows, SEP);
const ret = {
type: "environment",
env: "array",
args: [
{
type: "argument",
openMark: "{",
closeMark: "}",
content: arraySignatureWithSpacing
}
],
content: body
};
return ret;
}
function attachSystemeSettingsAsRenderInfo(ast) {
const systemeMatcher = match.createMacroMatcher(["systeme", "sysdelim"]);
visit(
ast,
(nodes, info) => {
if (!info.context.inMathMode || !nodes.some(systemeMatcher)) {
return;
}
const systemeLocations = nodes.flatMap(
(node, i) => match.macro(node, "systeme") ? i : []
);
const sysdelimLocations = nodes.flatMap(
(node, i) => match.macro(node, "sysdelim") ? i : []
);
if (systemeLocations.length === 0 || sysdelimLocations.length === 0) {
return;
}
for (const i of systemeLocations) {
const lastSysdelim = Math.max(
...sysdelimLocations.filter((loc) => loc < i)
);
if (lastSysdelim >= 0) {
const node = nodes[i];
const sysdelimMacro = nodes[lastSysdelim];
if (!match.anyMacro(sysdelimMacro)) {
throw new Error(
`Expecting sysdelim macro but found "${printRaw$1(
sysdelimMacro
)}"`
);
}
const args = getArgsContent(sysdelimMacro);
updateRenderInfo(node, { sysdelims: args });
}
}
},
{
test: Array.isArray,
includeArrays: true
}
);
}
export {
attachSystemeSettingsAsRenderInfo,
e as environments,
extractVariables,
m as macros,
parse,
printRaw,
systemeContentsToArray
};
//# sourceMappingURL=index.js.map