@lofcz/tikz 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/browser-worker.js +86 -83
- package/dist/worker.js +361 -49
- package/package.json +1 -1
- package/src/recover.js +255 -0
- package/src/source.js +60 -5
- package/src/tables.js +1 -1
package/dist/worker.js
CHANGED
|
@@ -802,21 +802,21 @@ var require_color_string = __commonJS({
|
|
|
802
802
|
to: {},
|
|
803
803
|
get: {}
|
|
804
804
|
};
|
|
805
|
-
cs.get = function(
|
|
806
|
-
var prefix =
|
|
805
|
+
cs.get = function(string3) {
|
|
806
|
+
var prefix = string3.substring(0, 3).toLowerCase();
|
|
807
807
|
var val;
|
|
808
808
|
var model;
|
|
809
809
|
switch (prefix) {
|
|
810
810
|
case "hsl":
|
|
811
|
-
val = cs.get.hsl(
|
|
811
|
+
val = cs.get.hsl(string3);
|
|
812
812
|
model = "hsl";
|
|
813
813
|
break;
|
|
814
814
|
case "hwb":
|
|
815
|
-
val = cs.get.hwb(
|
|
815
|
+
val = cs.get.hwb(string3);
|
|
816
816
|
model = "hwb";
|
|
817
817
|
break;
|
|
818
818
|
default:
|
|
819
|
-
val = cs.get.rgb(
|
|
819
|
+
val = cs.get.rgb(string3);
|
|
820
820
|
model = "rgb";
|
|
821
821
|
break;
|
|
822
822
|
}
|
|
@@ -825,8 +825,8 @@ var require_color_string = __commonJS({
|
|
|
825
825
|
}
|
|
826
826
|
return { model, value: val };
|
|
827
827
|
};
|
|
828
|
-
cs.get.rgb = function(
|
|
829
|
-
if (!
|
|
828
|
+
cs.get.rgb = function(string3) {
|
|
829
|
+
if (!string3) {
|
|
830
830
|
return null;
|
|
831
831
|
}
|
|
832
832
|
var abbr = /^#([a-f0-9]{3,4})$/i;
|
|
@@ -838,7 +838,7 @@ var require_color_string = __commonJS({
|
|
|
838
838
|
var match2;
|
|
839
839
|
var i;
|
|
840
840
|
var hexAlpha;
|
|
841
|
-
if (match2 =
|
|
841
|
+
if (match2 = string3.match(hex)) {
|
|
842
842
|
hexAlpha = match2[2];
|
|
843
843
|
match2 = match2[1];
|
|
844
844
|
for (i = 0; i < 3; i++) {
|
|
@@ -848,7 +848,7 @@ var require_color_string = __commonJS({
|
|
|
848
848
|
if (hexAlpha) {
|
|
849
849
|
rgb[3] = parseInt(hexAlpha, 16) / 255;
|
|
850
850
|
}
|
|
851
|
-
} else if (match2 =
|
|
851
|
+
} else if (match2 = string3.match(abbr)) {
|
|
852
852
|
match2 = match2[1];
|
|
853
853
|
hexAlpha = match2[3];
|
|
854
854
|
for (i = 0; i < 3; i++) {
|
|
@@ -857,7 +857,7 @@ var require_color_string = __commonJS({
|
|
|
857
857
|
if (hexAlpha) {
|
|
858
858
|
rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255;
|
|
859
859
|
}
|
|
860
|
-
} else if (match2 =
|
|
860
|
+
} else if (match2 = string3.match(rgba)) {
|
|
861
861
|
for (i = 0; i < 3; i++) {
|
|
862
862
|
rgb[i] = parseInt(match2[i + 1], 0);
|
|
863
863
|
}
|
|
@@ -868,7 +868,7 @@ var require_color_string = __commonJS({
|
|
|
868
868
|
rgb[3] = parseFloat(match2[4]);
|
|
869
869
|
}
|
|
870
870
|
}
|
|
871
|
-
} else if (match2 =
|
|
871
|
+
} else if (match2 = string3.match(per)) {
|
|
872
872
|
for (i = 0; i < 3; i++) {
|
|
873
873
|
rgb[i] = Math.round(parseFloat(match2[i + 1]) * 2.55);
|
|
874
874
|
}
|
|
@@ -879,7 +879,7 @@ var require_color_string = __commonJS({
|
|
|
879
879
|
rgb[3] = parseFloat(match2[4]);
|
|
880
880
|
}
|
|
881
881
|
}
|
|
882
|
-
} else if (match2 =
|
|
882
|
+
} else if (match2 = string3.match(keyword)) {
|
|
883
883
|
if (match2[1] === "transparent") {
|
|
884
884
|
return [0, 0, 0, 0];
|
|
885
885
|
}
|
|
@@ -898,12 +898,12 @@ var require_color_string = __commonJS({
|
|
|
898
898
|
rgb[3] = clamp(rgb[3], 0, 1);
|
|
899
899
|
return rgb;
|
|
900
900
|
};
|
|
901
|
-
cs.get.hsl = function(
|
|
902
|
-
if (!
|
|
901
|
+
cs.get.hsl = function(string3) {
|
|
902
|
+
if (!string3) {
|
|
903
903
|
return null;
|
|
904
904
|
}
|
|
905
905
|
var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
|
|
906
|
-
var match2 =
|
|
906
|
+
var match2 = string3.match(hsl);
|
|
907
907
|
if (match2) {
|
|
908
908
|
var alpha = parseFloat(match2[4]);
|
|
909
909
|
var h = (parseFloat(match2[1]) % 360 + 360) % 360;
|
|
@@ -914,12 +914,12 @@ var require_color_string = __commonJS({
|
|
|
914
914
|
}
|
|
915
915
|
return null;
|
|
916
916
|
};
|
|
917
|
-
cs.get.hwb = function(
|
|
918
|
-
if (!
|
|
917
|
+
cs.get.hwb = function(string3) {
|
|
918
|
+
if (!string3) {
|
|
919
919
|
return null;
|
|
920
920
|
}
|
|
921
921
|
var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
|
|
922
|
-
var match2 =
|
|
922
|
+
var match2 = string3.match(hwb);
|
|
923
923
|
if (match2) {
|
|
924
924
|
var alpha = parseFloat(match2[4]);
|
|
925
925
|
var h = (parseFloat(match2[1]) % 360 + 360) % 360;
|
|
@@ -1450,8 +1450,8 @@ var require_conversions = __commonJS({
|
|
|
1450
1450
|
};
|
|
1451
1451
|
convert.rgb.hex = function(args) {
|
|
1452
1452
|
const integer = ((Math.round(args[0]) & 255) << 16) + ((Math.round(args[1]) & 255) << 8) + (Math.round(args[2]) & 255);
|
|
1453
|
-
const
|
|
1454
|
-
return "000000".substring(
|
|
1453
|
+
const string3 = integer.toString(16).toUpperCase();
|
|
1454
|
+
return "000000".substring(string3.length) + string3;
|
|
1455
1455
|
};
|
|
1456
1456
|
convert.hex.rgb = function(args) {
|
|
1457
1457
|
const match2 = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
|
|
@@ -1631,8 +1631,8 @@ var require_conversions = __commonJS({
|
|
|
1631
1631
|
convert.gray.hex = function(gray) {
|
|
1632
1632
|
const val = Math.round(gray[0] / 100 * 255) & 255;
|
|
1633
1633
|
const integer = (val << 16) + (val << 8) + val;
|
|
1634
|
-
const
|
|
1635
|
-
return "000000".substring(
|
|
1634
|
+
const string3 = integer.toString(16).toUpperCase();
|
|
1635
|
+
return "000000".substring(string3.length) + string3;
|
|
1636
1636
|
};
|
|
1637
1637
|
convert.rgb.gray = function(rgb) {
|
|
1638
1638
|
const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
|
|
@@ -3350,14 +3350,14 @@ function visit(tree, visitor, options) {
|
|
|
3350
3350
|
enter = visitor.enter;
|
|
3351
3351
|
leave = visitor.leave;
|
|
3352
3352
|
}
|
|
3353
|
-
|
|
3353
|
+
walk2(tree, {
|
|
3354
3354
|
key: void 0,
|
|
3355
3355
|
index: void 0,
|
|
3356
3356
|
parents: [],
|
|
3357
3357
|
containingArray: void 0,
|
|
3358
3358
|
context: { ...startingContext }
|
|
3359
3359
|
});
|
|
3360
|
-
function
|
|
3360
|
+
function walk2(node, { key, index: index2, parents, context, containingArray }) {
|
|
3361
3361
|
const nodePassesTest = includeArrays ? test(node, {
|
|
3362
3362
|
key,
|
|
3363
3363
|
index: index2,
|
|
@@ -3388,7 +3388,7 @@ function visit(tree, visitor, options) {
|
|
|
3388
3388
|
})) : result;
|
|
3389
3389
|
if (Array.isArray(node)) for (let index3 = 0; index3 > -1 && index3 < node.length; index3++) {
|
|
3390
3390
|
const item = node[index3];
|
|
3391
|
-
const result2 =
|
|
3391
|
+
const result2 = walk2(item, {
|
|
3392
3392
|
key,
|
|
3393
3393
|
index: index3,
|
|
3394
3394
|
parents,
|
|
@@ -3423,7 +3423,7 @@ function visit(tree, visitor, options) {
|
|
|
3423
3423
|
newContext.inMathMode = true;
|
|
3424
3424
|
newContext.hasMathModeAncestor = true;
|
|
3425
3425
|
} else if (mathModeProps.leave.includes(key2)) newContext.inMathMode = false;
|
|
3426
|
-
const result2 =
|
|
3426
|
+
const result2 = walk2(value, {
|
|
3427
3427
|
key: key2,
|
|
3428
3428
|
index: void 0,
|
|
3429
3429
|
parents: grandparents,
|
|
@@ -11298,10 +11298,10 @@ var pgfkeys_default = (function() {
|
|
|
11298
11298
|
function peg$f8(x) {
|
|
11299
11299
|
return x;
|
|
11300
11300
|
}
|
|
11301
|
-
function peg$f9(
|
|
11301
|
+
function peg$f9(space2, x) {
|
|
11302
11302
|
return {
|
|
11303
11303
|
trailingComment: x,
|
|
11304
|
-
leadingParbreak:
|
|
11304
|
+
leadingParbreak: space2.parbreak > 0
|
|
11305
11305
|
};
|
|
11306
11306
|
}
|
|
11307
11307
|
function peg$f10(list) {
|
|
@@ -24330,9 +24330,9 @@ function buildWordRegex(allowedSet) {
|
|
|
24330
24330
|
function hasReparsableMacroNamesInArray(tree, allowedTokens) {
|
|
24331
24331
|
for (let i = 0; i < tree.length; i++) {
|
|
24332
24332
|
const macro3 = tree[i];
|
|
24333
|
-
const
|
|
24334
|
-
if (match.anyMacro(macro3) && match.anyString(
|
|
24335
|
-
if (allowedTokens.has(macro3.content.charAt(macro3.content.length - 1)) || allowedTokens.has(
|
|
24333
|
+
const string3 = tree[i + 1];
|
|
24334
|
+
if (match.anyMacro(macro3) && match.anyString(string3)) {
|
|
24335
|
+
if (allowedTokens.has(macro3.content.charAt(macro3.content.length - 1)) || allowedTokens.has(string3.content.charAt(0))) return true;
|
|
24336
24336
|
}
|
|
24337
24337
|
}
|
|
24338
24338
|
return false;
|
|
@@ -24358,24 +24358,24 @@ function reparseMacroNamesInArray(tree, allowedTokens) {
|
|
|
24358
24358
|
let i = 0;
|
|
24359
24359
|
while (i < tree.length) {
|
|
24360
24360
|
const macro3 = tree[i];
|
|
24361
|
-
const
|
|
24362
|
-
if (match.anyMacro(macro3) && (macro3.escapeToken == null || macro3.escapeToken === "\\") && match.anyString(
|
|
24363
|
-
const match2 =
|
|
24361
|
+
const string3 = tree[i + 1];
|
|
24362
|
+
if (match.anyMacro(macro3) && (macro3.escapeToken == null || macro3.escapeToken === "\\") && match.anyString(string3) && (allowedTokens.has(macro3.content.charAt(macro3.content.length - 1)) || allowedTokens.has(string3.content.charAt(0)))) {
|
|
24363
|
+
const match2 = string3.content.match(regex);
|
|
24364
24364
|
const takeable = match2 ? match2[0] : "";
|
|
24365
|
-
if (takeable.length > 0) if (takeable.length ===
|
|
24366
|
-
macro3.content +=
|
|
24365
|
+
if (takeable.length > 0) if (takeable.length === string3.content.length) {
|
|
24366
|
+
macro3.content += string3.content;
|
|
24367
24367
|
tree.splice(i + 1, 1);
|
|
24368
|
-
if (macro3.position &&
|
|
24368
|
+
if (macro3.position && string3.position?.end) macro3.position.end = string3.position.end;
|
|
24369
24369
|
} else {
|
|
24370
24370
|
macro3.content += takeable;
|
|
24371
|
-
|
|
24371
|
+
string3.content = string3.content.slice(takeable.length);
|
|
24372
24372
|
if (macro3.position?.end) {
|
|
24373
24373
|
macro3.position.end.offset += takeable.length;
|
|
24374
24374
|
macro3.position.end.column += takeable.length;
|
|
24375
24375
|
}
|
|
24376
|
-
if (
|
|
24377
|
-
|
|
24378
|
-
|
|
24376
|
+
if (string3.position?.start) {
|
|
24377
|
+
string3.position.start.offset += takeable.length;
|
|
24378
|
+
string3.position.start.column += takeable.length;
|
|
24379
24379
|
}
|
|
24380
24380
|
}
|
|
24381
24381
|
else i++;
|
|
@@ -24803,7 +24803,7 @@ var AUTO_PACKAGES = [
|
|
|
24803
24803
|
];
|
|
24804
24804
|
var AUTO_LIBRARIES = [
|
|
24805
24805
|
[/\bmatrix of (?:math )?nodes\b|\\matrix\b/, "matrix"],
|
|
24806
|
-
[/\b(?:regular polygon|trapezium|semicircle|isosceles triangle|kite|dart|circular sector|cylinder|diamond|star|ellipse)\s*[,\]=]/, "shapes.geometric"],
|
|
24806
|
+
[/\b(?:regular polygon|trapezium|parallelogram|semicircle|isosceles triangle|kite|dart|circular sector|cylinder|diamond|star|ellipse)\s*[,\]=]/, "shapes.geometric"],
|
|
24807
24807
|
[/\b(?:cross out|strike out|rounded rectangle|chamfered rectangle)\b/, "shapes.misc"],
|
|
24808
24808
|
[/\b(?:cloud|forbidden sign|magnifying glass|starburst|signal|tape|magnetic tape|correct forbidden sign)\s*[,\]=]/, "shapes.symbols"],
|
|
24809
24809
|
[/\b(?:rectangle split|circle split|ellipse split)\b/, "shapes.multipart"],
|
|
@@ -25266,6 +25266,265 @@ var TEXT_ARG_MACROS = /* @__PURE__ */ new Set(["textbf", "textit", "emph", "unde
|
|
|
25266
25266
|
var SHAPE_NAMES = /* @__PURE__ */ new Set(["rectangle", "circle", "coordinate", "ellipse", "diamond", "trapezium", "semicircle", "regular polygon", "star", "isosceles triangle", "kite", "dart", "circular sector", "cylinder", "cloud", "starburst", "signal", "tape", "magnifying glass", "forbidden sign", "magnetic tape", "cross out", "strike out", "rounded rectangle", "chamfered rectangle", "rectangle split", "circle split", "circle solidus", "ellipse split", "rectangle callout", "ellipse callout", "cloud callout", "arrow box", "single arrow", "double arrow", "circle ee", "circle wee", "cross", "ground", "generic circle IEC", "generic diode IEC", "and gate", "or gate", "nand gate", "nor gate", "xor gate", "xnor gate", "not gate", "buffer gate"]);
|
|
25267
25267
|
var MACRO_TYPOS = { circC: "\\circ\\mathrm{C}", degreeC: "^\\circ\\mathrm{C}", textcelsius: "\\celsius", textdegreeC: "\\textdegree C" };
|
|
25268
25268
|
|
|
25269
|
+
// src/recover.js
|
|
25270
|
+
var string2 = (content) => ({ type: "string", content });
|
|
25271
|
+
var group2 = (content) => ({ type: "group", content });
|
|
25272
|
+
var is = (node, text) => node?.type === "string" && node.content === text;
|
|
25273
|
+
var space = (node) => node?.type === "whitespace" || node?.type === "parbreak";
|
|
25274
|
+
var skip = (nodes, i) => {
|
|
25275
|
+
while (space(nodes[i])) i++;
|
|
25276
|
+
return i;
|
|
25277
|
+
};
|
|
25278
|
+
function walk(nodes, visit2) {
|
|
25279
|
+
visit2(nodes);
|
|
25280
|
+
for (const node of nodes) if (Array.isArray(node.content)) walk(node.content, visit2);
|
|
25281
|
+
}
|
|
25282
|
+
function closeAt(nodes, start, open, close) {
|
|
25283
|
+
let depth = 0;
|
|
25284
|
+
for (let i = start; i < nodes.length; i++) {
|
|
25285
|
+
if (is(nodes[i], open)) depth++;
|
|
25286
|
+
else if (is(nodes[i], close) && --depth === 0) return i;
|
|
25287
|
+
}
|
|
25288
|
+
return -1;
|
|
25289
|
+
}
|
|
25290
|
+
var DEFINITIONS = /* @__PURE__ */ new Set(["def", "gdef", "edef", "xdef", "let", "newcommand", "renewcommand", "providecommand", "pgfmathsetmacro", "pgfmathtruncatemacro", "pgfmathsetlengthmacro"]);
|
|
25291
|
+
function extendedIdentifiers(root, source2) {
|
|
25292
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
25293
|
+
const names = /* @__PURE__ */ new Set();
|
|
25294
|
+
walk(root, (nodes) => {
|
|
25295
|
+
for (const node of nodes) if (node.type === "macro") names.add(node.content);
|
|
25296
|
+
});
|
|
25297
|
+
walk(root, (nodes) => {
|
|
25298
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25299
|
+
if (nodes[i].type !== "macro" || !DEFINITIONS.has(nodes[i].content)) continue;
|
|
25300
|
+
const at = skip(nodes, i + 1);
|
|
25301
|
+
const target = nodes[at]?.type === "group" ? nodes[at].content : nodes.slice(at, at + 3);
|
|
25302
|
+
const [macro3, tail, end] = target;
|
|
25303
|
+
if (macro3?.type !== "macro" || tail?.type !== "string" || !/^(?:_[A-Za-z0-9_]+|[0-9][A-Za-z0-9_]*)$/.test(tail.content)) continue;
|
|
25304
|
+
if (end && end.type !== "group" && !(nodes[i].content === "let" && end.type === "macro")) continue;
|
|
25305
|
+
if (macro3.position?.end.offset !== tail.position?.start.offset) continue;
|
|
25306
|
+
const key = macro3.content + tail.content;
|
|
25307
|
+
if (bindings.has(key)) continue;
|
|
25308
|
+
let name = "tikzRecoveredVariable";
|
|
25309
|
+
let n = bindings.size;
|
|
25310
|
+
do {
|
|
25311
|
+
name += String.fromCharCode(65 + n % 26);
|
|
25312
|
+
n = Math.floor(n / 26);
|
|
25313
|
+
} while (n);
|
|
25314
|
+
while (names.has(name)) name += "X";
|
|
25315
|
+
names.add(name);
|
|
25316
|
+
bindings.set(key, { base: macro3.content, suffix: tail.content, name });
|
|
25317
|
+
}
|
|
25318
|
+
});
|
|
25319
|
+
if (!bindings.size) return;
|
|
25320
|
+
walk(root, (nodes) => {
|
|
25321
|
+
for (let i = 0; i + 1 < nodes.length; i++) {
|
|
25322
|
+
const node = nodes[i];
|
|
25323
|
+
if (node.type !== "macro") continue;
|
|
25324
|
+
for (const binding of bindings.values()) {
|
|
25325
|
+
const offset = node.position?.end.offset;
|
|
25326
|
+
if (node.content !== binding.base || !source2.startsWith(binding.suffix, offset)) continue;
|
|
25327
|
+
const end = offset + binding.suffix.length;
|
|
25328
|
+
if (/[A-Za-z0-9_]/.test(source2[end] ?? "")) continue;
|
|
25329
|
+
let j = i + 1;
|
|
25330
|
+
while (j < nodes.length && nodes[j].position?.end.offset <= end) j++;
|
|
25331
|
+
if (nodes[j - 1]?.position?.end.offset !== end) continue;
|
|
25332
|
+
node.content = binding.name;
|
|
25333
|
+
nodes.splice(i + 1, j - i - 1);
|
|
25334
|
+
break;
|
|
25335
|
+
}
|
|
25336
|
+
}
|
|
25337
|
+
});
|
|
25338
|
+
}
|
|
25339
|
+
function nestedOptions(nodes) {
|
|
25340
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25341
|
+
if (!is(nodes[i], "[")) continue;
|
|
25342
|
+
let close = closeAt(nodes, i, "[", "]");
|
|
25343
|
+
if (close < 0) continue;
|
|
25344
|
+
for (let j = i + 1; j < close; j++) {
|
|
25345
|
+
if (!is(nodes[j], "[")) continue;
|
|
25346
|
+
const end = closeAt(nodes, j, "[", "]");
|
|
25347
|
+
let start = j - 1;
|
|
25348
|
+
while (start > i && !is(nodes[start], "=") && !is(nodes[start], ",")) start--;
|
|
25349
|
+
if (end < 0 || !is(nodes[start], "=")) continue;
|
|
25350
|
+
const value = nodes.slice(start + 1, end + 1);
|
|
25351
|
+
nodes.splice(start + 1, end - start, group2(value));
|
|
25352
|
+
close -= end - start - 1;
|
|
25353
|
+
j = start + 1;
|
|
25354
|
+
}
|
|
25355
|
+
i = close;
|
|
25356
|
+
}
|
|
25357
|
+
}
|
|
25358
|
+
function coordinateComponent(nodes, alreadyGrouped = false) {
|
|
25359
|
+
const significant2 = nodes.filter((node) => !space(node));
|
|
25360
|
+
if (significant2.length === 1 && significant2[0].type === "group") {
|
|
25361
|
+
significant2[0].content = coordinateComponent(significant2[0].content, true);
|
|
25362
|
+
return nodes;
|
|
25363
|
+
}
|
|
25364
|
+
let unitStart = significant2.length - 1;
|
|
25365
|
+
let unit = significant2[unitStart]?.type === "string" ? significant2[unitStart].content : "";
|
|
25366
|
+
if (unit.length === 1 && significant2[unitStart - 1]?.type === "string") {
|
|
25367
|
+
unitStart--;
|
|
25368
|
+
unit = significant2[unitStart].content + unit;
|
|
25369
|
+
}
|
|
25370
|
+
if (!/^(?:cm|mm|pt|bp|in|em|ex)$/.test(unit)) unit = null;
|
|
25371
|
+
if (unit && significant2.length > 1 && (significant2[0].type === "group" || significant2.some((node) => is(node, "(")))) {
|
|
25372
|
+
const expr = significant2.slice(0, unitStart).flatMap((node) => node.type === "group" ? [string2("("), ...node.content, string2(")")] : [node]);
|
|
25373
|
+
const repaired = [string2("("), ...expr, string2(")*1" + unit)];
|
|
25374
|
+
return alreadyGrouped ? repaired : [group2(repaired)];
|
|
25375
|
+
}
|
|
25376
|
+
if (!alreadyGrouped && nodes.some((node) => is(node, "("))) return [group2(nodes)];
|
|
25377
|
+
return nodes;
|
|
25378
|
+
}
|
|
25379
|
+
function coordinates(nodes) {
|
|
25380
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25381
|
+
if (nodes[i].type === "inlinemath") {
|
|
25382
|
+
coordinates(nodes[i].content);
|
|
25383
|
+
continue;
|
|
25384
|
+
}
|
|
25385
|
+
if (!is(nodes[i], "(")) continue;
|
|
25386
|
+
const end = closeAt(nodes, i, "(", ")");
|
|
25387
|
+
if (end < 0) continue;
|
|
25388
|
+
const inside = nodes.slice(i + 1, end);
|
|
25389
|
+
if (inside.some((node) => node.type === "inlinemath")) {
|
|
25390
|
+
for (const node of inside) if (node.type === "inlinemath") coordinates(node.content);
|
|
25391
|
+
i = end;
|
|
25392
|
+
continue;
|
|
25393
|
+
}
|
|
25394
|
+
let depth = 0, start = 0;
|
|
25395
|
+
const segments = [], delimiters = [];
|
|
25396
|
+
for (let j = 0; j < inside.length; j++) {
|
|
25397
|
+
if (is(inside[j], "(")) depth++;
|
|
25398
|
+
else if (is(inside[j], ")")) depth--;
|
|
25399
|
+
else if (!depth && (is(inside[j], ",") || is(inside[j], ":") || is(inside[j], "and"))) {
|
|
25400
|
+
segments.push(inside.slice(start, j));
|
|
25401
|
+
delimiters.push(is(inside[j], "and") ? string2(" and ") : inside[j]);
|
|
25402
|
+
start = j + 1;
|
|
25403
|
+
}
|
|
25404
|
+
}
|
|
25405
|
+
segments.push(inside.slice(start));
|
|
25406
|
+
if (inside.some((node) => is(node, "=") || is(node, "|") || is(node, "cs"))) {
|
|
25407
|
+
i = end;
|
|
25408
|
+
continue;
|
|
25409
|
+
}
|
|
25410
|
+
const rebuilt = segments.flatMap((part, j) => [...coordinateComponent(part), ...delimiters[j] ? [delimiters[j]] : []]);
|
|
25411
|
+
nodes.splice(i + 1, end - i - 1, ...rebuilt);
|
|
25412
|
+
i += rebuilt.length + 1;
|
|
25413
|
+
}
|
|
25414
|
+
}
|
|
25415
|
+
var PATHS = /* @__PURE__ */ new Set(["draw", "fill", "filldraw", "shade", "shadedraw", "path", "coordinate", "node", "clip", "pic"]);
|
|
25416
|
+
function delimited(nodes, at, open, close) {
|
|
25417
|
+
at = skip(nodes, at);
|
|
25418
|
+
if (!is(nodes[at], open)) return null;
|
|
25419
|
+
const end = closeAt(nodes, at, open, close);
|
|
25420
|
+
return end < 0 ? null : { start: at, end: end + 1, content: nodes.slice(at + 1, end) };
|
|
25421
|
+
}
|
|
25422
|
+
function tkzCommands(nodes) {
|
|
25423
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25424
|
+
const node = nodes[i];
|
|
25425
|
+
if (node.type !== "macro" || !node.content.startsWith("tkz")) continue;
|
|
25426
|
+
const options = delimited(nodes, i + 1, "[", "]");
|
|
25427
|
+
const point2 = delimited(nodes, options?.end ?? i + 1, "(", ")");
|
|
25428
|
+
if (!point2) continue;
|
|
25429
|
+
if (node.content === "tkzDefLine" && options) {
|
|
25430
|
+
const first = skip(options.content, 0);
|
|
25431
|
+
const through = skip(options.content, first + 1);
|
|
25432
|
+
if (["orthogonal", "perpendicular", "parallel"].some((key) => is(options.content[first], key)) && is(options.content[through], "through")) {
|
|
25433
|
+
nodes.splice(options.start + 1 + first + 1, 0, string2("="));
|
|
25434
|
+
}
|
|
25435
|
+
}
|
|
25436
|
+
if (node.content === "tkzMidPoint") node.content = "tkzDefMidPoint";
|
|
25437
|
+
if (["tkzDefMidPoint", "tkzDefPointBy", "tkzDefPointWith"].includes(node.content)) {
|
|
25438
|
+
const out = skip(nodes, point2.end);
|
|
25439
|
+
if (nodes[out]?.type === "group") nodes.splice(out, 0, { type: "macro", content: "tkzGetPoint" });
|
|
25440
|
+
if (node.content === "tkzDefPointBy" && options) {
|
|
25441
|
+
const onto = options.content.findIndex((token) => is(token, "onto"));
|
|
25442
|
+
const line = skip(options.content, onto + 1);
|
|
25443
|
+
if (onto >= 0 && is(options.content[line], "line")) {
|
|
25444
|
+
options.content.splice(line, 1);
|
|
25445
|
+
nodes.splice(options.start + 1, options.end - options.start - 2, ...options.content);
|
|
25446
|
+
}
|
|
25447
|
+
}
|
|
25448
|
+
}
|
|
25449
|
+
if (node.content === "tkzInter" && options && printRaw(options.content).trim() === "R" && delimited(nodes, point2.end, "(", ")")) node.content = "tkzInterCC";
|
|
25450
|
+
if (node.content === "tkzDrawCircle" && options) {
|
|
25451
|
+
const keys2 = parsePgfkeys(options.content).map((item) => (item.itemParts ?? []).map((part) => printRaw(part).trim()).join("="));
|
|
25452
|
+
const mode = keys2.find((key) => ["circum", "in", "diameter", "R"].includes(key));
|
|
25453
|
+
const count = point2.content.filter((token) => is(token, ",")).length + 1;
|
|
25454
|
+
if (!mode || count !== (["circum", "in"].includes(mode) ? 3 : 2)) continue;
|
|
25455
|
+
const rest = keys2.filter((key) => key !== mode).join(",");
|
|
25456
|
+
if (mode === "R") {
|
|
25457
|
+
const comma = point2.content.findIndex((token) => is(token, ","));
|
|
25458
|
+
nodes.splice(i, point2.end - i, string2(String.raw`\draw[circle style,${rest}] (${printRaw(point2.content.slice(0, comma))}) circle (${printRaw(point2.content.slice(comma + 1))});`));
|
|
25459
|
+
continue;
|
|
25460
|
+
}
|
|
25461
|
+
const replacement = String.raw`{\tkzDefCircle[${mode}](${printRaw(point2.content)})\tkzGetPoints{tikzRecoveredCircleCenter}{tikzRecoveredCirclePoint}\tkzDrawCircle[${rest}](tikzRecoveredCircleCenter,tikzRecoveredCirclePoint)}`;
|
|
25462
|
+
nodes.splice(i, point2.end - i, string2(replacement));
|
|
25463
|
+
}
|
|
25464
|
+
}
|
|
25465
|
+
}
|
|
25466
|
+
function numberExpressions(nodes) {
|
|
25467
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25468
|
+
const node = nodes[i];
|
|
25469
|
+
if (node.type !== "macro") continue;
|
|
25470
|
+
if (["pgfmathparse", "pgfmathsetmacro", "pgfmathtruncatemacro"].includes(node.content)) {
|
|
25471
|
+
let at2 = skip(nodes, i + 1);
|
|
25472
|
+
if (node.content !== "pgfmathparse") at2 = skip(nodes, at2 + 1);
|
|
25473
|
+
const expr2 = nodes[at2];
|
|
25474
|
+
if (expr2?.type !== "group") continue;
|
|
25475
|
+
const mod = expr2.content.findIndex((token) => is(token, "mod"));
|
|
25476
|
+
const atom = (tokens) => {
|
|
25477
|
+
const value = tokens.filter((token) => !space(token));
|
|
25478
|
+
return value.length === 1 && (value[0].type === "macro" || value[0].type === "group" || value[0].type === "string" && /^-?\d+(?:\.\d+)?$/.test(value[0].content));
|
|
25479
|
+
};
|
|
25480
|
+
if (mod > 0 && atom(expr2.content.slice(0, mod)) && atom(expr2.content.slice(mod + 1))) expr2.content = [string2("mod("), ...expr2.content.slice(0, mod), string2(","), ...expr2.content.slice(mod + 1), string2(")")];
|
|
25481
|
+
}
|
|
25482
|
+
if (node.content !== "pgfmathprintnumber") continue;
|
|
25483
|
+
const options = delimited(nodes, i + 1, "[", "]");
|
|
25484
|
+
const at = skip(nodes, options?.end ?? i + 1);
|
|
25485
|
+
const expr = nodes[at];
|
|
25486
|
+
if (expr?.type !== "group" || !expr.content.some((token) => token.type === "string" && ["*", "/", "+", "("].includes(token.content))) continue;
|
|
25487
|
+
nodes.splice(i, at - i + 1, string2(String.raw`{\pgfmathparse{${printRaw(expr.content)}}\pgfmathprintnumber${options ? `[${printRaw(options.content)}]` : ""}{\pgfmathresult}}`));
|
|
25488
|
+
}
|
|
25489
|
+
}
|
|
25490
|
+
function relativeNodePosition(nodes) {
|
|
25491
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25492
|
+
if (nodes[i].type !== "macro" || nodes[i].content !== "node") continue;
|
|
25493
|
+
let at = i + 1;
|
|
25494
|
+
while (at < nodes.length && !is(nodes[at], "at") && !is(nodes[at], ";")) at++;
|
|
25495
|
+
if (!is(nodes[at], "at")) continue;
|
|
25496
|
+
const base2 = delimited(nodes, at + 1, "(", ")");
|
|
25497
|
+
if (!base2) continue;
|
|
25498
|
+
let plus = skip(nodes, base2.end);
|
|
25499
|
+
if (!is(nodes[plus], "+")) continue;
|
|
25500
|
+
plus++;
|
|
25501
|
+
if (is(nodes[plus], "+")) plus++;
|
|
25502
|
+
const offset = delimited(nodes, plus, "(", ")");
|
|
25503
|
+
if (!offset) continue;
|
|
25504
|
+
nodes.splice(base2.start, offset.end - base2.start, string2(`($(${printRaw(base2.content)})+(${printRaw(offset.content)})$)`));
|
|
25505
|
+
}
|
|
25506
|
+
}
|
|
25507
|
+
function recoverGeneratedSyntax(source2) {
|
|
25508
|
+
const root = parseMinimal(source2).content;
|
|
25509
|
+
extendedIdentifiers(root, source2);
|
|
25510
|
+
walk(root, nestedOptions);
|
|
25511
|
+
walk(root, tkzCommands);
|
|
25512
|
+
walk(root, numberExpressions);
|
|
25513
|
+
walk(root, relativeNodePosition);
|
|
25514
|
+
walk(root, (nodes) => {
|
|
25515
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
25516
|
+
if (nodes[i].type !== "macro" || !PATHS.has(nodes[i].content)) continue;
|
|
25517
|
+
let end = i + 1;
|
|
25518
|
+
while (end < nodes.length && !is(nodes[end], ";")) end++;
|
|
25519
|
+
const tokens = nodes.slice(i + 1, end);
|
|
25520
|
+
coordinates(tokens);
|
|
25521
|
+
nodes.splice(i + 1, end - i - 1, ...tokens);
|
|
25522
|
+
i += tokens.length;
|
|
25523
|
+
}
|
|
25524
|
+
});
|
|
25525
|
+
return printRaw(root);
|
|
25526
|
+
}
|
|
25527
|
+
|
|
25269
25528
|
// src/source.js
|
|
25270
25529
|
var DEFAULT_LIBRARIES = ["calc", "intersections", "angles", "quotes", "arrows.meta", "positioning"];
|
|
25271
25530
|
var TikzSourceError = class extends Error {
|
|
@@ -25305,8 +25564,8 @@ function definedMacroNames(text) {
|
|
|
25305
25564
|
if (isMacro(array[j])) names.add(array[j].content);
|
|
25306
25565
|
}
|
|
25307
25566
|
} else if (node.content === "tikzmath") {
|
|
25308
|
-
const
|
|
25309
|
-
if (isGroup(
|
|
25567
|
+
const group3 = array[skipSpace(array, i + 1)];
|
|
25568
|
+
if (isGroup(group3)) walkArrays(group3.content, (tokens) => {
|
|
25310
25569
|
for (let j = 0; j < tokens.length; j++) if (isMacro(tokens[j]) && isString(tokens[skipSpace(tokens, j + 1)], "=")) names.add(tokens[j].content);
|
|
25311
25570
|
});
|
|
25312
25571
|
} else if (node.content === "pgfkeysgetvalue") {
|
|
@@ -25719,13 +25978,29 @@ function processKeyList(nodes, context) {
|
|
|
25719
25978
|
for (const item of items) {
|
|
25720
25979
|
const parts = item.itemParts ?? [];
|
|
25721
25980
|
if (!parts.length) continue;
|
|
25722
|
-
|
|
25981
|
+
let key = printRaw(parts[0]).trim();
|
|
25723
25982
|
const value = parts[1];
|
|
25983
|
+
if (context.tikz && !key.includes("/") && key.endsWith(" style") && value?.some(isGroup)) {
|
|
25984
|
+
key += "/.style";
|
|
25985
|
+
parts[0] = [str(key)];
|
|
25986
|
+
}
|
|
25724
25987
|
if (value && TEXT_KEYS.has(key)) repairTextNodes(value, context);
|
|
25725
25988
|
if (value && /^(?:xtick|ytick|ztick)labels$|^legend entries$/.test(key)) {
|
|
25726
25989
|
for (const node of value) if (isGroup(node)) repairTextNodes(node.content, context);
|
|
25727
25990
|
}
|
|
25728
25991
|
const styleName = /^(.+?)\/\.(?:style|append style)$/.exec(key)?.[1];
|
|
25992
|
+
if (styleName && ["name", "label"].includes(styleName)) {
|
|
25993
|
+
const alias = `tikz recovered ${styleName} style`;
|
|
25994
|
+
context.styleAliases?.set(styleName, alias);
|
|
25995
|
+
parts[0] = [str(key.replace(styleName, alias))];
|
|
25996
|
+
} else if (!value && context.styleAliases?.has(key)) parts[0] = [str(context.styleAliases.get(key))];
|
|
25997
|
+
if (value && /^(above|below|left|right)( left| right)?$/.test(key)) {
|
|
25998
|
+
const target = value.findIndex((node) => isString(node, "of"));
|
|
25999
|
+
const point2 = target >= 0 ? skipSpace(value, target + 1) : -1;
|
|
26000
|
+
if (point2 >= 0 && value[point2]?.type === "inlinemath") {
|
|
26001
|
+
parts[1] = [{ type: "group", content: value }];
|
|
26002
|
+
}
|
|
26003
|
+
}
|
|
25729
26004
|
if (styleName && value) {
|
|
25730
26005
|
for (const node of value) if (isGroup(node)) unloopStyle(node.content, styleName);
|
|
25731
26006
|
}
|
|
@@ -25775,6 +26050,16 @@ function mergeParenthesisedValues(items) {
|
|
|
25775
26050
|
for (let i = 0; i < items.length; i++) {
|
|
25776
26051
|
const item = items[i];
|
|
25777
26052
|
const parts = item.itemParts ?? [];
|
|
26053
|
+
if (parts.length === 2 && /^(above|below|left|right)( left| right)?$/.test(printRaw(parts[0]).trim())) {
|
|
26054
|
+
const of = parts[1].findIndex((node) => isString(node, "of"));
|
|
26055
|
+
const number = (tokens) => /^-?\d+(?:\.\d+)?(?:cm|mm|pt)?$/.test(printRaw(tokens).trim());
|
|
26056
|
+
const next = items[i + 1]?.itemParts;
|
|
26057
|
+
if (of >= 0 && number(parts[1].slice(of + 1)) && next?.length === 1 && number(next[0])) {
|
|
26058
|
+
out.push({ ...item, itemParts: [parts[0], [{ type: "group", content: [...parts[1], str(","), ...next[0]] }]] });
|
|
26059
|
+
i++;
|
|
26060
|
+
continue;
|
|
26061
|
+
}
|
|
26062
|
+
}
|
|
25778
26063
|
if (parts.length !== 2 || balance(parts[1]) <= 0) {
|
|
25779
26064
|
out.push(item);
|
|
25780
26065
|
continue;
|
|
@@ -25869,7 +26154,7 @@ function processKeyLists(root, context) {
|
|
|
25869
26154
|
continue;
|
|
25870
26155
|
}
|
|
25871
26156
|
if (node?.type === "environment" && Array.isArray(node.args)) {
|
|
25872
|
-
for (const argument2 of node.args) if (argument2.openMark === "[") processKeyList(argument2.content, context);
|
|
26157
|
+
for (const argument2 of node.args) if (argument2.openMark === "[") processKeyList(argument2.content, { ...context, tikz: ["tikzpicture", "scope", "circuitikz"].includes(node.env) });
|
|
25873
26158
|
}
|
|
25874
26159
|
if (isMacro(node) && KEY_LIST_MACROS.has(node.content) && hasArgs(node)) {
|
|
25875
26160
|
for (const argument2 of node.args) if (argument2.openMark === "{") processKeyList(argument2.content, context);
|
|
@@ -26136,6 +26421,25 @@ function repairForeachLists(root) {
|
|
|
26136
26421
|
}
|
|
26137
26422
|
});
|
|
26138
26423
|
}
|
|
26424
|
+
function repairBoldMath(root) {
|
|
26425
|
+
walkArrays(root, (array) => {
|
|
26426
|
+
if (!array.some((node) => node.type === "inlinemath")) return;
|
|
26427
|
+
let bold = false;
|
|
26428
|
+
for (let i = 0; i < array.length; i++) {
|
|
26429
|
+
if (isMacro(array[i], "boldmath")) {
|
|
26430
|
+
bold = true;
|
|
26431
|
+
array.splice(i--, 1);
|
|
26432
|
+
continue;
|
|
26433
|
+
}
|
|
26434
|
+
if (isMacro(array[i], "unboldmath")) {
|
|
26435
|
+
bold = false;
|
|
26436
|
+
array.splice(i--, 1);
|
|
26437
|
+
continue;
|
|
26438
|
+
}
|
|
26439
|
+
if (bold && array[i].type === "inlinemath") array[i].content = [macro2("boldsymbol", [{ type: "argument", openMark: "{", closeMark: "}", content: array[i].content }])];
|
|
26440
|
+
}
|
|
26441
|
+
});
|
|
26442
|
+
}
|
|
26139
26443
|
function mathOnly(nodes) {
|
|
26140
26444
|
if (nodes.some((node) => node.type === "inlinemath" || node.type === "displaymath")) return false;
|
|
26141
26445
|
return needsMath(nodes.filter((node) => !isSpace(node)));
|
|
@@ -26158,7 +26462,7 @@ function stripOverlayKeys(root) {
|
|
|
26158
26462
|
}
|
|
26159
26463
|
}
|
|
26160
26464
|
function prepareTikzDocument(code) {
|
|
26161
|
-
const cleaned = cleanInput(code);
|
|
26465
|
+
const cleaned = recoverGeneratedSyntax(cleanInput(code));
|
|
26162
26466
|
if (!cleaned) throw new TikzSourceError("TikZ source is empty.");
|
|
26163
26467
|
const state = {
|
|
26164
26468
|
packages: /* @__PURE__ */ new Map(),
|
|
@@ -26180,15 +26484,17 @@ function prepareTikzDocument(code) {
|
|
|
26180
26484
|
const unicodeSeen = /* @__PURE__ */ new Set();
|
|
26181
26485
|
const colorsDefined = /* @__PURE__ */ new Set();
|
|
26182
26486
|
const colorsSeen = /* @__PURE__ */ new Set();
|
|
26183
|
-
|
|
26487
|
+
const keyContext = { styleAliases: /* @__PURE__ */ new Map() };
|
|
26488
|
+
for (const root of [statementsRoot, body]) {
|
|
26184
26489
|
rewriteHexColors(root);
|
|
26185
26490
|
replaceUnavailableMacros(root, state);
|
|
26186
|
-
processKeyLists(root,
|
|
26491
|
+
processKeyLists(root, keyContext);
|
|
26187
26492
|
}
|
|
26188
26493
|
stripOverlayKeys(body);
|
|
26189
26494
|
protectAndDelimiter(body);
|
|
26190
26495
|
repairForeachLists(body);
|
|
26191
26496
|
replaceTypos(body);
|
|
26497
|
+
repairBoldMath(body);
|
|
26192
26498
|
repairNodeTexts(body);
|
|
26193
26499
|
unicodeSupport(body, unicodeSeen, unicode);
|
|
26194
26500
|
unicodeSupport(statementsRoot, unicodeSeen, unicode);
|
|
@@ -26223,6 +26529,12 @@ ${declarations}`);
|
|
|
26223
26529
|
if (state.gdLibraries.size) lines.push(`\\usegdlibrary{${[...state.gdLibraries].join(",")}}`);
|
|
26224
26530
|
if (state.packages.has("pgfplots") && !state.compat) lines.push("\\pgfplotsset{compat=1.18}");
|
|
26225
26531
|
lines.push(...unicode, ...colors, COMPAT_SHIM);
|
|
26532
|
+
if (!excluded.has("pgfmathdistance") && /\\pgfmathdistance\b/.test(everything)) lines.push(String.raw`\makeatletter
|
|
26533
|
+
\providecommand{\pgfmathdistance}[2]{\pgfpointdiff{#1}{#2}\pgfmathveclen{\the\pgf@x}{\the\pgf@y}}
|
|
26534
|
+
\makeatother`);
|
|
26535
|
+
if (/\bparallelogram\b/.test(everything)) lines.push(String.raw`\pgfkeysifdefined{/tikz/parallelogram/.@cmd}{}{\tikzset{parallelogram/.style={shape=trapezium,trapezium left angle=70,trapezium right angle=110}}}`);
|
|
26536
|
+
lines.push(String.raw`\pgfkeysifdefined{/tikz/rounded cap/.@cmd}{}{\tikzset{rounded cap/.style={line cap=round}}}
|
|
26537
|
+
\pgfkeysifdefined{/tikz/final/.@cmd}{}{\tikzset{final/.style={accepting}}}`);
|
|
26226
26538
|
if (state.shims.has("siunitx")) lines.push(siunitxShim());
|
|
26227
26539
|
if (state.shims.has("physics")) lines.push(PHYSICS_SHIM);
|
|
26228
26540
|
if (state.shims.has("upgreek")) lines.push(...GREEK_NAMES.map((name) => `\\providecommand{\\up${name}}{\\ensuremath{\\${name}}}`));
|