@knowvah/dot-engine 2.6.1 → 2.6.3
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/dist/common/htmltable-lex.d.ts +38 -0
- package/dist/common/htmltable-lex.d.ts.map +1 -1
- package/dist/common/htmltable-parse-attrs.d.ts +41 -0
- package/dist/common/htmltable-parse-attrs.d.ts.map +1 -0
- package/dist/common/htmltable-parse.d.ts +3 -0
- package/dist/common/htmltable-parse.d.ts.map +1 -1
- package/dist/common/htmltable-pos.d.ts +17 -0
- package/dist/common/htmltable-pos.d.ts.map +1 -1
- package/dist/common/htmltable.d.ts +13 -1
- package/dist/common/htmltable.d.ts.map +1 -1
- package/dist/common/make-label.d.ts.map +1 -1
- package/dist/common/pointset.d.ts +35 -0
- package/dist/common/pointset.d.ts.map +1 -0
- package/dist/common/spline-midpoint.d.ts +8 -0
- package/dist/common/spline-midpoint.d.ts.map +1 -1
- package/dist/index.js +639 -315
- package/dist/index.js.map +4 -4
- package/dist/label/node.d.ts +7 -1
- package/dist/label/node.d.ts.map +1 -1
- package/dist/layout/circo/position-helpers.d.ts +15 -3
- package/dist/layout/circo/position-helpers.d.ts.map +1 -1
- package/dist/layout/circo/position.d.ts +17 -1
- package/dist/layout/circo/position.d.ts.map +1 -1
- package/dist/layout/dot/ortho-adapter.d.ts.map +1 -1
- package/dist/layout/neato/multispline.d.ts.map +1 -1
- package/dist/layout/pack/poly-pack.d.ts +2 -18
- package/dist/layout/pack/poly-pack.d.ts.map +1 -1
- package/dist/layout/pack/poly-place.d.ts.map +1 -1
- package/dist/pathplan/shortest.d.ts.map +1 -1
- package/dist/render.js +792 -468
- package/dist/render.js.map +4 -4
- package/package.json +2 -2
- package/src/common/htmltable-lex.ts +265 -5
- package/src/common/htmltable-parse-attrs.ts +166 -0
- package/src/common/htmltable-parse.ts +262 -242
- package/src/common/htmltable-pos.ts +37 -38
- package/src/common/htmltable.ts +139 -45
- package/src/common/make-label.ts +19 -3
- package/src/common/pointset.ts +73 -0
- package/src/common/spline-midpoint.ts +30 -9
- package/src/label/node.ts +8 -2
- package/src/layout/circo/position-helpers.ts +28 -17
- package/src/layout/circo/position.ts +28 -7
- package/src/layout/dot/ortho-adapter.ts +20 -9
- package/src/layout/neato/multispline.ts +17 -5
- package/src/layout/pack/poly-pack.ts +5 -31
- package/src/layout/pack/poly-place.ts +42 -47
- package/src/pathplan/shortest.ts +15 -2
package/dist/render.js
CHANGED
|
@@ -5854,16 +5854,152 @@ function parseOpenToken(inner) {
|
|
|
5854
5854
|
checkTag(tag);
|
|
5855
5855
|
return { type: "open", tag: normalizeTag(tag), attrs: parseAttrs(inner.slice(sp + 1)) };
|
|
5856
5856
|
}
|
|
5857
|
-
|
|
5857
|
+
var XML_ERROR_UNDEFINED_ENTITY = "undefined entity";
|
|
5858
|
+
var XML_ERROR_TAG_MISMATCH = "mismatched tag";
|
|
5859
|
+
var XML_ERROR_INVALID_TOKEN = "not well-formed (invalid token)";
|
|
5860
|
+
var XML_ERROR_DUPLICATE_ATTRIBUTE = "duplicate attribute";
|
|
5861
|
+
var XML_PREDEFINED_ENTITIES = /* @__PURE__ */ new Set(["lt", "gt", "amp", "quot", "apos"]);
|
|
5862
|
+
var XML_NAME = /^[A-Za-z_:][\w.:-]*$/;
|
|
5863
|
+
var HtmlLexError = class extends HtmlParseError {
|
|
5864
|
+
diagnostics;
|
|
5865
|
+
constructor(tag, message, diagnostics) {
|
|
5866
|
+
super(tag);
|
|
5867
|
+
this.message = message;
|
|
5868
|
+
this.diagnostics = diagnostics;
|
|
5869
|
+
}
|
|
5870
|
+
};
|
|
5871
|
+
function htmlErrorInLine(message, line, context) {
|
|
5872
|
+
const text = `${message} in line ${line} `;
|
|
5873
|
+
return new HtmlLexError(message, text, [`Error: ${text}`, `... ${context} ...`]);
|
|
5874
|
+
}
|
|
5875
|
+
var chunkInfo = /* @__PURE__ */ new WeakMap();
|
|
5876
|
+
function lineAt(src, pos) {
|
|
5877
|
+
let line = 1;
|
|
5878
|
+
for (let k = 0; k < pos; k++) {
|
|
5879
|
+
if (src[k] === "\n" || src[k] === "\r" && src[k + 1] !== "\n") line++;
|
|
5880
|
+
}
|
|
5881
|
+
return line;
|
|
5882
|
+
}
|
|
5883
|
+
function chunkLine(info) {
|
|
5884
|
+
if (info.src[info.pos] === "<") return lineAt(info.src, info.pos);
|
|
5885
|
+
const last = info.src.lastIndexOf("\n", info.end - 1);
|
|
5886
|
+
if (last < info.pos) return lineAt(info.src, info.pos);
|
|
5887
|
+
return lineAt(info.src, last === info.end - 1 ? last : last + 1);
|
|
5888
|
+
}
|
|
5889
|
+
function htmlErrorAtToken(message, tok) {
|
|
5890
|
+
const info = tok === void 0 ? void 0 : chunkInfo.get(tok);
|
|
5891
|
+
if (info === void 0) return void 0;
|
|
5892
|
+
return htmlErrorInLine(message, chunkLine(info), info.context);
|
|
5893
|
+
}
|
|
5894
|
+
function chunkEnd(src, i) {
|
|
5895
|
+
const j = src[i] === "<" ? src.indexOf(">", i + 1) : src.indexOf("<", i);
|
|
5896
|
+
if (j < 0) return src.length;
|
|
5897
|
+
return src[i] === "<" ? j + 1 : j;
|
|
5898
|
+
}
|
|
5899
|
+
function findUndefinedEntity(text) {
|
|
5900
|
+
for (let t = text.indexOf("&"); t >= 0; t = text.indexOf("&", t + 1)) {
|
|
5901
|
+
if (text[t + 1] === "#") continue;
|
|
5902
|
+
const semi = text.indexOf(";", t + 1);
|
|
5903
|
+
if (semi < 0) continue;
|
|
5904
|
+
const key = text.slice(t + 1, semi);
|
|
5905
|
+
if (XML_NAME.test(key) && !Object.hasOwn(HTML_ENTITIES, key) && !XML_PREDEFINED_ENTITIES.has(key)) {
|
|
5906
|
+
return t;
|
|
5907
|
+
}
|
|
5908
|
+
}
|
|
5909
|
+
return -1;
|
|
5910
|
+
}
|
|
5911
|
+
function parseTagChunk(chunk) {
|
|
5912
|
+
if (!chunk.endsWith(">")) return void 0;
|
|
5913
|
+
const body = chunk.slice(1, -1);
|
|
5914
|
+
if (body.startsWith("!")) return void 0;
|
|
5915
|
+
const close = body.startsWith("/");
|
|
5916
|
+
const name = /^[^\s/>]*/.exec(close ? body.slice(1) : body)?.[0] ?? "";
|
|
5917
|
+
return { close, selfClose: !close && body.endsWith("/"), name };
|
|
5918
|
+
}
|
|
5919
|
+
var ATTR_NAME = /^[A-Za-z_:][\w.:-]*/;
|
|
5920
|
+
var isSpace = (c) => c !== void 0 && /\s/.test(c);
|
|
5921
|
+
var invalidToken = (offset) => ({ message: XML_ERROR_INVALID_TOKEN, offset });
|
|
5922
|
+
function skipSpace(chunk, i) {
|
|
5923
|
+
let j = i;
|
|
5924
|
+
while (isSpace(chunk[j])) j++;
|
|
5925
|
+
return j;
|
|
5926
|
+
}
|
|
5927
|
+
function readAttrPair(chunk, i) {
|
|
5928
|
+
const name = ATTR_NAME.exec(chunk.slice(i))?.[0];
|
|
5929
|
+
if (name === void 0) return invalidToken(i);
|
|
5930
|
+
let j = skipSpace(chunk, i + name.length);
|
|
5931
|
+
if (chunk[j] !== "=") return invalidToken(j);
|
|
5932
|
+
j = skipSpace(chunk, j + 1);
|
|
5933
|
+
const q = chunk[j];
|
|
5934
|
+
if (q !== '"' && q !== "'") return invalidToken(j);
|
|
5935
|
+
const end = chunk.indexOf(q, j + 1);
|
|
5936
|
+
return end < 0 ? void 0 : { name, next: end + 1 };
|
|
5937
|
+
}
|
|
5938
|
+
function findAttrError(chunk, from) {
|
|
5939
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5940
|
+
let dup;
|
|
5941
|
+
let i = skipSpace(chunk, from);
|
|
5942
|
+
while (chunk[i] !== ">" && !(chunk[i] === "/" && chunk[i + 1] === ">")) {
|
|
5943
|
+
const pair = readAttrPair(chunk, i);
|
|
5944
|
+
if (pair === void 0) return void 0;
|
|
5945
|
+
if ("message" in pair) return pair;
|
|
5946
|
+
if (seen.has(pair.name) && dup === void 0) dup = { message: XML_ERROR_DUPLICATE_ATTRIBUTE, offset: i };
|
|
5947
|
+
seen.add(pair.name);
|
|
5948
|
+
i = skipSpace(chunk, pair.next);
|
|
5949
|
+
}
|
|
5950
|
+
return dup;
|
|
5951
|
+
}
|
|
5952
|
+
function checkTagChunk(src, start, st) {
|
|
5953
|
+
const tag = parseTagChunk(st.curr);
|
|
5954
|
+
if (tag === void 0) return;
|
|
5955
|
+
if (tag.close) {
|
|
5956
|
+
if (st.stack.length > 0 && st.stack.pop() !== tag.name) {
|
|
5957
|
+
throw htmlErrorInLine(XML_ERROR_TAG_MISMATCH, lineAt(src, start), st.prev + st.curr);
|
|
5958
|
+
}
|
|
5959
|
+
} else {
|
|
5960
|
+
const bad = findAttrError(st.curr, 1 + tag.name.length);
|
|
5961
|
+
if (bad !== void 0) {
|
|
5962
|
+
throw htmlErrorInLine(bad.message, lineAt(src, start + bad.offset), st.prev + st.curr);
|
|
5963
|
+
}
|
|
5964
|
+
if (!tag.selfClose) st.stack.push(tag.name);
|
|
5965
|
+
}
|
|
5966
|
+
if (KNOWN_TAGS.has(tag.name.toUpperCase())) return;
|
|
5967
|
+
const text = `Unknown HTML element <${tag.name}> on line ${lineAt(src, start)} `;
|
|
5968
|
+
throw new HtmlLexError(tag.name.toUpperCase(), text, [`Error: ${text}`]);
|
|
5969
|
+
}
|
|
5970
|
+
function checkChunk(src, start, st) {
|
|
5971
|
+
if (st.curr.startsWith("<")) {
|
|
5972
|
+
checkTagChunk(src, start, st);
|
|
5973
|
+
return;
|
|
5974
|
+
}
|
|
5975
|
+
const off = findUndefinedEntity(st.curr);
|
|
5976
|
+
if (off >= 0) {
|
|
5977
|
+
throw htmlErrorInLine(XML_ERROR_UNDEFINED_ENTITY, lineAt(src, start + off), st.prev + st.curr);
|
|
5978
|
+
}
|
|
5979
|
+
}
|
|
5980
|
+
function tokenizeDeferred(src) {
|
|
5858
5981
|
const tokens = [];
|
|
5982
|
+
const st = { stack: [], prev: "", curr: "" };
|
|
5859
5983
|
let i = 0;
|
|
5860
|
-
|
|
5861
|
-
|
|
5984
|
+
try {
|
|
5985
|
+
while (i < src.length) {
|
|
5986
|
+
const first = tokens.length;
|
|
5987
|
+
const start = i;
|
|
5988
|
+
st.prev = st.curr;
|
|
5989
|
+
st.curr = src.slice(i, chunkEnd(src, i));
|
|
5990
|
+
checkChunk(src, i, st);
|
|
5991
|
+
i = src[i] === "<" ? scanTag(src, i, tokens) : scanText(src, i, tokens);
|
|
5992
|
+
const info = { src, pos: start, end: i, context: st.prev + st.curr };
|
|
5993
|
+
for (let k = first; k < tokens.length; k++) chunkInfo.set(tokens[k], info);
|
|
5994
|
+
}
|
|
5995
|
+
} catch (e) {
|
|
5996
|
+
if (e instanceof HtmlParseError) return { tokens, error: e };
|
|
5997
|
+
throw e;
|
|
5862
5998
|
}
|
|
5863
|
-
return tokens;
|
|
5999
|
+
return { tokens };
|
|
5864
6000
|
}
|
|
5865
6001
|
|
|
5866
|
-
// src/common/htmltable-parse.ts
|
|
6002
|
+
// src/common/htmltable-parse-attrs.ts
|
|
5867
6003
|
function anchorAttr(v) {
|
|
5868
6004
|
return v === void 0 ? void 0 : htmlEntityUTF8(v);
|
|
5869
6005
|
}
|
|
@@ -5886,6 +6022,81 @@ var num = (s) => {
|
|
|
5886
6022
|
const n = parseInt(s, 10);
|
|
5887
6023
|
return isNaN(n) ? void 0 : n;
|
|
5888
6024
|
};
|
|
6025
|
+
var parseFixedSize = (a) => a["fixedsize"]?.toUpperCase() === "TRUE" ? true : void 0;
|
|
6026
|
+
var parseTitle = (a) => a["title"] !== void 0 ? a["title"] : a["tooltip"];
|
|
6027
|
+
var parseSides = (v) => {
|
|
6028
|
+
if (v === void 0) return void 0;
|
|
6029
|
+
let flags = 0;
|
|
6030
|
+
for (const c of v.toLowerCase()) {
|
|
6031
|
+
if (c === "l") flags |= BORDER_LEFT;
|
|
6032
|
+
else if (c === "t") flags |= BORDER_TOP;
|
|
6033
|
+
else if (c === "r") flags |= BORDER_RIGHT;
|
|
6034
|
+
else if (c === "b") flags |= BORDER_BOTTOM;
|
|
6035
|
+
}
|
|
6036
|
+
if (flags === 0 || flags === BORDER_MASK) return void 0;
|
|
6037
|
+
return flags;
|
|
6038
|
+
};
|
|
6039
|
+
var parseGradientAngle = (v) => {
|
|
6040
|
+
if (v === void 0) return void 0;
|
|
6041
|
+
const n = parseInt(v, 10);
|
|
6042
|
+
if (isNaN(n) || String(n) !== v.trim()) return void 0;
|
|
6043
|
+
if (n < 0 || n > 360) return void 0;
|
|
6044
|
+
return n;
|
|
6045
|
+
};
|
|
6046
|
+
var parseColumns = (v) => v === "*" ? true : void 0;
|
|
6047
|
+
var parseRows = (v) => v === "*" ? true : void 0;
|
|
6048
|
+
var buildCell = (content, a) => ({
|
|
6049
|
+
kind: "cell",
|
|
6050
|
+
content,
|
|
6051
|
+
port: a["port"],
|
|
6052
|
+
align: parseAlign(a["align"] !== void 0 ? a["align"] : ""),
|
|
6053
|
+
valign: parseVAlign(a["valign"] !== void 0 ? a["valign"] : ""),
|
|
6054
|
+
balign: parseAlign(a["balign"] !== void 0 ? a["balign"] : ""),
|
|
6055
|
+
bgcolor: a["bgcolor"],
|
|
6056
|
+
color: a["color"],
|
|
6057
|
+
border: num(a["border"]),
|
|
6058
|
+
cellpadding: num(a["cellpadding"]),
|
|
6059
|
+
cellspacing: num(a["cellspacing"]),
|
|
6060
|
+
sides: parseSides(a["sides"]),
|
|
6061
|
+
gradientangle: parseGradientAngle(a["gradientangle"]),
|
|
6062
|
+
style: a["style"],
|
|
6063
|
+
width: num(a["width"]),
|
|
6064
|
+
height: num(a["height"]),
|
|
6065
|
+
fixedsize: parseFixedSize(a),
|
|
6066
|
+
colspan: num(a["colspan"]),
|
|
6067
|
+
rowspan: num(a["rowspan"]),
|
|
6068
|
+
href: anchorAttr(a["href"]),
|
|
6069
|
+
title: parseTitle(a),
|
|
6070
|
+
target: anchorAttr(a["target"]),
|
|
6071
|
+
id: a["id"]
|
|
6072
|
+
});
|
|
6073
|
+
var buildTable = (rows, a) => ({
|
|
6074
|
+
kind: "table",
|
|
6075
|
+
rows,
|
|
6076
|
+
border: num(a["border"]),
|
|
6077
|
+
cellborder: num(a["cellborder"]),
|
|
6078
|
+
cellspacing: num(a["cellspacing"]),
|
|
6079
|
+
cellpadding: num(a["cellpadding"]),
|
|
6080
|
+
bgcolor: a["bgcolor"],
|
|
6081
|
+
color: a["color"],
|
|
6082
|
+
style: a["style"],
|
|
6083
|
+
align: parseAlign(a["align"] !== void 0 ? a["align"] : ""),
|
|
6084
|
+
valign: parseVAlign(a["valign"] !== void 0 ? a["valign"] : ""),
|
|
6085
|
+
fixedsize: parseFixedSize(a),
|
|
6086
|
+
width: num(a["width"]),
|
|
6087
|
+
height: num(a["height"]),
|
|
6088
|
+
href: anchorAttr(a["href"]),
|
|
6089
|
+
title: parseTitle(a),
|
|
6090
|
+
target: anchorAttr(a["target"]),
|
|
6091
|
+
id: a["id"],
|
|
6092
|
+
port: a["port"],
|
|
6093
|
+
sides: parseSides(a["sides"]),
|
|
6094
|
+
gradientangle: parseGradientAngle(a["gradientangle"]),
|
|
6095
|
+
vrule: parseColumns(a["columns"]),
|
|
6096
|
+
hrule: parseRows(a["rows"])
|
|
6097
|
+
});
|
|
6098
|
+
|
|
6099
|
+
// src/common/htmltable-parse.ts
|
|
5889
6100
|
var definedOf = (s) => Object.fromEntries(
|
|
5890
6101
|
Object.entries(s).filter(([, v]) => v !== void 0)
|
|
5891
6102
|
);
|
|
@@ -5909,6 +6120,11 @@ var fontItemProps = (f) => {
|
|
|
5909
6120
|
if (f.fontSize !== void 0) out.fontSize = f.fontSize;
|
|
5910
6121
|
return out;
|
|
5911
6122
|
};
|
|
6123
|
+
var MSG_SYNTAX_ERROR = "syntax error";
|
|
6124
|
+
var MSG_TEXT_BEFORE_TABLE = "Syntax error: non-space string used before <TABLE>";
|
|
6125
|
+
var MSG_TEXT_AFTER_TABLE = "Syntax error: non-space string used after </TABLE>";
|
|
6126
|
+
var nonSpace = (text) => /[^ \t\n\r]/.test(text);
|
|
6127
|
+
var parseError = (s, tok, message) => (tok === void 0 ? s.pending : htmlErrorAtToken(message, tok)) ?? new HtmlParseError(message);
|
|
5912
6128
|
var peek = (s) => s.tokens[s.pos];
|
|
5913
6129
|
var consume = (s) => {
|
|
5914
6130
|
const t = s.tokens[s.pos];
|
|
@@ -5927,12 +6143,20 @@ var inlineFontState = (tag, _attrs) => {
|
|
|
5927
6143
|
if (tag === "SUP") fs.superscript = true;
|
|
5928
6144
|
return fs;
|
|
5929
6145
|
};
|
|
6146
|
+
var consumeClose = (s, tag) => {
|
|
6147
|
+
const nxt = peek(s);
|
|
6148
|
+
if (nxt === void 0) return;
|
|
6149
|
+
if (nxt.type === "close" && nxt.tag === tag) {
|
|
6150
|
+
consume(s);
|
|
6151
|
+
return;
|
|
6152
|
+
}
|
|
6153
|
+
throw parseError(s, nxt, MSG_SYNTAX_ERROR);
|
|
6154
|
+
};
|
|
5930
6155
|
var applyBrTag = (s, t, fontStack, items) => {
|
|
5931
6156
|
consume(s);
|
|
5932
6157
|
const font = fontStack[fontStack.length - 1] ?? {};
|
|
5933
6158
|
items.push({ br: true, brAlign: parseAlign(t.attrs["align"] ?? ""), ...fontItemProps(font) });
|
|
5934
|
-
|
|
5935
|
-
if (nxt?.type === "close" && nxt.tag === "BR") consume(s);
|
|
6159
|
+
consumeClose(s, "BR");
|
|
5936
6160
|
};
|
|
5937
6161
|
var applyFontTag = (s, t, fontStack, items) => {
|
|
5938
6162
|
consume(s);
|
|
@@ -5989,12 +6213,6 @@ var parseText = (s, fontStack) => {
|
|
|
5989
6213
|
}
|
|
5990
6214
|
return { kind: "text", items };
|
|
5991
6215
|
};
|
|
5992
|
-
var parseHrContent = (s) => {
|
|
5993
|
-
consume(s);
|
|
5994
|
-
const nxt = peek(s);
|
|
5995
|
-
if (nxt?.type === "close" && nxt.tag === "HR") consume(s);
|
|
5996
|
-
return { kind: "hr" };
|
|
5997
|
-
};
|
|
5998
6216
|
var parseImgContent = (s, t, cellAttrs) => {
|
|
5999
6217
|
consume(s);
|
|
6000
6218
|
const img = {
|
|
@@ -6002,24 +6220,54 @@ var parseImgContent = (s, t, cellAttrs) => {
|
|
|
6002
6220
|
src: cellAttrs["src"] ?? t.attrs["src"] ?? "",
|
|
6003
6221
|
scale: t.attrs["scale"]
|
|
6004
6222
|
};
|
|
6005
|
-
|
|
6006
|
-
if (nxt?.type === "close" && nxt.tag === "IMG") consume(s);
|
|
6223
|
+
consumeClose(s, "IMG");
|
|
6007
6224
|
return img;
|
|
6008
6225
|
};
|
|
6009
|
-
var
|
|
6010
|
-
if (
|
|
6011
|
-
if (
|
|
6012
|
-
|
|
6226
|
+
var scanCellTable = (s, t, fontStack, st) => {
|
|
6227
|
+
if (st.kind === "image" || st.kind === "table") throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6228
|
+
if (st.textNonSpace) throw parseError(s, t, MSG_TEXT_BEFORE_TABLE);
|
|
6229
|
+
const tbl = parseTable(s, fontStack);
|
|
6230
|
+
st.kind = "table";
|
|
6231
|
+
return [tbl];
|
|
6232
|
+
};
|
|
6233
|
+
var scanCellText = (s, t, fontStack, st) => {
|
|
6234
|
+
const start = s.pos;
|
|
6013
6235
|
const txt = parseText(s, fontStack);
|
|
6236
|
+
if (s.pos === start) throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6237
|
+
if (txt.items.some((i) => i.text !== void 0 && nonSpace(i.text))) st.textNonSpace = true;
|
|
6238
|
+
st.kind = "text";
|
|
6014
6239
|
return txt.items.length > 0 ? [txt] : [];
|
|
6015
6240
|
};
|
|
6241
|
+
var scanAfterTable = (s, t, st) => {
|
|
6242
|
+
if (t.type !== "text") throw parseError(s, t, st.afterNonSpace ? MSG_TEXT_AFTER_TABLE : MSG_SYNTAX_ERROR);
|
|
6243
|
+
consume(s);
|
|
6244
|
+
if (nonSpace(t.value)) st.afterNonSpace = true;
|
|
6245
|
+
return [];
|
|
6246
|
+
};
|
|
6247
|
+
var scanCellImage = (s, t, cellAttrs, st) => {
|
|
6248
|
+
if (st.kind !== "none") throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6249
|
+
st.kind = "image";
|
|
6250
|
+
return [parseImgContent(s, t, cellAttrs)];
|
|
6251
|
+
};
|
|
6252
|
+
var scanCellItem = (s, t, cellAttrs, fontStack, st) => {
|
|
6253
|
+
if (st.kind === "table") return scanAfterTable(s, t, st);
|
|
6254
|
+
if (t.type === "open" && t.tag === "TABLE") return scanCellTable(s, t, fontStack, st);
|
|
6255
|
+
if (t.type === "open" && t.tag === "IMG") return scanCellImage(s, t, cellAttrs, st);
|
|
6256
|
+
if (st.kind === "image") throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6257
|
+
return scanCellText(s, t, fontStack, st);
|
|
6258
|
+
};
|
|
6259
|
+
var endsCell = (s, t, st) => {
|
|
6260
|
+
if (t.type !== "close") return false;
|
|
6261
|
+
const afterText = st.kind === "table" && st.afterNonSpace;
|
|
6262
|
+
if (t.tag === "TD" && !afterText) return true;
|
|
6263
|
+
throw parseError(s, t, afterText ? MSG_TEXT_AFTER_TABLE : MSG_SYNTAX_ERROR);
|
|
6264
|
+
};
|
|
6016
6265
|
var parseCellContent = (s, cellAttrs, fontStack) => {
|
|
6017
6266
|
const content = [];
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
if (
|
|
6021
|
-
|
|
6022
|
-
content.push(...parseCellItem(s, t, cellAttrs, fontStack));
|
|
6267
|
+
const st = { kind: "none", textNonSpace: false, afterNonSpace: false };
|
|
6268
|
+
for (let t = peek(s); t !== void 0; t = peek(s)) {
|
|
6269
|
+
if (endsCell(s, t, st)) break;
|
|
6270
|
+
content.push(...scanCellItem(s, t, cellAttrs, fontStack, st));
|
|
6023
6271
|
}
|
|
6024
6272
|
const nxt = peek(s);
|
|
6025
6273
|
if (nxt?.type === "close" && nxt.tag === "TD") consume(s);
|
|
@@ -6027,134 +6275,85 @@ var parseCellContent = (s, cellAttrs, fontStack) => {
|
|
|
6027
6275
|
if (tbl !== void 0) return [tbl];
|
|
6028
6276
|
return content;
|
|
6029
6277
|
};
|
|
6030
|
-
var parseFixedSize = (a) => a["fixedsize"]?.toUpperCase() === "TRUE" ? true : void 0;
|
|
6031
|
-
var parseTitle = (a) => a["title"] !== void 0 ? a["title"] : a["tooltip"];
|
|
6032
|
-
var parseSides = (v) => {
|
|
6033
|
-
if (v === void 0) return void 0;
|
|
6034
|
-
let flags = 0;
|
|
6035
|
-
for (const c of v.toLowerCase()) {
|
|
6036
|
-
if (c === "l") flags |= BORDER_LEFT;
|
|
6037
|
-
else if (c === "t") flags |= BORDER_TOP;
|
|
6038
|
-
else if (c === "r") flags |= BORDER_RIGHT;
|
|
6039
|
-
else if (c === "b") flags |= BORDER_BOTTOM;
|
|
6040
|
-
}
|
|
6041
|
-
if (flags === 0 || flags === BORDER_MASK) return void 0;
|
|
6042
|
-
return flags;
|
|
6043
|
-
};
|
|
6044
|
-
var parseGradientAngle = (v) => {
|
|
6045
|
-
if (v === void 0) return void 0;
|
|
6046
|
-
const n = parseInt(v, 10);
|
|
6047
|
-
if (isNaN(n) || String(n) !== v.trim()) return void 0;
|
|
6048
|
-
if (n < 0 || n > 360) return void 0;
|
|
6049
|
-
return n;
|
|
6050
|
-
};
|
|
6051
|
-
var parseColumns = (v) => v === "*" ? true : void 0;
|
|
6052
|
-
var parseRows = (v) => v === "*" ? true : void 0;
|
|
6053
|
-
var buildCell = (content, a) => ({
|
|
6054
|
-
kind: "cell",
|
|
6055
|
-
content,
|
|
6056
|
-
port: a["port"],
|
|
6057
|
-
align: parseAlign(a["align"] !== void 0 ? a["align"] : ""),
|
|
6058
|
-
valign: parseVAlign(a["valign"] !== void 0 ? a["valign"] : ""),
|
|
6059
|
-
balign: parseAlign(a["balign"] !== void 0 ? a["balign"] : ""),
|
|
6060
|
-
bgcolor: a["bgcolor"],
|
|
6061
|
-
color: a["color"],
|
|
6062
|
-
border: num(a["border"]),
|
|
6063
|
-
cellpadding: num(a["cellpadding"]),
|
|
6064
|
-
cellspacing: num(a["cellspacing"]),
|
|
6065
|
-
sides: parseSides(a["sides"]),
|
|
6066
|
-
gradientangle: parseGradientAngle(a["gradientangle"]),
|
|
6067
|
-
style: a["style"],
|
|
6068
|
-
width: num(a["width"]),
|
|
6069
|
-
height: num(a["height"]),
|
|
6070
|
-
fixedsize: parseFixedSize(a),
|
|
6071
|
-
colspan: num(a["colspan"]),
|
|
6072
|
-
rowspan: num(a["rowspan"]),
|
|
6073
|
-
href: anchorAttr(a["href"]),
|
|
6074
|
-
title: parseTitle(a),
|
|
6075
|
-
target: anchorAttr(a["target"]),
|
|
6076
|
-
id: a["id"]
|
|
6077
|
-
});
|
|
6078
6278
|
var parseCell = (s, attrs, fontStack) => buildCell(parseCellContent(s, attrs, fontStack), attrs);
|
|
6079
|
-
var
|
|
6279
|
+
var parseRowVr = (s, t, cells) => {
|
|
6280
|
+
const prev = cells[cells.length - 1];
|
|
6281
|
+
if (prev === void 0) throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6282
|
+
consume(s);
|
|
6283
|
+
consumeClose(s, "VR");
|
|
6284
|
+
prev.vruled = true;
|
|
6285
|
+
};
|
|
6286
|
+
var scanRowCell = (s, t, fontStack, rs) => {
|
|
6080
6287
|
if (t.type === "open" && t.tag === "TD") {
|
|
6081
6288
|
consume(s);
|
|
6082
|
-
cells.push(parseCell(s, t.attrs, fontStack));
|
|
6083
|
-
|
|
6289
|
+
rs.cells.push(parseCell(s, t.attrs, fontStack));
|
|
6290
|
+
rs.needCell = false;
|
|
6291
|
+
} else if (t.type === "open" && t.tag === "VR" && !rs.needCell) {
|
|
6292
|
+
parseRowVr(s, t, rs.cells);
|
|
6293
|
+
rs.needCell = true;
|
|
6294
|
+
} else {
|
|
6295
|
+
throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6084
6296
|
}
|
|
6085
|
-
|
|
6297
|
+
};
|
|
6298
|
+
var scanRowToken = (s, t, fontStack, rs) => {
|
|
6299
|
+
if (t.type === "text") {
|
|
6086
6300
|
consume(s);
|
|
6087
|
-
|
|
6088
|
-
if (nxt?.type === "close" && nxt.tag === "VR") consume(s);
|
|
6089
|
-
const prev = cells[cells.length - 1];
|
|
6090
|
-
if (prev === void 0) throw new HtmlParseError("VR");
|
|
6091
|
-
prev.vruled = true;
|
|
6092
|
-
return;
|
|
6301
|
+
return false;
|
|
6093
6302
|
}
|
|
6094
|
-
|
|
6303
|
+
if (t.type !== "close" || t.tag !== "TR") {
|
|
6304
|
+
scanRowCell(s, t, fontStack, rs);
|
|
6305
|
+
return false;
|
|
6306
|
+
}
|
|
6307
|
+
if (rs.cells.length === 0 || rs.needCell) throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6308
|
+
return true;
|
|
6095
6309
|
};
|
|
6096
6310
|
var parseRow = (s, fontStack) => {
|
|
6097
|
-
const
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
if (!t) break;
|
|
6101
|
-
if (t.type === "close" && t.tag === "TR") break;
|
|
6102
|
-
processRowToken(s, t, cells, fontStack);
|
|
6311
|
+
const rs = { cells: [], needCell: false };
|
|
6312
|
+
for (let t = peek(s); t !== void 0; t = peek(s)) {
|
|
6313
|
+
if (scanRowToken(s, t, fontStack, rs)) break;
|
|
6103
6314
|
}
|
|
6104
6315
|
const nxt = peek(s);
|
|
6105
6316
|
if (nxt?.type === "close" && nxt.tag === "TR") consume(s);
|
|
6106
|
-
return { cells };
|
|
6317
|
+
return { cells: rs.cells };
|
|
6318
|
+
};
|
|
6319
|
+
var scanTableRow = (s, t, fontStack, ts) => {
|
|
6320
|
+
if (t.type === "open" && t.tag === "TR") {
|
|
6321
|
+
consume(s);
|
|
6322
|
+
ts.rows.push(parseTableRow(s, fontStack, ts));
|
|
6323
|
+
ts.needRow = false;
|
|
6324
|
+
} else if (t.type === "open" && t.tag === "HR" && ts.rows.length > 0 && !ts.needRow) {
|
|
6325
|
+
consumeRowHr(s, ts.rows);
|
|
6326
|
+
ts.needRow = true;
|
|
6327
|
+
} else {
|
|
6328
|
+
throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6329
|
+
}
|
|
6330
|
+
};
|
|
6331
|
+
var scanTableToken = (s, t, fontStack, ts) => {
|
|
6332
|
+
if (t.type === "text") {
|
|
6333
|
+
consume(s);
|
|
6334
|
+
return false;
|
|
6335
|
+
}
|
|
6336
|
+
if (t.type !== "close" || t.tag !== "TABLE") {
|
|
6337
|
+
scanTableRow(s, t, fontStack, ts);
|
|
6338
|
+
return false;
|
|
6339
|
+
}
|
|
6340
|
+
if (ts.rows.length === 0 || ts.needRow) throw parseError(s, t, MSG_SYNTAX_ERROR);
|
|
6341
|
+
consume(s);
|
|
6342
|
+
return true;
|
|
6107
6343
|
};
|
|
6108
|
-
var buildTable = (rows, a) => ({
|
|
6109
|
-
kind: "table",
|
|
6110
|
-
rows,
|
|
6111
|
-
border: num(a["border"]),
|
|
6112
|
-
cellborder: num(a["cellborder"]),
|
|
6113
|
-
cellspacing: num(a["cellspacing"]),
|
|
6114
|
-
cellpadding: num(a["cellpadding"]),
|
|
6115
|
-
bgcolor: a["bgcolor"],
|
|
6116
|
-
color: a["color"],
|
|
6117
|
-
style: a["style"],
|
|
6118
|
-
align: parseAlign(a["align"] !== void 0 ? a["align"] : ""),
|
|
6119
|
-
valign: parseVAlign(a["valign"] !== void 0 ? a["valign"] : ""),
|
|
6120
|
-
fixedsize: parseFixedSize(a),
|
|
6121
|
-
width: num(a["width"]),
|
|
6122
|
-
height: num(a["height"]),
|
|
6123
|
-
href: anchorAttr(a["href"]),
|
|
6124
|
-
title: parseTitle(a),
|
|
6125
|
-
target: anchorAttr(a["target"]),
|
|
6126
|
-
id: a["id"],
|
|
6127
|
-
port: a["port"],
|
|
6128
|
-
sides: parseSides(a["sides"]),
|
|
6129
|
-
gradientangle: parseGradientAngle(a["gradientangle"]),
|
|
6130
|
-
vrule: parseColumns(a["columns"]),
|
|
6131
|
-
hrule: parseRows(a["rows"])
|
|
6132
|
-
});
|
|
6133
6344
|
var parseTable = (s, fontStack) => {
|
|
6134
6345
|
const open = consume(s);
|
|
6135
6346
|
if (open.type !== "open" || open.tag !== "TABLE") throw new HtmlParseError("TABLE");
|
|
6136
|
-
const
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
break;
|
|
6145
|
-
}
|
|
6146
|
-
if (t.type === "open" && t.tag === "TR") {
|
|
6147
|
-
consume(s);
|
|
6148
|
-
rows.push(parseTableRow(s, fontStack, { hrule, vrule }));
|
|
6149
|
-
continue;
|
|
6150
|
-
}
|
|
6151
|
-
if (t.type === "open" && t.tag === "HR") {
|
|
6152
|
-
consumeRowHr(s, rows);
|
|
6153
|
-
continue;
|
|
6154
|
-
}
|
|
6155
|
-
consume(s);
|
|
6347
|
+
const ts = {
|
|
6348
|
+
rows: [],
|
|
6349
|
+
needRow: false,
|
|
6350
|
+
hrule: parseRows(open.attrs["rows"]) === true,
|
|
6351
|
+
vrule: parseColumns(open.attrs["columns"]) === true
|
|
6352
|
+
};
|
|
6353
|
+
for (let t = peek(s); t !== void 0; t = peek(s)) {
|
|
6354
|
+
if (scanTableToken(s, t, fontStack, ts)) break;
|
|
6156
6355
|
}
|
|
6157
|
-
return buildTable(rows, open.attrs);
|
|
6356
|
+
return buildTable(ts.rows, open.attrs);
|
|
6158
6357
|
};
|
|
6159
6358
|
var parseTableRow = (s, fontStack, opts) => {
|
|
6160
6359
|
const row = parseRow(s, fontStack);
|
|
@@ -6164,11 +6363,9 @@ var parseTableRow = (s, fontStack, opts) => {
|
|
|
6164
6363
|
};
|
|
6165
6364
|
var consumeRowHr = (s, rows) => {
|
|
6166
6365
|
consume(s);
|
|
6167
|
-
|
|
6168
|
-
if (nxt?.type === "close" && nxt.tag === "HR") consume(s);
|
|
6366
|
+
consumeClose(s, "HR");
|
|
6169
6367
|
const prev = rows[rows.length - 1];
|
|
6170
|
-
if (prev
|
|
6171
|
-
prev.ruled = true;
|
|
6368
|
+
if (prev !== void 0) prev.ruled = true;
|
|
6172
6369
|
};
|
|
6173
6370
|
var findFirstRealToken = (tokens, start) => {
|
|
6174
6371
|
for (let i = start; i < tokens.length; i++) {
|
|
@@ -6184,34 +6381,61 @@ var skipLeadingWs = (s) => {
|
|
|
6184
6381
|
consume(s);
|
|
6185
6382
|
}
|
|
6186
6383
|
};
|
|
6384
|
+
var finishTableLabel = (s) => {
|
|
6385
|
+
let afterNonSpace = false;
|
|
6386
|
+
for (let t = peek(s); t?.type === "text"; t = peek(s)) {
|
|
6387
|
+
consume(s);
|
|
6388
|
+
if (nonSpace(t.value)) afterNonSpace = true;
|
|
6389
|
+
}
|
|
6390
|
+
const nxt = peek(s);
|
|
6391
|
+
if (nxt === void 0) return;
|
|
6392
|
+
if (afterNonSpace) throw parseError(s, nxt, MSG_TEXT_AFTER_TABLE);
|
|
6393
|
+
if (nxt.type !== "close" || nxt.tag !== "HTML") throw parseError(s, nxt, MSG_SYNTAX_ERROR);
|
|
6394
|
+
consume(s);
|
|
6395
|
+
};
|
|
6187
6396
|
var parseTableLabel = (s, fontStack) => {
|
|
6188
6397
|
skipLeadingWs(s);
|
|
6189
6398
|
const table = parseTable(s, fontStack);
|
|
6190
|
-
|
|
6191
|
-
if (nxt?.type === "close" && nxt.tag === "HTML") consume(s);
|
|
6399
|
+
finishTableLabel(s);
|
|
6192
6400
|
return { kind: "table", table };
|
|
6193
6401
|
};
|
|
6194
|
-
var
|
|
6195
|
-
const wrapped = `<HTML>${src}</HTML>`;
|
|
6196
|
-
const tokens = tokenize(wrapped);
|
|
6197
|
-
const s = { tokens, pos: 0 };
|
|
6198
|
-
const fontStack = [{}];
|
|
6199
|
-
const htmlOpen = consume(s);
|
|
6200
|
-
if (htmlOpen.type !== "open" || htmlOpen.tag !== "HTML") throw new HtmlParseError("HTML");
|
|
6201
|
-
const firstReal = findFirstRealToken(tokens, s.pos);
|
|
6202
|
-
if (firstReal?.type === "open" && firstReal.tag === "TABLE") {
|
|
6203
|
-
return parseTableLabel(s, fontStack);
|
|
6204
|
-
}
|
|
6402
|
+
var parseTextLabel = (s, fontStack) => {
|
|
6205
6403
|
const texts = [];
|
|
6206
6404
|
const txt = parseText(s, fontStack);
|
|
6207
6405
|
if (txt.items.length > 0) texts.push(txt);
|
|
6208
6406
|
const nxt = peek(s);
|
|
6209
|
-
if (nxt
|
|
6210
|
-
|
|
6407
|
+
if (nxt === void 0) return { kind: "text", texts };
|
|
6408
|
+
if (nxt.type === "open" && nxt.tag === "TABLE") {
|
|
6409
|
+
if (txt.items.some((i) => i.text !== void 0 && nonSpace(i.text))) {
|
|
6410
|
+
throw parseError(s, nxt, MSG_TEXT_BEFORE_TABLE);
|
|
6411
|
+
}
|
|
6412
|
+
throw new HtmlParseError("TABLE");
|
|
6211
6413
|
}
|
|
6212
|
-
if (nxt
|
|
6414
|
+
if (nxt.type !== "close" || nxt.tag !== "HTML") throw parseError(s, nxt, MSG_SYNTAX_ERROR);
|
|
6415
|
+
consume(s);
|
|
6213
6416
|
return { kind: "text", texts };
|
|
6214
6417
|
};
|
|
6418
|
+
var parseTokens = (s) => {
|
|
6419
|
+
const fontStack = [{}];
|
|
6420
|
+
const htmlOpen = consume(s);
|
|
6421
|
+
if (htmlOpen.type !== "open" || htmlOpen.tag !== "HTML") throw new HtmlParseError("HTML");
|
|
6422
|
+
const firstReal = findFirstRealToken(s.tokens, s.pos);
|
|
6423
|
+
if (firstReal?.type === "open" && firstReal.tag === "TABLE") return parseTableLabel(s, fontStack);
|
|
6424
|
+
return parseTextLabel(s, fontStack);
|
|
6425
|
+
};
|
|
6426
|
+
var parseHtmlLabel = (src) => {
|
|
6427
|
+
const { tokens, error } = tokenizeDeferred(`<HTML>${src}</HTML>`);
|
|
6428
|
+
const s = { tokens, pos: 0, pending: error };
|
|
6429
|
+
let label;
|
|
6430
|
+
try {
|
|
6431
|
+
label = parseTokens(s);
|
|
6432
|
+
} catch (e) {
|
|
6433
|
+
if (error !== void 0 && s.pos >= tokens.length) throw error;
|
|
6434
|
+
throw e;
|
|
6435
|
+
}
|
|
6436
|
+
if (error !== void 0) throw error;
|
|
6437
|
+
return label;
|
|
6438
|
+
};
|
|
6215
6439
|
|
|
6216
6440
|
// src/gvc/usershape.ts
|
|
6217
6441
|
var activeSizer = null;
|
|
@@ -6219,28 +6443,80 @@ function findImageSize(src) {
|
|
|
6219
6443
|
return activeSizer !== null ? activeSizer(src) : null;
|
|
6220
6444
|
}
|
|
6221
6445
|
|
|
6446
|
+
// src/common/pointset.ts
|
|
6447
|
+
function cmpPair(a, b) {
|
|
6448
|
+
if (a.x > b.x) return 1;
|
|
6449
|
+
if (a.x < b.x) return -1;
|
|
6450
|
+
if (a.y > b.y) return 1;
|
|
6451
|
+
if (a.y < b.y) return -1;
|
|
6452
|
+
return 0;
|
|
6453
|
+
}
|
|
6454
|
+
var PointSet = class {
|
|
6455
|
+
byX = /* @__PURE__ */ new Map();
|
|
6456
|
+
n = 0;
|
|
6457
|
+
/**
|
|
6458
|
+
* Insert (x, y). A duplicate keeps the point inserted first, as `dtinsert`
|
|
6459
|
+
* returns the existing object and the new one is freed.
|
|
6460
|
+
* @see lib/common/pointset.c:addPS
|
|
6461
|
+
*/
|
|
6462
|
+
addPS(x, y) {
|
|
6463
|
+
let col = this.byX.get(x);
|
|
6464
|
+
if (col === void 0) {
|
|
6465
|
+
col = /* @__PURE__ */ new Map();
|
|
6466
|
+
this.byX.set(x, col);
|
|
6467
|
+
}
|
|
6468
|
+
if (col.has(y)) return;
|
|
6469
|
+
col.set(y, { x, y });
|
|
6470
|
+
this.n++;
|
|
6471
|
+
}
|
|
6472
|
+
/** @see lib/common/pointset.c:inPS */
|
|
6473
|
+
inPS(pt) {
|
|
6474
|
+
return this.byX.get(pt.x)?.has(pt.y) ?? false;
|
|
6475
|
+
}
|
|
6476
|
+
/** @see lib/common/pointset.c:isInPS */
|
|
6477
|
+
isInPS(x, y) {
|
|
6478
|
+
return this.byX.get(x)?.has(y) ?? false;
|
|
6479
|
+
}
|
|
6480
|
+
/** @see lib/common/pointset.c:sizeOf */
|
|
6481
|
+
sizeOf() {
|
|
6482
|
+
return this.n;
|
|
6483
|
+
}
|
|
6484
|
+
/**
|
|
6485
|
+
* The points in dictionary order (`dtflatten` walks the ordered set).
|
|
6486
|
+
* @see lib/common/pointset.c:pointsOf
|
|
6487
|
+
*/
|
|
6488
|
+
pointsOf() {
|
|
6489
|
+
const pts = [];
|
|
6490
|
+
for (const col of this.byX.values()) {
|
|
6491
|
+
for (const p of col.values()) pts.push({ x: p.x, y: p.y });
|
|
6492
|
+
}
|
|
6493
|
+
return pts.sort(cmpPair);
|
|
6494
|
+
}
|
|
6495
|
+
};
|
|
6496
|
+
|
|
6222
6497
|
// src/common/htmltable.ts
|
|
6223
6498
|
var DEFAULT_BORDER = 1;
|
|
6224
6499
|
var DEFAULT_CELLPADDING = 2;
|
|
6225
6500
|
var DEFAULT_CELLSPACING = 2;
|
|
6226
6501
|
var DEFAULT_FONTSIZE = 14;
|
|
6227
|
-
var findCol = (
|
|
6502
|
+
var findCol = (ps, row, startCol, colspan, rowspan) => {
|
|
6228
6503
|
let col = startCol;
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6504
|
+
let notFound = true;
|
|
6505
|
+
const end = colspan - 1;
|
|
6506
|
+
while (notFound) {
|
|
6507
|
+
const lastc = col + end;
|
|
6508
|
+
let c;
|
|
6509
|
+
for (c = lastc; c >= col; c--) {
|
|
6510
|
+
if (ps.isInPS(c, row)) break;
|
|
6511
|
+
}
|
|
6512
|
+
if (c >= col) col = c + 1;
|
|
6513
|
+
else notFound = false;
|
|
6514
|
+
}
|
|
6515
|
+
for (let j = col; j < col + colspan; j++) {
|
|
6516
|
+
for (let i = row; i < row + rowspan; i++) {
|
|
6517
|
+
ps.addPS(j, i);
|
|
6238
6518
|
}
|
|
6239
|
-
if (!conflict) break;
|
|
6240
6519
|
}
|
|
6241
|
-
for (let c = col; c < col + colspan; c++)
|
|
6242
|
-
for (let r = row; r < row + rowspan; r++)
|
|
6243
|
-
used.add(`${c},${r}`);
|
|
6244
6520
|
return col;
|
|
6245
6521
|
};
|
|
6246
6522
|
var DEFAULT_SIZE_ENV = { fontsize: DEFAULT_FONTSIZE, fontname: "" };
|
|
@@ -6319,29 +6595,32 @@ var sizeTextContent = (texts, measurer, env = DEFAULT_SIZE_ENV) => {
|
|
|
6319
6595
|
if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].mxysize : DEFAULT_FONTSIZE;
|
|
6320
6596
|
return { w, h };
|
|
6321
6597
|
};
|
|
6598
|
+
var missingImages = /* @__PURE__ */ new WeakSet();
|
|
6322
6599
|
var sizeHtmlImg = (img, imageSizer) => {
|
|
6323
|
-
if (img.width !== void 0 && img.height !== void 0) return;
|
|
6600
|
+
if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
|
|
6324
6601
|
const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
|
|
6325
6602
|
if (sz !== null) {
|
|
6326
6603
|
img.width = sz.w;
|
|
6327
6604
|
img.height = sz.h;
|
|
6328
|
-
return;
|
|
6605
|
+
return 0;
|
|
6329
6606
|
}
|
|
6330
6607
|
console.error(`Error: No or improper image file="${img.src}"`);
|
|
6331
6608
|
img.width = 0;
|
|
6332
6609
|
img.height = 0;
|
|
6610
|
+
missingImages.add(img);
|
|
6611
|
+
return 1;
|
|
6333
6612
|
};
|
|
6334
6613
|
var sizeContentItem = (item, measurer, env) => {
|
|
6335
|
-
if (item.kind === "text") return sizeTextContent([item], measurer, env);
|
|
6614
|
+
if (item.kind === "text") return { ...sizeTextContent([item], measurer, env), rv: 0 };
|
|
6336
6615
|
if (item.kind === "table") {
|
|
6337
|
-
sizeTableInner(item, measurer, env);
|
|
6338
|
-
return item.dimen !== void 0 ? item.dimen : { w: 0, h: 0 };
|
|
6616
|
+
const rv = sizeTableInner(item, measurer, env);
|
|
6617
|
+
return { ...item.dimen !== void 0 ? item.dimen : { w: 0, h: 0 }, rv };
|
|
6339
6618
|
}
|
|
6340
6619
|
if (item.kind === "image") {
|
|
6341
|
-
sizeHtmlImg(item, env.imageSizer);
|
|
6342
|
-
return { w: item.width ?? 0, h: item.height ?? 0 };
|
|
6620
|
+
const rv = sizeHtmlImg(item, env.imageSizer);
|
|
6621
|
+
return { w: item.width ?? 0, h: item.height ?? 0, rv };
|
|
6343
6622
|
}
|
|
6344
|
-
return { w: 0, h: 0 };
|
|
6623
|
+
return { w: 0, h: 0, rv: 0 };
|
|
6345
6624
|
};
|
|
6346
6625
|
var cellPad = (cell2, tbl) => cell2.cellpadding !== void 0 ? cell2.cellpadding : tbl.cellpadding !== void 0 ? tbl.cellpadding : DEFAULT_CELLPADDING;
|
|
6347
6626
|
var cellBorder = (cell2, tbl) => {
|
|
@@ -6351,27 +6630,60 @@ var cellBorder = (cell2, tbl) => {
|
|
|
6351
6630
|
if (tbl.border !== void 0) return tbl.border;
|
|
6352
6631
|
return DEFAULT_BORDER;
|
|
6353
6632
|
};
|
|
6633
|
+
function inheritTablePenColor(tbl, parentColor) {
|
|
6634
|
+
if (tbl.color === void 0) tbl.color = parentColor;
|
|
6635
|
+
const tblColor = tbl.color;
|
|
6636
|
+
for (const row of tbl.rows) {
|
|
6637
|
+
for (const cell2 of row.cells) {
|
|
6638
|
+
if (cell2.color === void 0) cell2.color = tblColor;
|
|
6639
|
+
for (const item of cell2.content) {
|
|
6640
|
+
if (item.kind === "table") inheritTablePenColor(item, cell2.color);
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
var WARN_CELL_TOO_SMALL = "Warning: cell size too small for content";
|
|
6646
|
+
var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or height";
|
|
6647
|
+
var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
|
|
6648
|
+
var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
|
|
6649
|
+
var sizeWarned = /* @__PURE__ */ new WeakSet();
|
|
6650
|
+
var fixedCellCheck = (cell2, sz, warn) => {
|
|
6651
|
+
if (!cell2.fixedsize) return { rv: 0, zero: false };
|
|
6652
|
+
if (cell2.width && cell2.height) {
|
|
6653
|
+
const small = (cell2.width < sz.w || cell2.height < sz.h) && cell2.content[0]?.kind !== "image";
|
|
6654
|
+
if (small && warn) console.warn(WARN_CELL_TOO_SMALL);
|
|
6655
|
+
return { rv: small ? 1 : 0, zero: true };
|
|
6656
|
+
}
|
|
6657
|
+
if (warn) console.warn(WARN_CELL_UNSPECIFIED);
|
|
6658
|
+
return { rv: 1, zero: false };
|
|
6659
|
+
};
|
|
6354
6660
|
var getCellSize = (cell2, tbl, measurer, env) => {
|
|
6355
6661
|
const margin = 2 * (cellPad(cell2, tbl) + cellBorder(cell2, tbl));
|
|
6356
|
-
let cw = 0, ch = 0;
|
|
6662
|
+
let cw = 0, ch = 0, rv = 0;
|
|
6357
6663
|
for (const item of cell2.content) {
|
|
6358
6664
|
const s = sizeContentItem(item, measurer, env);
|
|
6359
6665
|
cw = Math.max(cw, s.w);
|
|
6360
6666
|
ch += s.h;
|
|
6667
|
+
rv |= s.rv;
|
|
6361
6668
|
}
|
|
6362
6669
|
let szx = cw + margin;
|
|
6363
6670
|
let szy = ch + margin;
|
|
6364
|
-
|
|
6671
|
+
const warn = !sizeWarned.has(cell2);
|
|
6672
|
+
sizeWarned.add(cell2);
|
|
6673
|
+
const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn);
|
|
6674
|
+
rv |= fixed.rv;
|
|
6675
|
+
if (fixed.zero) {
|
|
6365
6676
|
szx = 0;
|
|
6366
6677
|
szy = 0;
|
|
6367
6678
|
}
|
|
6368
6679
|
const bw = cell2.width !== void 0 ? cell2.width : 0;
|
|
6369
6680
|
const bh = cell2.height !== void 0 ? cell2.height : 0;
|
|
6370
|
-
return { w: Math.max(szx, bw), h: Math.max(szy, bh) };
|
|
6681
|
+
return { w: Math.max(szx, bw), h: Math.max(szy, bh), rv };
|
|
6371
6682
|
};
|
|
6372
6683
|
var buildLayouts = (tbl, measurer, env) => {
|
|
6373
6684
|
const entries = [];
|
|
6374
|
-
|
|
6685
|
+
let rv = 0;
|
|
6686
|
+
const ps = new PointSet();
|
|
6375
6687
|
let rowIdx = 0;
|
|
6376
6688
|
for (const row of tbl.rows) {
|
|
6377
6689
|
let col = 0;
|
|
@@ -6381,14 +6693,15 @@ var buildLayouts = (tbl, measurer, env) => {
|
|
|
6381
6693
|
}
|
|
6382
6694
|
const colspan = c.colspan !== void 0 ? c.colspan : 1;
|
|
6383
6695
|
const rowspan = c.rowspan !== void 0 ? c.rowspan : 1;
|
|
6384
|
-
const { w, h } = getCellSize(c, tbl, measurer, env);
|
|
6385
|
-
|
|
6696
|
+
const { w, h, rv: cellRv } = getCellSize(c, tbl, measurer, env);
|
|
6697
|
+
rv |= cellRv;
|
|
6698
|
+
col = findCol(ps, rowIdx, col, colspan, rowspan);
|
|
6386
6699
|
entries.push({ cell: c, row: rowIdx, col, colspan, rowspan, w, h });
|
|
6387
6700
|
col += colspan;
|
|
6388
6701
|
}
|
|
6389
6702
|
rowIdx++;
|
|
6390
6703
|
}
|
|
6391
|
-
return entries;
|
|
6704
|
+
return { entries, rv };
|
|
6392
6705
|
};
|
|
6393
6706
|
var setColWidths = (entries, ncols, spacing) => {
|
|
6394
6707
|
const widths = new Array(ncols + 1).fill(0);
|
|
@@ -6441,21 +6754,34 @@ var sumTableDims = (a) => {
|
|
|
6441
6754
|
var layoutHtmlTable = (tbl, measurer, env = DEFAULT_SIZE_ENV) => {
|
|
6442
6755
|
const spacing = getSpacing(tbl);
|
|
6443
6756
|
const border = getBorder(tbl);
|
|
6444
|
-
const entries = buildLayouts(tbl, measurer, env);
|
|
6757
|
+
const { entries, rv } = buildLayouts(tbl, measurer, env);
|
|
6445
6758
|
if (entries.length === 0) {
|
|
6446
|
-
return { entries, widths: [], heights: [], spacing, border };
|
|
6759
|
+
return { entries, widths: [], heights: [], spacing, border, rv };
|
|
6447
6760
|
}
|
|
6448
6761
|
const ncols = Math.max(...entries.map((e) => e.col + e.colspan));
|
|
6449
6762
|
const nrows = Math.max(...entries.map((e) => e.row + e.rowspan));
|
|
6450
6763
|
const widths = setColWidths(entries, ncols, spacing);
|
|
6451
6764
|
const heights = setRowHeights(entries, nrows, spacing);
|
|
6452
|
-
return { entries, widths, heights, spacing, border };
|
|
6765
|
+
return { entries, widths, heights, spacing, border, rv };
|
|
6766
|
+
};
|
|
6767
|
+
var warnFixedTable = (tbl, dims) => {
|
|
6768
|
+
const warn = !sizeWarned.has(tbl);
|
|
6769
|
+
sizeWarned.add(tbl);
|
|
6770
|
+
if (tbl.fixedsize !== true) return 0;
|
|
6771
|
+
if (tbl.width && tbl.height) {
|
|
6772
|
+
if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
|
|
6773
|
+
if (warn) console.warn(WARN_TABLE_TOO_SMALL);
|
|
6774
|
+
return 1;
|
|
6775
|
+
}
|
|
6776
|
+
if (warn) console.warn(WARN_TABLE_UNSPECIFIED);
|
|
6777
|
+
return 1;
|
|
6453
6778
|
};
|
|
6454
6779
|
var sizeTableInner = (tbl, measurer, env) => {
|
|
6455
|
-
const { entries, widths, heights, spacing, border } = layoutHtmlTable(tbl, measurer, env);
|
|
6780
|
+
const { entries, widths, heights, spacing, border, rv } = layoutHtmlTable(tbl, measurer, env);
|
|
6456
6781
|
if (entries.length === 0) {
|
|
6782
|
+
const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border }));
|
|
6457
6783
|
tbl.dimen = { w: 0, h: 0 };
|
|
6458
|
-
return;
|
|
6784
|
+
return rv | fixed2;
|
|
6459
6785
|
}
|
|
6460
6786
|
const ncols = Math.max(...entries.map((e) => e.col + e.colspan));
|
|
6461
6787
|
const nrows = Math.max(...entries.map((e) => e.row + e.rowspan));
|
|
@@ -6463,19 +6789,22 @@ var sizeTableInner = (tbl, measurer, env) => {
|
|
|
6463
6789
|
const { wd, ht } = sumTableDims({ widths, heights, ncols, nrows, spacing, border });
|
|
6464
6790
|
const baseWd = tbl.width !== void 0 ? tbl.width : 0;
|
|
6465
6791
|
const baseHt = tbl.height !== void 0 ? tbl.height : 0;
|
|
6792
|
+
const fixed = warnFixedTable(tbl, { wd, ht });
|
|
6466
6793
|
const zeroContent = isTblFixed(tbl) && baseWd !== 0 && baseHt !== 0;
|
|
6467
6794
|
tbl.dimen = {
|
|
6468
6795
|
w: Math.max(zeroContent ? 0 : wd, baseWd),
|
|
6469
6796
|
h: Math.max(zeroContent ? 0 : ht, baseHt)
|
|
6470
6797
|
};
|
|
6798
|
+
return rv | fixed;
|
|
6471
6799
|
};
|
|
6472
6800
|
var sizeHtmlLabel = (label, measurer, env = DEFAULT_SIZE_ENV) => {
|
|
6473
6801
|
if (label.kind === "table") {
|
|
6474
|
-
sizeTableInner(label.table, measurer, env);
|
|
6802
|
+
const rv = sizeTableInner(label.table, measurer, env);
|
|
6475
6803
|
label.dimen = label.table.dimen;
|
|
6476
|
-
|
|
6477
|
-
label.dimen = sizeTextContent(label.texts, measurer, env);
|
|
6804
|
+
return rv;
|
|
6478
6805
|
}
|
|
6806
|
+
label.dimen = sizeTextContent(label.texts, measurer, env);
|
|
6807
|
+
return 0;
|
|
6479
6808
|
};
|
|
6480
6809
|
|
|
6481
6810
|
// src/common/splines-constants.ts
|
|
@@ -6918,28 +7247,18 @@ function posHtmlLabel(label, finfo, measurer) {
|
|
|
6918
7247
|
if (label.kind === "table") return posHtmlTable(label.table, finfo, measurer);
|
|
6919
7248
|
return posTextLabel(label, finfo, measurer);
|
|
6920
7249
|
}
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
const tblColor = tbl.color;
|
|
6924
|
-
for (const row of tbl.rows) {
|
|
6925
|
-
for (const cell2 of row.cells) {
|
|
6926
|
-
if (cell2.color === void 0) cell2.color = tblColor;
|
|
6927
|
-
for (const item of cell2.content) {
|
|
6928
|
-
if (item.kind === "table") inheritTablePenColor(item, cell2.color);
|
|
6929
|
-
}
|
|
6930
|
-
}
|
|
6931
|
-
}
|
|
6932
|
-
}
|
|
6933
|
-
function makeHtmlLabel(content, finfo, measurer) {
|
|
7250
|
+
var HTML_PARSE_FATAL = 3;
|
|
7251
|
+
function makeHtmlLabelRv(content, finfo, measurer) {
|
|
6934
7252
|
const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
|
|
6935
7253
|
let lbl;
|
|
6936
7254
|
try {
|
|
6937
7255
|
lbl = parseHtmlLabel(content);
|
|
6938
|
-
} catch {
|
|
6939
|
-
|
|
7256
|
+
} catch (e) {
|
|
7257
|
+
if (e instanceof HtmlLexError) for (const line of e.diagnostics) console.error(line);
|
|
7258
|
+
return { label: makeLabel("", fontname, fontsize, fontcolor, measurer), rv: HTML_PARSE_FATAL };
|
|
6940
7259
|
}
|
|
6941
7260
|
if (lbl.kind === "table") inheritTablePenColor(lbl.table, pencolor);
|
|
6942
|
-
sizeHtmlLabel(lbl, measurer, {
|
|
7261
|
+
const rv = sizeHtmlLabel(lbl, measurer, {
|
|
6943
7262
|
fontsize,
|
|
6944
7263
|
fontname,
|
|
6945
7264
|
imageSizer
|
|
@@ -6947,7 +7266,7 @@ function makeHtmlLabel(content, finfo, measurer) {
|
|
|
6947
7266
|
const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
|
|
6948
7267
|
const dim = lbl.dimen ?? { w: 0, h: 0 };
|
|
6949
7268
|
const text = lbl.kind === "table" ? "<TABLE>" : content;
|
|
6950
|
-
return htmlTextLabel(text, { fontname, fontsize, fontcolor }, placed, dim);
|
|
7269
|
+
return { label: htmlTextLabel(text, { fontname, fontsize, fontcolor }, placed, dim), rv };
|
|
6951
7270
|
}
|
|
6952
7271
|
function htmlTextLabel(text, finfo, placed, dim) {
|
|
6953
7272
|
return {
|
|
@@ -7336,6 +7655,159 @@ function interpretCRNL(str) {
|
|
|
7336
7655
|
return out;
|
|
7337
7656
|
}
|
|
7338
7657
|
|
|
7658
|
+
// src/model/graphInfo.ts
|
|
7659
|
+
function makeGraphInfo() {
|
|
7660
|
+
return {
|
|
7661
|
+
bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } },
|
|
7662
|
+
rankdir: 0,
|
|
7663
|
+
flags: 0,
|
|
7664
|
+
charset: 0,
|
|
7665
|
+
gui_state: 0,
|
|
7666
|
+
has_labels: 0,
|
|
7667
|
+
has_images: false
|
|
7668
|
+
};
|
|
7669
|
+
}
|
|
7670
|
+
|
|
7671
|
+
// src/model/graph.ts
|
|
7672
|
+
var Graph = class {
|
|
7673
|
+
/** Graph name; agnameof equivalent. @see lib/cgraph/cgraph.h:agnameof */
|
|
7674
|
+
name;
|
|
7675
|
+
/**
|
|
7676
|
+
* True when the graph was declared with NO name (`digraph {`), as opposed to
|
|
7677
|
+
* an explicit empty name (`digraph "" {`). Both store `name === ''`, but
|
|
7678
|
+
* cgraph gives the truly-anonymous root the internal id `%1` (agnameof) while
|
|
7679
|
+
* the empty-named one keeps `""`. Only the imagemap `<map id/name>` reads this
|
|
7680
|
+
* (map.ts:mapGraphName); dot/xdot re-serialization keeps `name` so an
|
|
7681
|
+
* anonymous root round-trips as `digraph {`, not `digraph %1 {`.
|
|
7682
|
+
* @see lib/cgraph/id.c:idmap (anon → `%1`) ; lib/cgraph/agraph.c:agnameof
|
|
7683
|
+
*/
|
|
7684
|
+
anonymous;
|
|
7685
|
+
/**
|
|
7686
|
+
* Directed/strict classification; mirrors Agdesc_t.directed and
|
|
7687
|
+
* Agdesc_t.strict. @see lib/cgraph/cgraph.h:Agdesc_s
|
|
7688
|
+
*/
|
|
7689
|
+
kind;
|
|
7690
|
+
/**
|
|
7691
|
+
* Node set in insertion order, keyed by name.
|
|
7692
|
+
* Mirrors Agraph_t.n_seq (sequence dict) merged with n_id access.
|
|
7693
|
+
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
7694
|
+
*/
|
|
7695
|
+
nodes;
|
|
7696
|
+
/**
|
|
7697
|
+
* All edges owned by this graph (root graph only for ownership; subgraphs
|
|
7698
|
+
* reference a subset). Mirrors Agraph_t.e_seq.
|
|
7699
|
+
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
7700
|
+
*/
|
|
7701
|
+
edges;
|
|
7702
|
+
/**
|
|
7703
|
+
* Named subgraphs, keyed by name. Mirrors Agraph_t.g_seq/g_id.
|
|
7704
|
+
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
7705
|
+
*/
|
|
7706
|
+
subgraphs;
|
|
7707
|
+
/**
|
|
7708
|
+
* String attributes (agget/agset equivalents).
|
|
7709
|
+
* Replaces the Agattr_t / Agsym_t machinery for simple key-value access.
|
|
7710
|
+
* @see lib/cgraph/cgraph.h:Agattr_s
|
|
7711
|
+
*/
|
|
7712
|
+
attrs;
|
|
7713
|
+
/** Default attributes applied to all nodes in this graph scope. */
|
|
7714
|
+
nodeDefaults;
|
|
7715
|
+
/** Default attributes applied to all edges in this graph scope. */
|
|
7716
|
+
edgeDefaults;
|
|
7717
|
+
/**
|
|
7718
|
+
* Snapshot of the enclosing graphs' graph-attribute defaults (this graph ->
|
|
7719
|
+
* root, inner wins) captured when this subgraph was OPENED during parsing.
|
|
7720
|
+
* Graph attributes set on an ancestor AFTER this subgraph was created are not
|
|
7721
|
+
* included — mirroring cgraph's parse-time agsubg defval copy. Used for
|
|
7722
|
+
* order-correct label/font inheritance (e.g. a root `label=` declared after a
|
|
7723
|
+
* cluster must NOT apply to that cluster). Undefined on the root graph.
|
|
7724
|
+
* @see lib/cgraph/graph.c:agsubg (attr defval copy)
|
|
7725
|
+
*/
|
|
7726
|
+
graphDefaultsSnapshot;
|
|
7727
|
+
/**
|
|
7728
|
+
* Keys in `attrs` the BUILDER seeded from `graphDefaultsSnapshot` rather than
|
|
7729
|
+
* the input declaring them in this scope (see builder.ts GRAPH_LABEL_INHERIT_
|
|
7730
|
+
* KEYS). cgraph distinguishes these structurally — a seeded value is inherited
|
|
7731
|
+
* through the dict view and has no local symbol, while a local declaration
|
|
7732
|
+
* creates one even when its value equals the inherited value — so the
|
|
7733
|
+
* serializer needs the provenance to decide what write_dict would print.
|
|
7734
|
+
* Undefined on the root graph and on any scope that seeded nothing.
|
|
7735
|
+
* @see lib/cgraph/write.c:262 write_dict
|
|
7736
|
+
*/
|
|
7737
|
+
seededAttrs;
|
|
7738
|
+
/**
|
|
7739
|
+
* Graph-attribute keys whose declaration in THIS scope was the first anywhere
|
|
7740
|
+
* in the graph. cgraph's `setattr` splits on exactly this: a key with no
|
|
7741
|
+
* existing symbol takes the global-declaration branch, which ends up seeding
|
|
7742
|
+
* every direct subgraph that already exists with a local empty value (see
|
|
7743
|
+
* `eagerEmptyParts`); a key some earlier scope already declared takes the
|
|
7744
|
+
* "new local definition" branch and touches no subgraph at all. So an
|
|
7745
|
+
* identical `graph [fill=x]` statement makes a child print `fill=""` or print
|
|
7746
|
+
* nothing purely according to whether a SIBLING declared `fill` first.
|
|
7747
|
+
* Undefined on any scope that declared nothing new.
|
|
7748
|
+
* @see lib/cgraph/attr.c:257 setattr (lsym / psym / global branches)
|
|
7749
|
+
*/
|
|
7750
|
+
firstGraphDecl;
|
|
7751
|
+
/**
|
|
7752
|
+
* Layout-engine info; replaces GD_* macros via agbindrec (AD-1).
|
|
7753
|
+
* @see lib/cgraph/cgraph.h:agbindrec
|
|
7754
|
+
*/
|
|
7755
|
+
info;
|
|
7756
|
+
/**
|
|
7757
|
+
* Immediate parent graph. null for root graphs.
|
|
7758
|
+
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
7759
|
+
*/
|
|
7760
|
+
parent;
|
|
7761
|
+
/**
|
|
7762
|
+
* Root (main) graph. Self-referential for root graphs;
|
|
7763
|
+
* points up for subgraphs.
|
|
7764
|
+
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
7765
|
+
*/
|
|
7766
|
+
root;
|
|
7767
|
+
/**
|
|
7768
|
+
* Subgraph sequence number (AGSEQ). A global counter on the root, assigned
|
|
7769
|
+
* at creation in source order, counting anonymous subgraphs. The root keeps
|
|
7770
|
+
* the default 0 (par == NULL never calls agnextseq). Consumed by getObjId to
|
|
7771
|
+
* emit cluster ids `clust<seq>`.
|
|
7772
|
+
* @see lib/cgraph/cgraph.h:AGSEQ
|
|
7773
|
+
* @see lib/cgraph/graph.c:agopen (AGSEQ(g) = agnextseq(par, AGRAPH))
|
|
7774
|
+
*/
|
|
7775
|
+
seq = 0;
|
|
7776
|
+
/**
|
|
7777
|
+
* Root-only counter mirroring `clos->seq[AGRAPH]`: the running maximum AGSEQ
|
|
7778
|
+
* handed out to subgraphs. Meaningful only on the root graph; `assignSubgSeq`
|
|
7779
|
+
* pre-increments it. Other graphs leave it at 0.
|
|
7780
|
+
* @see lib/cgraph/graph.c:agnextseq (++clos->seq[AGRAPH])
|
|
7781
|
+
*/
|
|
7782
|
+
subgSeqCounter = 0;
|
|
7783
|
+
/**
|
|
7784
|
+
* Names of graph attributes (AGRAPH) declared anywhere in this hierarchy —
|
|
7785
|
+
* the port's stand-in for cgraph's `Agsym_t` symbol table. Populated on the
|
|
7786
|
+
* ROOT only, at parse time, whenever a graph attribute is assigned on any
|
|
7787
|
+
* (sub)graph: setting `ordering=out` on a subgraph declares "ordering"
|
|
7788
|
+
* graph-wide with an empty default, so `agGraphAttr(root, "ordering")` returns
|
|
7789
|
+
* `""` (not undefined) — mirroring `agfindgraphattr`/`late_string`. Read via
|
|
7790
|
+
* `agGraphAttr` (model/cgraph-ops.ts); empty on non-root graphs.
|
|
7791
|
+
* @see lib/cgraph/attr.c:agattr (graph-wide declaration, "" default)
|
|
7792
|
+
*/
|
|
7793
|
+
declaredGraphAttrs = /* @__PURE__ */ new Set();
|
|
7794
|
+
/** @see lib/cgraph/graph.c:agopen */
|
|
7795
|
+
constructor(name, kind, anonymous = false) {
|
|
7796
|
+
this.name = name;
|
|
7797
|
+
this.anonymous = anonymous;
|
|
7798
|
+
this.kind = kind;
|
|
7799
|
+
this.nodes = /* @__PURE__ */ new Map();
|
|
7800
|
+
this.edges = [];
|
|
7801
|
+
this.subgraphs = /* @__PURE__ */ new Map();
|
|
7802
|
+
this.attrs = /* @__PURE__ */ new Map();
|
|
7803
|
+
this.nodeDefaults = /* @__PURE__ */ new Map();
|
|
7804
|
+
this.edgeDefaults = /* @__PURE__ */ new Map();
|
|
7805
|
+
this.info = makeGraphInfo();
|
|
7806
|
+
this.parent = null;
|
|
7807
|
+
this.root = this;
|
|
7808
|
+
}
|
|
7809
|
+
};
|
|
7810
|
+
|
|
7339
7811
|
// src/common/make-label.ts
|
|
7340
7812
|
var DEFAULT_FONTSIZE2 = 14;
|
|
7341
7813
|
var DEFAULT_FONTNAME = "Times-Roman";
|
|
@@ -7351,6 +7823,14 @@ function getPenColor(obj) {
|
|
|
7351
7823
|
function rootOf(obj) {
|
|
7352
7824
|
return obj instanceof Edge ? obj.tail.root : obj.root;
|
|
7353
7825
|
}
|
|
7826
|
+
function inLabelOf(obj) {
|
|
7827
|
+
if (obj instanceof Edge) {
|
|
7828
|
+
const sep = obj.head.root.kind.endsWith("undirected") ? "--" : "->";
|
|
7829
|
+
return `in label of edge ${obj.tail.name} ${sep} ${obj.head.name}`;
|
|
7830
|
+
}
|
|
7831
|
+
if (obj instanceof Graph) return `in label of graph ${obj.name}`;
|
|
7832
|
+
return `in label of node ${obj.name}`;
|
|
7833
|
+
}
|
|
7354
7834
|
function buildSpan(text, font, measured) {
|
|
7355
7835
|
return {
|
|
7356
7836
|
str: text,
|
|
@@ -7418,7 +7898,9 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
|
|
|
7418
7898
|
function makeAnyLabel(content, isHtml, font, measurer, obj) {
|
|
7419
7899
|
if (isHtml && content !== "") {
|
|
7420
7900
|
const imageSizer = obj !== void 0 ? rootOf(obj).info.gvc?.imageSizer : void 0;
|
|
7421
|
-
|
|
7901
|
+
const { label, rv } = makeHtmlLabelRv(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer);
|
|
7902
|
+
if (rv !== 0 && obj !== void 0) console.error(inLabelOf(obj));
|
|
7903
|
+
return label;
|
|
7422
7904
|
}
|
|
7423
7905
|
const subst2 = obj !== void 0 ? substObj(content, obj, false) : content;
|
|
7424
7906
|
const text = htmlEntityUTF8(subst2);
|
|
@@ -8887,19 +9369,6 @@ var RenderJob = class {
|
|
|
8887
9369
|
}
|
|
8888
9370
|
};
|
|
8889
9371
|
|
|
8890
|
-
// src/model/graphInfo.ts
|
|
8891
|
-
function makeGraphInfo() {
|
|
8892
|
-
return {
|
|
8893
|
-
bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } },
|
|
8894
|
-
rankdir: 0,
|
|
8895
|
-
flags: 0,
|
|
8896
|
-
charset: 0,
|
|
8897
|
-
gui_state: 0,
|
|
8898
|
-
has_labels: 0,
|
|
8899
|
-
has_images: false
|
|
8900
|
-
};
|
|
8901
|
-
}
|
|
8902
|
-
|
|
8903
9372
|
// src/common/shapeData.ts
|
|
8904
9373
|
var DOGEAR = 1;
|
|
8905
9374
|
var TAB = 2;
|
|
@@ -15489,146 +15958,6 @@ function ncross(ctx) {
|
|
|
15489
15958
|
return total;
|
|
15490
15959
|
}
|
|
15491
15960
|
|
|
15492
|
-
// src/model/graph.ts
|
|
15493
|
-
var Graph = class {
|
|
15494
|
-
/** Graph name; agnameof equivalent. @see lib/cgraph/cgraph.h:agnameof */
|
|
15495
|
-
name;
|
|
15496
|
-
/**
|
|
15497
|
-
* True when the graph was declared with NO name (`digraph {`), as opposed to
|
|
15498
|
-
* an explicit empty name (`digraph "" {`). Both store `name === ''`, but
|
|
15499
|
-
* cgraph gives the truly-anonymous root the internal id `%1` (agnameof) while
|
|
15500
|
-
* the empty-named one keeps `""`. Only the imagemap `<map id/name>` reads this
|
|
15501
|
-
* (map.ts:mapGraphName); dot/xdot re-serialization keeps `name` so an
|
|
15502
|
-
* anonymous root round-trips as `digraph {`, not `digraph %1 {`.
|
|
15503
|
-
* @see lib/cgraph/id.c:idmap (anon → `%1`) ; lib/cgraph/agraph.c:agnameof
|
|
15504
|
-
*/
|
|
15505
|
-
anonymous;
|
|
15506
|
-
/**
|
|
15507
|
-
* Directed/strict classification; mirrors Agdesc_t.directed and
|
|
15508
|
-
* Agdesc_t.strict. @see lib/cgraph/cgraph.h:Agdesc_s
|
|
15509
|
-
*/
|
|
15510
|
-
kind;
|
|
15511
|
-
/**
|
|
15512
|
-
* Node set in insertion order, keyed by name.
|
|
15513
|
-
* Mirrors Agraph_t.n_seq (sequence dict) merged with n_id access.
|
|
15514
|
-
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
15515
|
-
*/
|
|
15516
|
-
nodes;
|
|
15517
|
-
/**
|
|
15518
|
-
* All edges owned by this graph (root graph only for ownership; subgraphs
|
|
15519
|
-
* reference a subset). Mirrors Agraph_t.e_seq.
|
|
15520
|
-
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
15521
|
-
*/
|
|
15522
|
-
edges;
|
|
15523
|
-
/**
|
|
15524
|
-
* Named subgraphs, keyed by name. Mirrors Agraph_t.g_seq/g_id.
|
|
15525
|
-
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
15526
|
-
*/
|
|
15527
|
-
subgraphs;
|
|
15528
|
-
/**
|
|
15529
|
-
* String attributes (agget/agset equivalents).
|
|
15530
|
-
* Replaces the Agattr_t / Agsym_t machinery for simple key-value access.
|
|
15531
|
-
* @see lib/cgraph/cgraph.h:Agattr_s
|
|
15532
|
-
*/
|
|
15533
|
-
attrs;
|
|
15534
|
-
/** Default attributes applied to all nodes in this graph scope. */
|
|
15535
|
-
nodeDefaults;
|
|
15536
|
-
/** Default attributes applied to all edges in this graph scope. */
|
|
15537
|
-
edgeDefaults;
|
|
15538
|
-
/**
|
|
15539
|
-
* Snapshot of the enclosing graphs' graph-attribute defaults (this graph ->
|
|
15540
|
-
* root, inner wins) captured when this subgraph was OPENED during parsing.
|
|
15541
|
-
* Graph attributes set on an ancestor AFTER this subgraph was created are not
|
|
15542
|
-
* included — mirroring cgraph's parse-time agsubg defval copy. Used for
|
|
15543
|
-
* order-correct label/font inheritance (e.g. a root `label=` declared after a
|
|
15544
|
-
* cluster must NOT apply to that cluster). Undefined on the root graph.
|
|
15545
|
-
* @see lib/cgraph/graph.c:agsubg (attr defval copy)
|
|
15546
|
-
*/
|
|
15547
|
-
graphDefaultsSnapshot;
|
|
15548
|
-
/**
|
|
15549
|
-
* Keys in `attrs` the BUILDER seeded from `graphDefaultsSnapshot` rather than
|
|
15550
|
-
* the input declaring them in this scope (see builder.ts GRAPH_LABEL_INHERIT_
|
|
15551
|
-
* KEYS). cgraph distinguishes these structurally — a seeded value is inherited
|
|
15552
|
-
* through the dict view and has no local symbol, while a local declaration
|
|
15553
|
-
* creates one even when its value equals the inherited value — so the
|
|
15554
|
-
* serializer needs the provenance to decide what write_dict would print.
|
|
15555
|
-
* Undefined on the root graph and on any scope that seeded nothing.
|
|
15556
|
-
* @see lib/cgraph/write.c:262 write_dict
|
|
15557
|
-
*/
|
|
15558
|
-
seededAttrs;
|
|
15559
|
-
/**
|
|
15560
|
-
* Graph-attribute keys whose declaration in THIS scope was the first anywhere
|
|
15561
|
-
* in the graph. cgraph's `setattr` splits on exactly this: a key with no
|
|
15562
|
-
* existing symbol takes the global-declaration branch, which ends up seeding
|
|
15563
|
-
* every direct subgraph that already exists with a local empty value (see
|
|
15564
|
-
* `eagerEmptyParts`); a key some earlier scope already declared takes the
|
|
15565
|
-
* "new local definition" branch and touches no subgraph at all. So an
|
|
15566
|
-
* identical `graph [fill=x]` statement makes a child print `fill=""` or print
|
|
15567
|
-
* nothing purely according to whether a SIBLING declared `fill` first.
|
|
15568
|
-
* Undefined on any scope that declared nothing new.
|
|
15569
|
-
* @see lib/cgraph/attr.c:257 setattr (lsym / psym / global branches)
|
|
15570
|
-
*/
|
|
15571
|
-
firstGraphDecl;
|
|
15572
|
-
/**
|
|
15573
|
-
* Layout-engine info; replaces GD_* macros via agbindrec (AD-1).
|
|
15574
|
-
* @see lib/cgraph/cgraph.h:agbindrec
|
|
15575
|
-
*/
|
|
15576
|
-
info;
|
|
15577
|
-
/**
|
|
15578
|
-
* Immediate parent graph. null for root graphs.
|
|
15579
|
-
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
15580
|
-
*/
|
|
15581
|
-
parent;
|
|
15582
|
-
/**
|
|
15583
|
-
* Root (main) graph. Self-referential for root graphs;
|
|
15584
|
-
* points up for subgraphs.
|
|
15585
|
-
* @see lib/cgraph/cgraph.h:Agraph_s
|
|
15586
|
-
*/
|
|
15587
|
-
root;
|
|
15588
|
-
/**
|
|
15589
|
-
* Subgraph sequence number (AGSEQ). A global counter on the root, assigned
|
|
15590
|
-
* at creation in source order, counting anonymous subgraphs. The root keeps
|
|
15591
|
-
* the default 0 (par == NULL never calls agnextseq). Consumed by getObjId to
|
|
15592
|
-
* emit cluster ids `clust<seq>`.
|
|
15593
|
-
* @see lib/cgraph/cgraph.h:AGSEQ
|
|
15594
|
-
* @see lib/cgraph/graph.c:agopen (AGSEQ(g) = agnextseq(par, AGRAPH))
|
|
15595
|
-
*/
|
|
15596
|
-
seq = 0;
|
|
15597
|
-
/**
|
|
15598
|
-
* Root-only counter mirroring `clos->seq[AGRAPH]`: the running maximum AGSEQ
|
|
15599
|
-
* handed out to subgraphs. Meaningful only on the root graph; `assignSubgSeq`
|
|
15600
|
-
* pre-increments it. Other graphs leave it at 0.
|
|
15601
|
-
* @see lib/cgraph/graph.c:agnextseq (++clos->seq[AGRAPH])
|
|
15602
|
-
*/
|
|
15603
|
-
subgSeqCounter = 0;
|
|
15604
|
-
/**
|
|
15605
|
-
* Names of graph attributes (AGRAPH) declared anywhere in this hierarchy —
|
|
15606
|
-
* the port's stand-in for cgraph's `Agsym_t` symbol table. Populated on the
|
|
15607
|
-
* ROOT only, at parse time, whenever a graph attribute is assigned on any
|
|
15608
|
-
* (sub)graph: setting `ordering=out` on a subgraph declares "ordering"
|
|
15609
|
-
* graph-wide with an empty default, so `agGraphAttr(root, "ordering")` returns
|
|
15610
|
-
* `""` (not undefined) — mirroring `agfindgraphattr`/`late_string`. Read via
|
|
15611
|
-
* `agGraphAttr` (model/cgraph-ops.ts); empty on non-root graphs.
|
|
15612
|
-
* @see lib/cgraph/attr.c:agattr (graph-wide declaration, "" default)
|
|
15613
|
-
*/
|
|
15614
|
-
declaredGraphAttrs = /* @__PURE__ */ new Set();
|
|
15615
|
-
/** @see lib/cgraph/graph.c:agopen */
|
|
15616
|
-
constructor(name, kind, anonymous = false) {
|
|
15617
|
-
this.name = name;
|
|
15618
|
-
this.anonymous = anonymous;
|
|
15619
|
-
this.kind = kind;
|
|
15620
|
-
this.nodes = /* @__PURE__ */ new Map();
|
|
15621
|
-
this.edges = [];
|
|
15622
|
-
this.subgraphs = /* @__PURE__ */ new Map();
|
|
15623
|
-
this.attrs = /* @__PURE__ */ new Map();
|
|
15624
|
-
this.nodeDefaults = /* @__PURE__ */ new Map();
|
|
15625
|
-
this.edgeDefaults = /* @__PURE__ */ new Map();
|
|
15626
|
-
this.info = makeGraphInfo();
|
|
15627
|
-
this.parent = null;
|
|
15628
|
-
this.root = this;
|
|
15629
|
-
}
|
|
15630
|
-
};
|
|
15631
|
-
|
|
15632
15961
|
// src/model/cgraph-ops.ts
|
|
15633
15962
|
var LOCALNAMEPREFIX = "%";
|
|
15634
15963
|
function freshNodeId(root) {
|
|
@@ -25057,18 +25386,22 @@ function dotSameports(g) {
|
|
|
25057
25386
|
function dist2(p, q) {
|
|
25058
25387
|
const dx = p.x - q.x;
|
|
25059
25388
|
const dy = p.y - q.y;
|
|
25060
|
-
return dx
|
|
25389
|
+
return fma(dx, dx, dy * dy);
|
|
25061
25390
|
}
|
|
25062
25391
|
function distPt(p, q) {
|
|
25063
25392
|
return Math.sqrt(dist2(p, q));
|
|
25064
25393
|
}
|
|
25065
|
-
function
|
|
25394
|
+
function bezier(v, t) {
|
|
25066
25395
|
const u = 1 - t;
|
|
25067
|
-
const [
|
|
25068
|
-
|
|
25069
|
-
|
|
25070
|
-
|
|
25071
|
-
|
|
25396
|
+
const x = [v[0].x, v[1].x, v[2].x, v[3].x];
|
|
25397
|
+
const y = [v[0].y, v[1].y, v[2].y, v[3].y];
|
|
25398
|
+
for (let i = 1; i <= 3; i++) {
|
|
25399
|
+
for (let j = 0; j <= 3 - i; j++) {
|
|
25400
|
+
x[j] = fma(x[j], u, t * x[j + 1]);
|
|
25401
|
+
y[j] = fma(y[j], u, t * y[j + 1]);
|
|
25402
|
+
}
|
|
25403
|
+
}
|
|
25404
|
+
return { x: x[0], y: y[0] };
|
|
25072
25405
|
}
|
|
25073
25406
|
function dotneatoClosest(spl, pt) {
|
|
25074
25407
|
let besti = 0;
|
|
@@ -25098,7 +25431,7 @@ function dotneatoClosest(spl, pt) {
|
|
|
25098
25431
|
let pt2;
|
|
25099
25432
|
for (; ; ) {
|
|
25100
25433
|
const t = (lo + hi) / 2;
|
|
25101
|
-
pt2 =
|
|
25434
|
+
pt2 = bezier(c, t);
|
|
25102
25435
|
if (Math.abs(dlo2 - dhi2) < 1 || Math.abs(hi - lo) < 1e-5) break;
|
|
25103
25436
|
if (dlo2 < dhi2) {
|
|
25104
25437
|
hi = t;
|
|
@@ -26010,9 +26343,19 @@ var ShortestHelper = class _ShortestHelper {
|
|
|
26010
26343
|
_ShortestHelper.connectAll(tris);
|
|
26011
26344
|
const ftrii = _ShortestHelper.findTri(tris, eps[0]);
|
|
26012
26345
|
const ltrii = _ShortestHelper.findTri(tris, eps[1]);
|
|
26013
|
-
if (ftrii === NO_TRI
|
|
26346
|
+
if (ftrii === NO_TRI) {
|
|
26347
|
+
console.warn("source point not in any triangle");
|
|
26348
|
+
return null;
|
|
26349
|
+
}
|
|
26350
|
+
if (ltrii === NO_TRI) {
|
|
26351
|
+
console.warn("destination point not in any triangle");
|
|
26352
|
+
return null;
|
|
26353
|
+
}
|
|
26014
26354
|
if (ftrii === ltrii) return [eps[0], eps[1]];
|
|
26015
|
-
if (!_ShortestHelper.markPath(tris, ftrii, ltrii))
|
|
26355
|
+
if (!_ShortestHelper.markPath(tris, ftrii, ltrii)) {
|
|
26356
|
+
console.warn("cannot find triangle path");
|
|
26357
|
+
return [eps[0], eps[1]];
|
|
26358
|
+
}
|
|
26016
26359
|
const epnls = [{ pp: eps[0], link: null }, { pp: eps[1], link: null }];
|
|
26017
26360
|
const dq = _ShortestHelper.initDeque(pnlps.length);
|
|
26018
26361
|
_ShortestHelper.add2dq(dq, DQ_FRONT, epnls[0]);
|
|
@@ -27994,7 +28337,7 @@ function nodeCover(n) {
|
|
|
27994
28337
|
for (let i = 0; i < NODECARD; i++) {
|
|
27995
28338
|
if (n.branch[i].child !== null) {
|
|
27996
28339
|
if (flag) {
|
|
27997
|
-
r = n.branch[i].rect;
|
|
28340
|
+
r = { boundary: [...n.branch[i].rect.boundary] };
|
|
27998
28341
|
flag = false;
|
|
27999
28342
|
} else {
|
|
28000
28343
|
r = combineRect(r, n.branch[i].rect);
|
|
@@ -30260,8 +30603,8 @@ function nodeInsideFn2(box) {
|
|
|
30260
30603
|
const pw = box.penwidth ?? DEFAULT_NODEPENWIDTH;
|
|
30261
30604
|
return box.isEllipse ? makeEllipseInsideFn(halfW, halfH, pw) : makeBoxInsideFn(halfW, halfH, pw);
|
|
30262
30605
|
}
|
|
30263
|
-
function clipToNodes(
|
|
30264
|
-
const step1 = clip.tail ? bezierClipNode(
|
|
30606
|
+
function clipToNodes(bezier2, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
|
|
30607
|
+
const step1 = clip.tail ? bezierClipNode(bezier2, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier2;
|
|
30265
30608
|
const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
|
|
30266
30609
|
const arrowTip = step2[3];
|
|
30267
30610
|
const elen = normalArrowLen(penwidth);
|
|
@@ -30275,9 +30618,9 @@ function clipToNodes(bezier, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH,
|
|
|
30275
30618
|
function routeWithRank(tailBox, headBox, rank3, penwidth = DEFAULT_NODEPENWIDTH, port) {
|
|
30276
30619
|
const corridor = port ? { tailP: port.tailP, headP: port.headP } : void 0;
|
|
30277
30620
|
const { startPt, endPt, boxes } = buildRankCorridor(tailBox, headBox, rank3, corridor);
|
|
30278
|
-
const
|
|
30621
|
+
const bezier2 = computeSpline(boxes, startPt, endPt);
|
|
30279
30622
|
const clip = port ? { tail: port.clipTail, head: port.clipHead } : CLIP_BOTH;
|
|
30280
|
-
const { clipped, arrowTip, arrowDir } = clipToNodes(
|
|
30623
|
+
const { clipped, arrowTip, arrowDir } = clipToNodes(bezier2, tailBox, headBox, penwidth, clip);
|
|
30281
30624
|
return { bezierPts: clipped, arrowTip, arrowDir };
|
|
30282
30625
|
}
|
|
30283
30626
|
function routeSimple(tailBox, headBox, routeBezierFn) {
|
|
@@ -32870,24 +33213,27 @@ function buildNodes(nodeArr) {
|
|
|
32870
33213
|
ysize: n.info.ht
|
|
32871
33214
|
}));
|
|
32872
33215
|
}
|
|
33216
|
+
function isConcentrateDup(ps, e) {
|
|
33217
|
+
const ti = e.tail.id;
|
|
33218
|
+
const hi = e.head.id;
|
|
33219
|
+
const lo = ti <= hi ? ti : hi;
|
|
33220
|
+
const up = ti <= hi ? hi : ti;
|
|
33221
|
+
if (ps.isInPS(lo, up)) return true;
|
|
33222
|
+
ps.addPS(lo, up);
|
|
33223
|
+
return false;
|
|
33224
|
+
}
|
|
32873
33225
|
function buildEdges(g, nodeArr, orthoNodes) {
|
|
32874
33226
|
const concentrate = dotRoot(g).info.concentrate ?? false;
|
|
32875
33227
|
const nodeIndex = /* @__PURE__ */ new Map();
|
|
32876
33228
|
nodeArr.forEach((n, i) => nodeIndex.set(n, i));
|
|
32877
33229
|
const outIndex = buildOutEdgeIndex(g);
|
|
32878
|
-
const
|
|
33230
|
+
const ps = concentrate ? new PointSet() : null;
|
|
32879
33231
|
const result = [];
|
|
32880
33232
|
for (const n of nodeArr) {
|
|
32881
33233
|
const oes = outIndex.get(n);
|
|
32882
33234
|
if (oes === void 0) continue;
|
|
32883
33235
|
for (const e of oes) {
|
|
32884
|
-
if (
|
|
32885
|
-
const ti = e.tail.id;
|
|
32886
|
-
const hi = e.head.id;
|
|
32887
|
-
const key = ti <= hi ? `${ti},${hi}` : `${hi},${ti}`;
|
|
32888
|
-
if (seen.has(key)) continue;
|
|
32889
|
-
seen.add(key);
|
|
32890
|
-
}
|
|
33236
|
+
if (ps !== null && isConcentrateDup(ps, e)) continue;
|
|
32891
33237
|
result.push({
|
|
32892
33238
|
tail: orthoNodes[nodeIndex.get(e.tail)],
|
|
32893
33239
|
head: orthoNodes[nodeIndex.get(e.head)],
|
|
@@ -33975,15 +34321,6 @@ function spiralSearch(info, ctx, wide) {
|
|
|
33975
34321
|
|
|
33976
34322
|
// src/layout/pack/poly-pack.ts
|
|
33977
34323
|
var C2 = 100;
|
|
33978
|
-
function psKey(x, y) {
|
|
33979
|
-
return `${cround(x)},${cround(y)}`;
|
|
33980
|
-
}
|
|
33981
|
-
function inPS(ps, p) {
|
|
33982
|
-
return ps.has(psKey(p.x, p.y));
|
|
33983
|
-
}
|
|
33984
|
-
function insertPS(ps, p) {
|
|
33985
|
-
ps.add(psKey(p.x, p.y));
|
|
33986
|
-
}
|
|
33987
34324
|
function computeStep(ng, bbs, margin) {
|
|
33988
34325
|
let b = 0;
|
|
33989
34326
|
let c = 0;
|
|
@@ -34030,14 +34367,14 @@ function genBox2(p) {
|
|
|
34030
34367
|
function hasCollision(cells, dx, dy, ps) {
|
|
34031
34368
|
for (let i = 0; i < cells.length; i++) {
|
|
34032
34369
|
const cell2 = cells[i];
|
|
34033
|
-
if (cell2 !== void 0 && inPS(
|
|
34370
|
+
if (cell2 !== void 0 && ps.inPS({ x: cell2.x + dx, y: cell2.y + dy })) return true;
|
|
34034
34371
|
}
|
|
34035
34372
|
return false;
|
|
34036
34373
|
}
|
|
34037
34374
|
function markCells(cells, dx, dy, ps) {
|
|
34038
34375
|
for (let i = 0; i < cells.length; i++) {
|
|
34039
34376
|
const cell2 = cells[i];
|
|
34040
|
-
if (cell2 !== void 0)
|
|
34377
|
+
if (cell2 !== void 0) ps.addPS(cell2.x + dx, cell2.y + dy);
|
|
34041
34378
|
}
|
|
34042
34379
|
}
|
|
34043
34380
|
function fits(x, y, info, ctx) {
|
|
@@ -34082,7 +34419,7 @@ function polyRects(ng, bbs, pinfo) {
|
|
|
34082
34419
|
infos.push(genBox2({ bb, ssize: step, margin: pinfo.margin, idx: i }));
|
|
34083
34420
|
}
|
|
34084
34421
|
const sorted = gvQsort([...infos], cmpByGPerimeter);
|
|
34085
|
-
const ctx = { ps:
|
|
34422
|
+
const ctx = { ps: new PointSet(), step, bbs };
|
|
34086
34423
|
const places = new Array(ng).fill({ x: 0, y: 0 });
|
|
34087
34424
|
for (let i = 0; i < sorted.length; i++) {
|
|
34088
34425
|
const info = sorted[i];
|
|
@@ -34103,21 +34440,6 @@ function cval2(v, s) {
|
|
|
34103
34440
|
function cell(p, s) {
|
|
34104
34441
|
return { x: cval2(p.x, s), y: cval2(p.y, s) };
|
|
34105
34442
|
}
|
|
34106
|
-
var PointSet = class {
|
|
34107
|
-
m = /* @__PURE__ */ new Map();
|
|
34108
|
-
add(x, y) {
|
|
34109
|
-
this.m.set(`${x},${y}`, { x, y });
|
|
34110
|
-
}
|
|
34111
|
-
has(p) {
|
|
34112
|
-
return this.m.has(`${p.x},${p.y}`);
|
|
34113
|
-
}
|
|
34114
|
-
points() {
|
|
34115
|
-
return [...this.m.values()];
|
|
34116
|
-
}
|
|
34117
|
-
get size() {
|
|
34118
|
-
return this.m.size;
|
|
34119
|
-
}
|
|
34120
|
-
};
|
|
34121
34443
|
function computeStep2(bbs, margin) {
|
|
34122
34444
|
const a = C_AVG * bbs.length - 1;
|
|
34123
34445
|
let b = 0;
|
|
@@ -34135,7 +34457,7 @@ function computeStep2(bbs, margin) {
|
|
|
34135
34457
|
function lineXDominant(st, ps) {
|
|
34136
34458
|
let d = st.ay - (st.ax >> 1);
|
|
34137
34459
|
for (; ; ) {
|
|
34138
|
-
ps.
|
|
34460
|
+
ps.addPS(st.x, st.y);
|
|
34139
34461
|
if (st.x === st.x2) return;
|
|
34140
34462
|
if (d >= 0) {
|
|
34141
34463
|
st.y += st.sy;
|
|
@@ -34148,7 +34470,7 @@ function lineXDominant(st, ps) {
|
|
|
34148
34470
|
function lineYDominant(st, ps) {
|
|
34149
34471
|
let d = st.ax - (st.ay >> 1);
|
|
34150
34472
|
for (; ; ) {
|
|
34151
|
-
ps.
|
|
34473
|
+
ps.addPS(st.x, st.y);
|
|
34152
34474
|
if (st.y === st.y2) return;
|
|
34153
34475
|
if (d >= 0) {
|
|
34154
34476
|
st.x += st.sx;
|
|
@@ -34180,7 +34502,7 @@ function fillLine(p, q, ps) {
|
|
|
34180
34502
|
}
|
|
34181
34503
|
function fillRect(LL, UR, ps) {
|
|
34182
34504
|
for (let x = LL.x; x <= UR.x; x++) {
|
|
34183
|
-
for (let y = LL.y; y <= UR.y; y++) ps.
|
|
34505
|
+
for (let y = LL.y; y <= UR.y; y++) ps.addPS(x, y);
|
|
34184
34506
|
}
|
|
34185
34507
|
}
|
|
34186
34508
|
function roundedCell(p, ssize) {
|
|
@@ -34232,7 +34554,7 @@ function genBox3(bb0, ssize, margin, center) {
|
|
|
34232
34554
|
const UR = roundedCell({ x: center.x + bbW + margin, y: center.y + bbH + margin }, ssize);
|
|
34233
34555
|
fillRect(LL, UR, ps);
|
|
34234
34556
|
return {
|
|
34235
|
-
cells: ps.
|
|
34557
|
+
cells: ps.pointsOf(),
|
|
34236
34558
|
perim: grid(bb0.ur.x - bb0.ll.x + 2 * margin, ssize) + grid(bb0.ur.y - bb0.ll.y + 2 * margin, ssize),
|
|
34237
34559
|
index: 0
|
|
34238
34560
|
};
|
|
@@ -34264,42 +34586,38 @@ function genPoly(root, g, bb, ssize, pinfo, center) {
|
|
|
34264
34586
|
};
|
|
34265
34587
|
for (const n of g.nodes.values()) coverNode(n, ctx);
|
|
34266
34588
|
return {
|
|
34267
|
-
cells: ps.
|
|
34589
|
+
cells: ps.pointsOf(),
|
|
34268
34590
|
perim: grid(bb.ur.x - bb.ll.x + 2 * pinfo.margin, ssize) + grid(bb.ur.y - bb.ll.y + 2 * pinfo.margin, ssize),
|
|
34269
34591
|
index: 0
|
|
34270
34592
|
};
|
|
34271
34593
|
}
|
|
34272
34594
|
function fits2(x, y, info, ctx) {
|
|
34273
34595
|
for (const c of info.cells) {
|
|
34274
|
-
if (ctx.ps.
|
|
34596
|
+
if (ctx.ps.isInPS(c.x + x, c.y + y)) return false;
|
|
34275
34597
|
}
|
|
34276
34598
|
const bb = ctx.bbs[info.index];
|
|
34277
34599
|
const LL = { x: cround(bb.ll.x), y: cround(bb.ll.y) };
|
|
34278
34600
|
ctx.places[info.index] = { x: Math.imul(ctx.step, x) - LL.x, y: Math.imul(ctx.step, y) - LL.y };
|
|
34279
|
-
for (const c of info.cells) ctx.ps.
|
|
34601
|
+
for (const c of info.cells) ctx.ps.addPS(c.x + x, c.y + y);
|
|
34280
34602
|
return true;
|
|
34281
34603
|
}
|
|
34282
|
-
function
|
|
34283
|
-
|
|
34284
|
-
|
|
34285
|
-
|
|
34286
|
-
|
|
34287
|
-
|
|
34288
|
-
|
|
34289
|
-
|
|
34290
|
-
|
|
34291
|
-
|
|
34292
|
-
|
|
34293
|
-
|
|
34294
|
-
|
|
34295
|
-
for (; x < bnd; x++) yield [x, y];
|
|
34296
|
-
for (; y < bnd; y++) yield [x, y];
|
|
34297
|
-
for (; x > -bnd; x--) yield [x, y];
|
|
34298
|
-
for (; y > 0; y--) yield [x, y];
|
|
34604
|
+
function leg(c, dx, dy, end, info, ctx) {
|
|
34605
|
+
for (; (dx !== 0 ? c.x : c.y) !== end; c.x += dx, c.y += dy) {
|
|
34606
|
+
if (fits2(c.x, c.y, info, ctx)) return true;
|
|
34607
|
+
}
|
|
34608
|
+
return false;
|
|
34609
|
+
}
|
|
34610
|
+
function ringWide(bnd, info, ctx) {
|
|
34611
|
+
const c = { x: 0, y: -bnd };
|
|
34612
|
+
return leg(c, 1, 0, bnd, info, ctx) || leg(c, 0, 1, bnd, info, ctx) || leg(c, -1, 0, -bnd, info, ctx) || leg(c, 0, -1, -bnd, info, ctx) || leg(c, 1, 0, 0, info, ctx);
|
|
34613
|
+
}
|
|
34614
|
+
function ringTall(bnd, info, ctx) {
|
|
34615
|
+
const c = { x: -bnd, y: 0 };
|
|
34616
|
+
return leg(c, 0, -1, -bnd, info, ctx) || leg(c, 1, 0, bnd, info, ctx) || leg(c, 0, 1, bnd, info, ctx) || leg(c, -1, 0, -bnd, info, ctx) || leg(c, 0, -1, 0, info, ctx);
|
|
34299
34617
|
}
|
|
34300
34618
|
function placeFixed(info, ctx, center) {
|
|
34301
34619
|
ctx.places[info.index] = { x: -center.x, y: -center.y };
|
|
34302
|
-
for (const c of info.cells) ctx.ps.
|
|
34620
|
+
for (const c of info.cells) ctx.ps.addPS(c.x, c.y);
|
|
34303
34621
|
}
|
|
34304
34622
|
function placeGraph2(i, info, ctx) {
|
|
34305
34623
|
const bb = ctx.bbs[info.index];
|
|
@@ -34311,10 +34629,7 @@ function placeGraph2(i, info, ctx) {
|
|
|
34311
34629
|
if (fits2(0, 0, info, ctx)) return;
|
|
34312
34630
|
const wide = Math.ceil(bb.ur.x - bb.ll.x) >= Math.ceil(bb.ur.y - bb.ll.y);
|
|
34313
34631
|
for (let bnd = 1; ; bnd++) {
|
|
34314
|
-
|
|
34315
|
-
for (const [x, y] of ring) {
|
|
34316
|
-
if (fits2(x, y, info, ctx)) return;
|
|
34317
|
-
}
|
|
34632
|
+
if (wide ? ringWide(bnd, info, ctx) : ringTall(bnd, info, ctx)) return;
|
|
34318
34633
|
}
|
|
34319
34634
|
}
|
|
34320
34635
|
function polyGraphs(gs, root, pinfo, bbs) {
|
|
@@ -37954,6 +38269,12 @@ function chainOf(e) {
|
|
|
37954
38269
|
}
|
|
37955
38270
|
return list;
|
|
37956
38271
|
}
|
|
38272
|
+
function warnNoControlPoints(e) {
|
|
38273
|
+
console.warn(
|
|
38274
|
+
`Warning: Could not create control points for multiple spline for edge (${e.tail.name},${e.head.name})`
|
|
38275
|
+
);
|
|
38276
|
+
return 1;
|
|
38277
|
+
}
|
|
37957
38278
|
function genroute(g, trip, t, e, doPolyline) {
|
|
37958
38279
|
const eps = [
|
|
37959
38280
|
{ x: trip.ps[0].x, y: trip.ps[0].y },
|
|
@@ -37963,7 +38284,7 @@ function genroute(g, trip, t, e, doPolyline) {
|
|
|
37963
38284
|
const mult = e.info.count ?? 1;
|
|
37964
38285
|
const head = e.head;
|
|
37965
38286
|
const pl = shortestPath({ ps: trip.ps }, eps);
|
|
37966
|
-
if (pl === null) return
|
|
38287
|
+
if (pl === null) return warnNoControlPoints(e);
|
|
37967
38288
|
if (pl.length === 2) {
|
|
37968
38289
|
const chain = chainOf(e);
|
|
37969
38290
|
makeStraightEdges(g, chain, chain.length, doPolyline ? 1 : 0, MSINFO);
|
|
@@ -37971,7 +38292,7 @@ function genroute(g, trip, t, e, doPolyline) {
|
|
|
37971
38292
|
}
|
|
37972
38293
|
if (mult === 1 || concentrate) {
|
|
37973
38294
|
const spl = routeMember(trip.ps, t, pl, doPolyline);
|
|
37974
|
-
if (spl === null) return
|
|
38295
|
+
if (spl === null) return warnNoControlPoints(e);
|
|
37975
38296
|
finishEdge(e, spl, e.head !== head);
|
|
37976
38297
|
return 0;
|
|
37977
38298
|
}
|
|
@@ -37979,7 +38300,7 @@ function genroute(g, trip, t, e, doPolyline) {
|
|
|
37979
38300
|
const cpts = [];
|
|
37980
38301
|
for (let i = 0; i + 2 < pl.length; i++) {
|
|
37981
38302
|
const cp = mkCtrlPts(t, mult + 1, pl[i], pl[i + 1], pl[i + 2], trip);
|
|
37982
|
-
if (cp === null) return
|
|
38303
|
+
if (cp === null) return warnNoControlPoints(e);
|
|
37983
38304
|
cpts.push(cp);
|
|
37984
38305
|
}
|
|
37985
38306
|
let cur = e;
|
|
@@ -37994,9 +38315,9 @@ function genroute(g, trip, t, e, doPolyline) {
|
|
|
37994
38315
|
poly[pn - j] = cpts[j - 1][i + 1];
|
|
37995
38316
|
}
|
|
37996
38317
|
const mmpl = shortestPath({ ps: poly }, eps);
|
|
37997
|
-
if (mmpl === null) return
|
|
38318
|
+
if (mmpl === null) return warnNoControlPoints(cur);
|
|
37998
38319
|
const spl = routeMember(poly, pl.length - 1, mmpl, doPolyline);
|
|
37999
|
-
if (spl === null) return
|
|
38320
|
+
if (spl === null) return warnNoControlPoints(cur);
|
|
38000
38321
|
finishEdge(cur, spl, cur.head !== head);
|
|
38001
38322
|
cur = cur.info.to_virt;
|
|
38002
38323
|
}
|
|
@@ -47220,22 +47541,22 @@ function freeBlocktree(bp) {
|
|
|
47220
47541
|
|
|
47221
47542
|
// src/layout/circo/position-helpers.ts
|
|
47222
47543
|
function rotatePoint(x, y, cosR, sinR) {
|
|
47223
|
-
return [x
|
|
47544
|
+
return [fma(x, cosR, -sinR * y), fma(x, sinR, cosR * y)];
|
|
47224
47545
|
}
|
|
47225
47546
|
function nodePsi(n) {
|
|
47226
47547
|
return n.info.alg?.psi ?? 0;
|
|
47227
47548
|
}
|
|
47228
47549
|
function rotFromParentPos(sn, theta) {
|
|
47229
|
-
let r = theta + Math.PI - sn.parentPos;
|
|
47550
|
+
let r = theta + (Math.PI - sn.parentPos);
|
|
47230
47551
|
if (r < 0) r += 2 * Math.PI;
|
|
47231
47552
|
return r;
|
|
47232
47553
|
}
|
|
47233
47554
|
function closestNode(sn, x, y, skip) {
|
|
47234
47555
|
let best = skip;
|
|
47235
|
-
let bestDist =
|
|
47556
|
+
let bestDist = libmHypot(skip.info.pos[0] + x, skip.info.pos[1] + y);
|
|
47236
47557
|
for (const dn of sn.subGraph.nodes) {
|
|
47237
47558
|
if (dn.orig === skip) continue;
|
|
47238
|
-
const d =
|
|
47559
|
+
const d = libmHypot(dn.orig.info.pos[0] + x, dn.orig.info.pos[1] + y);
|
|
47239
47560
|
if (d < bestDist) {
|
|
47240
47561
|
bestDist = d;
|
|
47241
47562
|
best = dn.orig;
|
|
@@ -47248,22 +47569,19 @@ function rotCoalesced(sn, x, y, nbr, theta) {
|
|
|
47248
47569
|
const r = sn.radius - rho;
|
|
47249
47570
|
const nx = nbr.info.pos[0];
|
|
47250
47571
|
const ny = nbr.info.pos[1];
|
|
47251
|
-
|
|
47252
|
-
const phi2 = Math.atan2(ny, nx);
|
|
47253
|
-
return theta + Math.PI - phi2 - nodePsi(nbr);
|
|
47254
|
-
}
|
|
47255
|
-
const R2 = Math.hypot(x, y);
|
|
47572
|
+
const R2 = libmHypot(x, y);
|
|
47256
47573
|
const phi = Math.atan2(ny, nx + r);
|
|
47257
47574
|
const l = r - rho / Math.cos(phi);
|
|
47258
|
-
return theta + Math.PI / 2 - phi - Math.asin(l / R2 * Math.cos(phi));
|
|
47575
|
+
return theta + (Math.PI / 2 - phi - Math.asin(l / R2 * Math.cos(phi)));
|
|
47259
47576
|
}
|
|
47260
47577
|
function rotGeneral(sn, x, y, nbr, theta) {
|
|
47261
47578
|
if (closestNode(sn, x, y, nbr) === nbr) return 0;
|
|
47262
|
-
|
|
47579
|
+
const r = sn.radius - sn.rad0;
|
|
47580
|
+
if (isCoalesced(sn) && -r < nbr.info.pos[0]) return rotCoalesced(sn, x, y, nbr, theta);
|
|
47263
47581
|
const phi = Math.atan2(nbr.info.pos[1], nbr.info.pos[0]);
|
|
47264
|
-
let
|
|
47265
|
-
if (
|
|
47266
|
-
return
|
|
47582
|
+
let t = theta + (Math.PI - phi - nodePsi(nbr));
|
|
47583
|
+
if (t > 2 * Math.PI) t -= 2 * Math.PI;
|
|
47584
|
+
return t;
|
|
47267
47585
|
}
|
|
47268
47586
|
function applyDelta(sn, x, y, rotate) {
|
|
47269
47587
|
const cosR = Math.cos(rotate);
|
|
@@ -47306,7 +47624,7 @@ function getInfo(pi, stp, minDist) {
|
|
|
47306
47624
|
}
|
|
47307
47625
|
function setInfo(p0, p1, delta2) {
|
|
47308
47626
|
const t = Math.max(
|
|
47309
|
-
(p0.diameter
|
|
47627
|
+
fma(p0.diameter, p1.minRadius, p1.diameter * p0.minRadius) / (2 * delta2 * p0.minRadius * p1.minRadius),
|
|
47310
47628
|
1
|
|
47311
47629
|
);
|
|
47312
47630
|
p0.scale = Math.max(p0.scale, t);
|
|
@@ -47316,7 +47634,13 @@ function placeChild(child, ca, ctx) {
|
|
|
47316
47634
|
const dx = ctx.childRadius * Math.cos(ca);
|
|
47317
47635
|
const dy = ctx.childRadius * Math.sin(ca);
|
|
47318
47636
|
applyDelta(child, dx, dy, getRotation(child, dx, dy, ca));
|
|
47319
|
-
return
|
|
47637
|
+
return nextChildAngle(ca, ctx.incAngle, ctx.mindistAngle, ctx.length);
|
|
47638
|
+
}
|
|
47639
|
+
function nextChildAngle(ca, inc2, mda, length) {
|
|
47640
|
+
return length === 1 ? ca + (inc2 + mda) : ca + (inc2 + mda / 2);
|
|
47641
|
+
}
|
|
47642
|
+
function leftoverArc(childRadius, diameter) {
|
|
47643
|
+
return fma(2 * Math.PI, childRadius, -diameter);
|
|
47320
47644
|
}
|
|
47321
47645
|
function advanceAngleL1(ca, inc2, total, cnt, stp) {
|
|
47322
47646
|
const next = cnt === 0 ? 0 : total === 2 ? Math.PI : ca + inc2;
|
|
@@ -47326,7 +47650,7 @@ function advanceAngleL1(ca, inc2, total, cnt, stp) {
|
|
|
47326
47650
|
}
|
|
47327
47651
|
function advanceAngleLN(ca, inc2, mda, total, theta) {
|
|
47328
47652
|
if (total === 1) return theta;
|
|
47329
|
-
return ca + inc2 + mda / 2;
|
|
47653
|
+
return ca + (inc2 + mda / 2);
|
|
47330
47654
|
}
|
|
47331
47655
|
function maybeWritePsi(n, stp, ca, isMid) {
|
|
47332
47656
|
if (isMid && n === stp.neighbor) {
|
|
@@ -47341,7 +47665,7 @@ function positionChildren(pi, stp, length, minDist) {
|
|
|
47341
47665
|
let md = minDist;
|
|
47342
47666
|
if (length === 1) {
|
|
47343
47667
|
cr = Math.max(cr, pi.diameter / (2 * Math.PI));
|
|
47344
|
-
const d =
|
|
47668
|
+
const d = leftoverArc(cr, pi.diameter);
|
|
47345
47669
|
if (d > 0) md += d / pi.childCount;
|
|
47346
47670
|
}
|
|
47347
47671
|
stp.subtreeR = Math.max(stp.subtreeR, cr + pi.maxRadius);
|
|
@@ -54370,11 +54694,11 @@ function lexToken(s, i) {
|
|
|
54370
54694
|
function scanNumberAmbiguities(src, stripped) {
|
|
54371
54695
|
const out = [];
|
|
54372
54696
|
let line = 1;
|
|
54373
|
-
let
|
|
54697
|
+
let lineAt2 = 0;
|
|
54374
54698
|
for (let i = 0; i < stripped.length; ) {
|
|
54375
54699
|
const { next, bad } = lexToken(stripped, i);
|
|
54376
54700
|
if (bad !== null) {
|
|
54377
|
-
for (;
|
|
54701
|
+
for (; lineAt2 < i; lineAt2++) if (src[lineAt2] === "\n") line++;
|
|
54378
54702
|
out.push({ text: bad, line, offset: i });
|
|
54379
54703
|
}
|
|
54380
54704
|
i = next;
|