@reportwright/cli 0.11.0 → 0.12.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/CHANGELOG.md +81 -0
- package/README.md +1 -1
- package/dist/pw.mjs +743 -601
- package/dist/pw.mjs.map +3 -3
- package/package.json +2 -2
package/dist/pw.mjs
CHANGED
|
@@ -3849,9 +3849,23 @@ function nodeRequest(url, init, trusted) {
|
|
|
3849
3849
|
for (let i = 0; i < res.rawHeaders.length; i += 2) pairs2.push([res.rawHeaders[i], res.rawHeaders[i + 1]]);
|
|
3850
3850
|
const none = [101, 204, 205, 304].includes(res.statusCode) || (init.method || "GET").toUpperCase() === "HEAD";
|
|
3851
3851
|
if (none) res.resume();
|
|
3852
|
-
|
|
3852
|
+
const enc = String(res.headers["content-encoding"] || "").trim().toLowerCase();
|
|
3853
|
+
let body = res, decoded = false;
|
|
3854
|
+
if (!none && enc && enc !== "identity") {
|
|
3855
|
+
const zlib = nodeMod("node:zlib");
|
|
3856
|
+
const dec2 = enc === "gzip" || enc === "x-gzip" ? zlib.createGunzip() : enc === "deflate" ? zlib.createInflate() : enc === "br" ? zlib.createBrotliDecompress() : null;
|
|
3857
|
+
if (!dec2) {
|
|
3858
|
+
res.resume();
|
|
3859
|
+
return reject(Object.assign(new Error(`the response is encoded as "${enc}", which the data fetch cannot decode`), { status: 415 }));
|
|
3860
|
+
}
|
|
3861
|
+
body = stream.pipeline(res, dec2, () => {
|
|
3862
|
+
});
|
|
3863
|
+
decoded = true;
|
|
3864
|
+
}
|
|
3865
|
+
const kept = decoded ? pairs2.filter(([k]) => !/^(content-encoding|content-length)$/i.test(k)) : pairs2;
|
|
3866
|
+
resolve(new Response(none ? null : stream.Readable.toWeb(body), { status: res.statusCode, statusText: res.statusMessage, headers: (
|
|
3853
3867
|
/** @type {any} */
|
|
3854
|
-
|
|
3868
|
+
kept
|
|
3855
3869
|
) }));
|
|
3856
3870
|
});
|
|
3857
3871
|
req.on("error", reject);
|
|
@@ -3869,7 +3883,7 @@ function redirectRequest(from, to, req, status) {
|
|
|
3869
3883
|
}
|
|
3870
3884
|
function guardedFetch(opt, base) {
|
|
3871
3885
|
const allow = (opt.allowHosts || []).map((h) => String(h).toLowerCase().replace(/^\[|\]$/g, ""));
|
|
3872
|
-
const node2 = inNode();
|
|
3886
|
+
const node2 = !opt.viaBase && inNode();
|
|
3873
3887
|
return (
|
|
3874
3888
|
/** @type {any} */
|
|
3875
3889
|
(async (input, init = {}) => {
|
|
@@ -4802,7 +4816,10 @@ function fetcherFor(opt) {
|
|
|
4802
4816
|
return boundedFetch(f4, opt);
|
|
4803
4817
|
}
|
|
4804
4818
|
function checkHostSource(src, url, opt) {
|
|
4805
|
-
|
|
4819
|
+
const rule = opt.fetch ? opt.fetch.hostRule : opt.unsafeFetch ? null : opt;
|
|
4820
|
+
if (!rule) return;
|
|
4821
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(String(url).trim());
|
|
4822
|
+
if (scheme && !/^https?$/i.test(scheme[1])) throw Object.assign(new Error(`Only http and https URLs can be fetched, not ${scheme[1].toLowerCase()}:`), { status: 400 });
|
|
4806
4823
|
const t = String(src.url ?? "").trim();
|
|
4807
4824
|
if (/^\/(?![/\\])/.test(t)) return;
|
|
4808
4825
|
const m = /^https?:\/\/([^/?#\\]*)/i.exec(t);
|
|
@@ -4813,7 +4830,7 @@ function checkHostSource(src, url, opt) {
|
|
|
4813
4830
|
host = new URL(url).hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
4814
4831
|
} catch {
|
|
4815
4832
|
}
|
|
4816
|
-
if (whole && host && (
|
|
4833
|
+
if (whole && host && (rule.allowHosts || []).map((h) => String(h).toLowerCase()).includes(host)) return;
|
|
4817
4834
|
throw Object.assign(new Error("its host is made by a parameter or an expression: write the scheme and host out (parameters may fill the path and query), or make the whole URL a parameter and list its host in allowHosts"), { status: 403 });
|
|
4818
4835
|
}
|
|
4819
4836
|
async function loadSources(def, opt) {
|
|
@@ -11348,7 +11365,8 @@ function toRdlx3(root, notes, reportName) {
|
|
|
11348
11365
|
const on = prop(b, "aggregateOn") ?? simpleList(b, "aggregateOn")[0]?.text;
|
|
11349
11366
|
const gc = { ...c, group: on && on !== "All" ? on : void 0 };
|
|
11350
11367
|
if (fn3) {
|
|
11351
|
-
const arg = listProp(b, "arguments").map((x) => prop(x, "value")).find((x) => x != null);
|
|
11368
|
+
const arg = listProp(b, "arguments").map((x) => prop(x, "value")).find((x) => x != null) ?? prop(b, "expression");
|
|
11369
|
+
if (arg == null && fn3 !== "count") throw new Untranslatable2(`the aggregate ${fn3.toUpperCase()} with no expression`);
|
|
11352
11370
|
const inner2 = arg != null ? vb2(arg, { ...c, inSet: false }, depth) : "1";
|
|
11353
11371
|
if (prop(b, "filterExpr")) throw new Untranslatable2(`the bound column "${prop(b, "name")}", an aggregate with a filter`);
|
|
11354
11372
|
const all = gc.group ?? c.region;
|
|
@@ -12126,6 +12144,7 @@ function special(cp) {
|
|
|
12126
12144
|
if (cp >= 8192 && cp <= 8303) return cp >= 8203 && cp <= 8207 || cp >= 8234 && cp <= 8238 || cp >= 8288;
|
|
12127
12145
|
return cp >= 11904 && cp <= 42191 || cp >= 43056 && cp <= 44031 || cp >= 44032 && cp <= 55215 || cp >= 63744 && cp <= 64255 || cp >= 64285 && cp <= 65023 || cp >= 65024 && cp <= 65039 || cp >= 65072 && cp <= 65103 || cp >= 65136 && cp <= 65278 || cp >= 65280 && cp <= 65519 || cp >= 65536;
|
|
12128
12146
|
}
|
|
12147
|
+
var FORMAT_CHAR = new RegExp("^\\p{Cf}$", "u");
|
|
12129
12148
|
var cjk = (cp) => cp >= 11904 && cp <= 40959 || cp >= 44032 && cp <= 55215 || cp >= 63744 && cp <= 64255 || cp >= 65280 && cp <= 65519 || cp >= 131072 && cp <= 262143;
|
|
12130
12149
|
var NO_START = new Set("、。,.・:;?!ー)」』】〕〉》〗〙〟’”}⦆ぁぃぅぇぉっゃゅょゎゕゖァィゥェォッャュョヮヵヶ々〻‐゠–〜~…‥,.!?:;)]}%ゝゞヽヾ゛゜ㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ。」、・ー%]⦆");
|
|
12131
12150
|
var NO_END = new Set("(「『【〔〈《〖〘〝‘“{⦅([{[「$¥£");
|
|
@@ -12521,7 +12540,7 @@ var TextMeasurer = class {
|
|
|
12521
12540
|
}
|
|
12522
12541
|
/** The font for one character: the chosen one, else the bundled fallback for its script, else the one before. */
|
|
12523
12542
|
pick(cp, key, prev) {
|
|
12524
|
-
if (cp < 32 || this.has(key, cp)) return key;
|
|
12543
|
+
if (cp < 32 || this.has(key, cp) || FORMAT_CHAR.test(String.fromCodePoint(cp))) return key;
|
|
12525
12544
|
const fb = fallbackKey(cp, key);
|
|
12526
12545
|
if (fb && !this.store.failed.has(fb)) {
|
|
12527
12546
|
if (!this.store.has(fb)) {
|
|
@@ -13348,8 +13367,8 @@ function rgbOf(c) {
|
|
|
13348
13367
|
if (h.length === 3) h = h.replace(/./g, (x) => x + x);
|
|
13349
13368
|
return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16) / 255);
|
|
13350
13369
|
}
|
|
13351
|
-
var lum = (
|
|
13352
|
-
const [r, g, b] =
|
|
13370
|
+
var lum = (rgb4) => {
|
|
13371
|
+
const [r, g, b] = rgb4.map((v) => v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
|
|
13353
13372
|
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
13354
13373
|
};
|
|
13355
13374
|
function contrast(a, b) {
|
|
@@ -13377,6 +13396,11 @@ function niceScale(min, max, ticks = 5) {
|
|
|
13377
13396
|
const step3 = niceNum(range / Math.max(1, ticks - 1), true);
|
|
13378
13397
|
return { lo: Math.floor(min / step3) * step3, hi: Math.ceil(max / step3) * step3, step: step3 };
|
|
13379
13398
|
}
|
|
13399
|
+
function niceScaleSpan(min, max, ticks = 5) {
|
|
13400
|
+
if (!Number.isFinite(min) || !Number.isFinite(max) || !(max > min)) return niceScale(min, max, ticks);
|
|
13401
|
+
const step3 = niceNum((max - min) / Math.max(1, ticks - 1), true);
|
|
13402
|
+
return { lo: Math.floor(min / step3) * step3, hi: Math.ceil(max / step3) * step3, step: step3 };
|
|
13403
|
+
}
|
|
13380
13404
|
function niceNum(x, round) {
|
|
13381
13405
|
const e2 = Math.floor(Math.log10(x));
|
|
13382
13406
|
const f4 = x / 10 ** e2;
|
|
@@ -14334,7 +14358,7 @@ var byName = (lc, pal) => (name) => {
|
|
|
14334
14358
|
};
|
|
14335
14359
|
function chartData(item, ctx, lc, pal = paletteOf(item.palette)) {
|
|
14336
14360
|
let rows = item.dataSet ? related(lc.dataSets[item.dataSet] || [], ctx) : ctx.aggRows || [];
|
|
14337
|
-
if (item.dataSet && !lc.dataSets[item.dataSet]) lc.warn(`${item.name}: the data set "${item.dataSet}" does not exist`);
|
|
14361
|
+
if (item.dataSet && !lc.dataSets[item.dataSet]) lc.warn(`${item.name || item.type}: the data set "${item.dataSet}" does not exist`);
|
|
14338
14362
|
if (item.filters?.length) rows = applyFilters(rows, item.filters, ctx);
|
|
14339
14363
|
if (item.sort?.length) rows = applySort(rows, item.sort, ctx);
|
|
14340
14364
|
const who = item.name || "Chart";
|
|
@@ -14622,13 +14646,15 @@ function valueAxis(spec, lo, hi, minPos, { includeZero = true, len = 100, fs: fs
|
|
|
14622
14646
|
lo = lo < 0 ? -1 : 0;
|
|
14623
14647
|
hi = 1;
|
|
14624
14648
|
}
|
|
14649
|
+
let padded = false;
|
|
14625
14650
|
if (pad2 > 0 && hi > lo) {
|
|
14626
14651
|
const d = (hi - lo) * pad2;
|
|
14627
|
-
if (smin == null) lo
|
|
14628
|
-
if (smax == null) hi
|
|
14652
|
+
if (smin == null) lo = lo >= 0 && lo - d < 0 ? 0 : lo - d;
|
|
14653
|
+
if (smax == null) hi = hi <= 0 && hi + d > 0 ? 0 : hi + d;
|
|
14654
|
+
padded = true;
|
|
14629
14655
|
}
|
|
14630
14656
|
const want = len < fs2 * 6 ? 3 : 5;
|
|
14631
|
-
const sc = niceScale(smin ?? lo, smax ?? hi, want);
|
|
14657
|
+
const sc = padded && smin == null && smax == null && (lo >= 0 || hi <= 0) ? niceScaleSpan(lo, hi, want) : niceScale(smin ?? lo, smax ?? hi, want);
|
|
14632
14658
|
let a = sc.lo, b = sc.hi, ticks;
|
|
14633
14659
|
if (smin != null || smax != null) {
|
|
14634
14660
|
a = smin ?? sc.lo;
|
|
@@ -15056,31 +15082,27 @@ function rowPoints(type, g) {
|
|
|
15056
15082
|
rows = rows.slice(0, cap2);
|
|
15057
15083
|
}
|
|
15058
15084
|
const blank2 = (v) => v == null || v === "";
|
|
15059
|
-
const
|
|
15085
|
+
const drawn = /* @__PURE__ */ new Set();
|
|
15060
15086
|
const sets = data.series.map((s, si) => {
|
|
15061
15087
|
const pts2 = [];
|
|
15062
15088
|
rows.forEach((r, ri) => {
|
|
15063
15089
|
c.fields = r;
|
|
15064
15090
|
const rx = safe2(item.xValue, c, lc, who), ry = safe2(s.def.value || "=0", { ...c, aggRows: [r] }, lc, who);
|
|
15065
|
-
if (blank2(rx) || blank2(ry))
|
|
15066
|
-
missing2.add(ri);
|
|
15067
|
-
return;
|
|
15068
|
-
}
|
|
15091
|
+
if (blank2(rx) || blank2(ry)) return;
|
|
15069
15092
|
const x = Number(rx), y = Number(ry);
|
|
15070
|
-
if (!Number.isFinite(x) || !Number.isFinite(y))
|
|
15071
|
-
missing2.add(ri);
|
|
15072
|
-
return;
|
|
15073
|
-
}
|
|
15093
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) return;
|
|
15074
15094
|
let size = 1;
|
|
15075
15095
|
if (type === "bubble") {
|
|
15076
15096
|
size = Number(safe2(s.def.size || "=1", { ...c, aggRows: [r] }, lc, who));
|
|
15077
15097
|
if (!Number.isFinite(size) || size <= 0) return;
|
|
15078
15098
|
}
|
|
15079
15099
|
pts2.push({ x, y, size });
|
|
15100
|
+
drawn.add(ri);
|
|
15080
15101
|
});
|
|
15081
15102
|
return { s, pts: pts2, i: si };
|
|
15082
15103
|
});
|
|
15083
|
-
|
|
15104
|
+
const missing2 = rows.length - drawn.size;
|
|
15105
|
+
if (missing2 > 0) lc.warn(`${who}: ${missing2} of ${rows.length} rows have no x or y value and are not drawn`);
|
|
15084
15106
|
return sets;
|
|
15085
15107
|
}
|
|
15086
15108
|
function paintXY(type, g) {
|
|
@@ -17512,7 +17534,7 @@ function hidden(item, ctx, lc) {
|
|
|
17512
17534
|
const r = evalSafe(item.hidden, ctx, lc, item.name || item.type);
|
|
17513
17535
|
h = !r.err && truthy(r.v);
|
|
17514
17536
|
}
|
|
17515
|
-
return item.name && lc.state?.toggles?.[`item:${item.name}`] ? !h : h;
|
|
17537
|
+
return item.name && lc.state?.toggles?.[`item:${item.name || item.type}`] ? !h : h;
|
|
17516
17538
|
}
|
|
17517
17539
|
var SHRINK_DEFAULTS = { minFontSize: 4, step: 0.5 };
|
|
17518
17540
|
function rotationOf(item) {
|
|
@@ -17848,7 +17870,7 @@ register("table", {
|
|
|
17848
17870
|
else {
|
|
17849
17871
|
rows = item.dataSet && lc.dataSets[item.dataSet] || [];
|
|
17850
17872
|
rows = related(rows, tctx);
|
|
17851
|
-
if (item.dataSet && !lc.dataSets[item.dataSet]) lc.warn(`${item.name ||
|
|
17873
|
+
if (item.dataSet && !lc.dataSets[item.dataSet]) lc.warn(`${item.name || item.type}: the data set "${item.dataSet}" does not exist`);
|
|
17852
17874
|
if (item.filters?.length) rows = applyFilters(rows, item.filters, tctx);
|
|
17853
17875
|
const sort = lc.state?.sort?.[item.name] || item.sort;
|
|
17854
17876
|
if (sort?.length) rows = applySort(rows, sort, tctx);
|
|
@@ -17864,11 +17886,11 @@ register("table", {
|
|
|
17864
17886
|
if (overflow === "shrink" && room > 0) {
|
|
17865
17887
|
const k = room / designedW;
|
|
17866
17888
|
cols = cols.map((c) => ({ ...c, width: (Number(c.width) || 0) * k }));
|
|
17867
|
-
lc.warn(`${item.name ||
|
|
17889
|
+
lc.warn(`${item.name || item.type}: its columns are ${Math.round(designedW)}pt wide, wider than the page (${Math.round(room)}pt), so they are narrowed to fit`);
|
|
17868
17890
|
} else if (overflow === "clip" || overflow === "paginate" && lc.fixed) {
|
|
17869
|
-
lc.warn(`${item.name ||
|
|
17891
|
+
lc.warn(`${item.name || item.type}: its columns are ${Math.round(designedW)}pt wide, wider than the page (${Math.round(room)}pt), so the columns past the page edge are cut`, true);
|
|
17870
17892
|
} else if (overflow === "paginate" && item.overflow !== "paginate") {
|
|
17871
|
-
lc.warn(`${item.name ||
|
|
17893
|
+
lc.warn(`${item.name || item.type}: its columns are ${Math.round(designedW)}pt wide, wider than the page (${Math.round(room)}pt), so they continue on the next pages`);
|
|
17872
17894
|
}
|
|
17873
17895
|
const colX = [];
|
|
17874
17896
|
let acc = item.x;
|
|
@@ -17878,13 +17900,14 @@ register("table", {
|
|
|
17878
17900
|
}
|
|
17879
17901
|
const width = acc - item.x;
|
|
17880
17902
|
const region = { name: item.name, columns: cols.map((c) => c.width), rows: [] };
|
|
17903
|
+
if (lc.tablesSeen) lc.tablesSeen.n++;
|
|
17881
17904
|
const tableScope = { rows, index: -1, run: [] };
|
|
17882
17905
|
const scopes = { ...tctx.scopes || {}, [item.name]: tableScope };
|
|
17883
17906
|
const groupChains = {};
|
|
17884
17907
|
(item.groups || []).forEach((g, i) => {
|
|
17885
17908
|
if (g.name) groupChains[g.name] = { rows, keys: item.groups.slice(0, i + 1).map((x) => x.expr) };
|
|
17886
17909
|
});
|
|
17887
|
-
const base = { ...tctx, aggRows: rows, aggIndex: void 0, fields: rows[0] || null, scopes, region: tableScope, group: void 0, groupChains: { ...tctx.groupChains || {}, ...groupChains } };
|
|
17910
|
+
const base = { ...tctx, aggRows: rows, aggIndex: void 0, fields: lc.win?.first || rows[0] || null, scopes, region: tableScope, group: void 0, groupChains: { ...tctx.groupChains || {}, ...groupChains } };
|
|
17888
17911
|
const units = [];
|
|
17889
17912
|
let y = 0;
|
|
17890
17913
|
let repeatH = 0;
|
|
@@ -17901,7 +17924,7 @@ register("table", {
|
|
|
17901
17924
|
const covered = (ci) => cover[ci] !== null;
|
|
17902
17925
|
const cellsAt = /* @__PURE__ */ new WeakMap();
|
|
17903
17926
|
const layRow = (row, ctx, kind, extra) => {
|
|
17904
|
-
if (row.hidden != null && row.hidden !== false && row.hidden !== "" && hidden({ hidden: row.hidden, name: `${item.name ||
|
|
17927
|
+
if (row.hidden != null && row.hidden !== false && row.hidden !== "" && hidden({ hidden: row.hidden, name: `${item.name || item.type} row` }, ctx, lc)) {
|
|
17905
17928
|
if (openSpans.length) {
|
|
17906
17929
|
for (const s of openSpans) s.left--;
|
|
17907
17930
|
for (const s of openSpans) if (s.left <= 0) closeSpan(s);
|
|
@@ -17935,7 +17958,7 @@ register("table", {
|
|
|
17935
17958
|
else try {
|
|
17936
17959
|
v = evalValue(cell.value ?? "", cctx);
|
|
17937
17960
|
} catch (e2) {
|
|
17938
|
-
lc.warn(`${item.name ||
|
|
17961
|
+
lc.warn(`${item.name || item.type} cell: ${e2.message}`);
|
|
17939
17962
|
v = "#Error";
|
|
17940
17963
|
}
|
|
17941
17964
|
let text2 = textOf(v, st, cctx, lc);
|
|
@@ -17978,7 +18001,7 @@ register("table", {
|
|
|
17978
18001
|
cells.forEach((c, k) => {
|
|
17979
18002
|
if (c.cell.visual?.type) {
|
|
17980
18003
|
items.push(...paintBox({ x: c.x, y: 0, w: c.w, h, st: c.st, tl: null, m: lc.m }));
|
|
17981
|
-
if (first) items.push(...paintVisual(c.cell.visual, { x: c.x, y: 0, w: c.w, h }, c.ctx, lc, c.st, `${item.name} cell`, { cell: true }));
|
|
18004
|
+
if (first) items.push(...paintVisual(c.cell.visual, { x: c.x, y: 0, w: c.w, h }, c.ctx, lc, c.st, `${item.name || item.type} cell`, { cell: true }));
|
|
17982
18005
|
return;
|
|
17983
18006
|
}
|
|
17984
18007
|
if (c.nested) {
|
|
@@ -18033,7 +18056,7 @@ register("table", {
|
|
|
18033
18056
|
};
|
|
18034
18057
|
const layoutInCell = (inner2, x, cw, st, cctx, row) => {
|
|
18035
18058
|
const pd = padding(st);
|
|
18036
|
-
const it = { ...inner2, name: inner2.name || `${item.name}_cell`, x: x + pd[3], y: 0, w: Math.max(1, cw - pd[1] - pd[3]), h: Number(inner2.h) || Math.max(1, (row.height || 18) - pd[0] - pd[2]) };
|
|
18059
|
+
const it = { ...inner2, name: inner2.name || `${item.name || item.type}_cell`, x: x + pd[3], y: 0, w: Math.max(1, cw - pd[1] - pd[3]), h: Number(inner2.h) || Math.max(1, (row.height || 18) - pd[0] - pd[2]) };
|
|
18037
18060
|
const scopeRows2 = cctx.aggIndex != null ? [cctx.fields] : cctx.aggRows || [];
|
|
18038
18061
|
const current = item.dataSet ? { ...cctx.current || {}, [item.dataSet]: scopeRows2 } : cctx.current;
|
|
18039
18062
|
const child = {
|
|
@@ -18053,7 +18076,7 @@ register("table", {
|
|
|
18053
18076
|
const reads = (it.dataSet && it.dataSet !== item.dataSet ? child.ctxFor(it).aggRows?.length : scopeRows2.length) || 1;
|
|
18054
18077
|
if (budget.left < reads) {
|
|
18055
18078
|
budget.left = 0;
|
|
18056
|
-
lc.warn(`${item.name}: more than ${CELL_ITEM_UNITS} rows of items inside cells; the rest are left empty`);
|
|
18079
|
+
lc.warn(`${item.name || item.type}: more than ${CELL_ITEM_UNITS} rows of items inside cells; the rest are left empty`);
|
|
18057
18080
|
return { items: [], height: 0 };
|
|
18058
18081
|
}
|
|
18059
18082
|
budget.left -= reads;
|
|
@@ -18097,7 +18120,7 @@ register("table", {
|
|
|
18097
18120
|
u.items.splice(at2 < 0 ? u.items.length : at2, 0, ...add2);
|
|
18098
18121
|
});
|
|
18099
18122
|
if (s.tl.needed > s.units[0].height + GROW_TOLERANCE || s.st.verticalAlign && s.st.verticalAlign !== "top") {
|
|
18100
|
-
const id = `${item.name}:span:${lc.nextId()}`;
|
|
18123
|
+
const id = `${item.name || item.type}:span:${lc.nextId()}`;
|
|
18101
18124
|
for (const u of s.units) u.block ||= id;
|
|
18102
18125
|
} else {
|
|
18103
18126
|
let above = s.units[0].height;
|
|
@@ -18122,7 +18145,8 @@ register("table", {
|
|
|
18122
18145
|
openSpans = [];
|
|
18123
18146
|
};
|
|
18124
18147
|
const fl = base.bandRows === "first-last";
|
|
18125
|
-
const
|
|
18148
|
+
const first0 = lc.win?.first || rows[0];
|
|
18149
|
+
const headerUnits = (item.header || []).map((r) => layRow(r, fl && rows.length ? { ...base, pendingRows: [first0] } : base, "header")).filter(Boolean);
|
|
18126
18150
|
endBand();
|
|
18127
18151
|
const headerHeight = headerUnits.reduce((s, u) => s + u.height, 0);
|
|
18128
18152
|
if (item.repeatHeader !== false) repeatH = headerHeight;
|
|
@@ -18136,9 +18160,9 @@ register("table", {
|
|
|
18136
18160
|
y += tl.needed;
|
|
18137
18161
|
}
|
|
18138
18162
|
const groups = item.groups || [];
|
|
18139
|
-
let rowNo = 0;
|
|
18163
|
+
let rowNo = lc.win?.rowOffset || 0;
|
|
18140
18164
|
const groupTables = [];
|
|
18141
|
-
const tableKey = `${item.name}#${lc.nextId()}`;
|
|
18165
|
+
const tableKey = `${item.name || item.type}#${lc.nextId()}`;
|
|
18142
18166
|
const emit2 = (level, grows, ctx, chain, keyPath) => {
|
|
18143
18167
|
if (level === groups.length) {
|
|
18144
18168
|
for (let i = 0; i < grows.length; i++) {
|
|
@@ -18156,9 +18180,16 @@ register("table", {
|
|
|
18156
18180
|
const dctx = { ...ctx, fields: grows[i], aggRows: grows, aggIndex: i, rowNumber: rowNo };
|
|
18157
18181
|
const u0 = units.length;
|
|
18158
18182
|
for (const r of item.detail || []) layRow(r, dctx, "detail", { level: groups.length });
|
|
18159
|
-
if (
|
|
18183
|
+
if (lc.win && units[u0]) {
|
|
18184
|
+
units[u0].rowHead = true;
|
|
18185
|
+
for (let k = u0; k < units.length; k++) units[k].dataRow = rowNo;
|
|
18186
|
+
}
|
|
18187
|
+
if (groups.length && item.widowControl !== false) for (let k = u0; k < units.length; k++) {
|
|
18188
|
+
units[k].grp = tableKey + keyPath;
|
|
18189
|
+
if (ctx.__before) units[k].grpBefore = ctx.__before;
|
|
18190
|
+
}
|
|
18160
18191
|
const every = Math.trunc(Number(item.pageBreakEvery)) || 0;
|
|
18161
|
-
if (every > 0 && rowNo > 1 && (rowNo - 1) % every === 0 && units[u0]) units[u0].breakBefore = true;
|
|
18192
|
+
if (every > 0 && rowNo > (lc.win?.rowOffset || 0) + 1 && (rowNo - 1) % every === 0 && units[u0]) units[u0].breakBefore = true;
|
|
18162
18193
|
endBand();
|
|
18163
18194
|
}
|
|
18164
18195
|
return;
|
|
@@ -18193,7 +18224,7 @@ register("table", {
|
|
|
18193
18224
|
kids = /* @__PURE__ */ new Map();
|
|
18194
18225
|
roots = [];
|
|
18195
18226
|
for (const b of buckets) {
|
|
18196
|
-
const pk = evalSafe(g.parent, { ...ctx, fields: b.rows[0], aggRows: b.rows, aggIndex: void 0 }, lc, `${item.name} group parent`).v;
|
|
18227
|
+
const pk = evalSafe(g.parent, { ...ctx, fields: b.rows[0], aggRows: b.rows, aggIndex: void 0 }, lc, `${item.name || item.type} group parent`).v;
|
|
18197
18228
|
const pr = pk == null || pk === "" ? null : byText.get(pk instanceof Date ? String(pk.getTime()) : String(pk));
|
|
18198
18229
|
if (!pr || pr === b) roots.push(b);
|
|
18199
18230
|
else {
|
|
@@ -18218,20 +18249,26 @@ register("table", {
|
|
|
18218
18249
|
if (lc.rowBudget?.cut || shown2.has(bk)) return;
|
|
18219
18250
|
shown2.add(bk);
|
|
18220
18251
|
const sc = { rows: bk.rows, index: -1, run: [], number: bi + 1, prevRows: bi > 0 ? sibs[bi - 1].rows : null, siblings: sibRows(sibs), ...kids ? { level: depth, recRows: recOf.get(bk) } : {} };
|
|
18221
|
-
const
|
|
18252
|
+
const cont = bi === 0 && (level === 0 || ctx.__cont) ? lc.win?.cont?.[level] : null;
|
|
18253
|
+
const gctx = { ...ctx, fields: cont ? cont.first : bk.rows[0], aggRows: bk.rows, aggIndex: void 0, scopes: { ...ctx.scopes, [gname]: sc }, groupKey: bk.key, group: sc, __cont: !!cont, __before: cont && level === groups.length - 1 ? cont.before : 0 };
|
|
18222
18254
|
if (kids) {
|
|
18223
18255
|
gctx.level = depth;
|
|
18224
18256
|
if (g.indent) gctx.indent = (ctx.indent || 0) + depth * Number(g.indent);
|
|
18225
18257
|
}
|
|
18226
18258
|
const path2 = `${parentPath}/${bk.text}`;
|
|
18227
|
-
const tkey = `${item.name}|${level}|${path2}`;
|
|
18259
|
+
const tkey = `${item.name || item.type}|${level}|${path2}`;
|
|
18228
18260
|
const dflt = kids && g.expandLevels != null ? depth < Number(g.expandLevels) : !g.initiallyCollapsed;
|
|
18229
18261
|
const open = !g.collapsible ? true : lc.state?.toggles?.[tkey] ?? dflt;
|
|
18230
18262
|
const start = units.length;
|
|
18231
|
-
const hctx = g.header?.length ? { ...gctx, pendingRows: fl ? [bk.rows[0]] : recOf.get(bk) || bk.rows } : gctx;
|
|
18232
|
-
const hu = (g.header || []).map((r, ri) => layRow(r, hctx, "groupHeader", { level, ...ri === 0 && g.collapsible ? { toggle: { key: tkey, open } } : {} })).filter(Boolean);
|
|
18263
|
+
const hctx = g.header?.length ? { ...gctx, pendingRows: fl ? [cont ? cont.first : bk.rows[0]] : recOf.get(bk) || bk.rows } : gctx;
|
|
18264
|
+
const hu = (cont && !g.repeatHeader ? [] : g.header || []).map((r, ri) => layRow(r, hctx, "groupHeader", { level, ...ri === 0 && g.collapsible ? { toggle: { key: tkey, open } } : {} })).filter(Boolean);
|
|
18233
18265
|
endBand();
|
|
18234
18266
|
const before = units.length;
|
|
18267
|
+
if (lc.win && !cont && before > start) {
|
|
18268
|
+
for (let k = start; k < before; k++) units[k].dataRow = rowNo + 1;
|
|
18269
|
+
units[start].rowHead = true;
|
|
18270
|
+
units[start].headLevel = level;
|
|
18271
|
+
}
|
|
18235
18272
|
const rep = g.repeatHeader && before > start && !lc.fixed ? [...ctx.__rep || [], (() => {
|
|
18236
18273
|
const hdr = units.slice(start, before), h0 = hdr[0].top, its = [];
|
|
18237
18274
|
for (const u of hdr) for (const it of shiftLocal(u.items.filter((i) => i.t !== "link" && i.t !== "bookmark"), u.top - h0)) its.push(it);
|
|
@@ -18241,7 +18278,7 @@ register("table", {
|
|
|
18241
18278
|
const ch = kids?.get(bk) || [];
|
|
18242
18279
|
if (open) {
|
|
18243
18280
|
emit2(level + 1, bk.rows, gctx, [...chain, sc], path2);
|
|
18244
|
-
if (ch.length && depth + 1 >= MAX_TREE_DEPTH) lc.warn(`${item.name}: the group "${gname}" is more than ${MAX_TREE_DEPTH} levels deep; deeper rows are listed at the top level`);
|
|
18281
|
+
if (ch.length && depth + 1 >= MAX_TREE_DEPTH) lc.warn(`${item.name || item.type}: the group "${gname}" is more than ${MAX_TREE_DEPTH} levels deep; deeper rows are listed at the top level`);
|
|
18245
18282
|
else ch.forEach((c, ci) => node2(c, ci, ch, depth + 1, path2));
|
|
18246
18283
|
} else {
|
|
18247
18284
|
const rs = recOf.get(bk) || bk.rows;
|
|
@@ -18270,8 +18307,11 @@ register("table", {
|
|
|
18270
18307
|
if (g.newSection) units[start].sectionStart = true;
|
|
18271
18308
|
if (g.pageBreak === "after" && bi < sibs.length - 1) units[units.length - 1].breakAfter = true;
|
|
18272
18309
|
if (g.keepTogether) {
|
|
18273
|
-
const id = `${item.name}:g${level}:${path2}:${lc.nextId()}`;
|
|
18274
|
-
for (let k = start; k < units.length; k++) units[k].block
|
|
18310
|
+
const id = `${item.name || item.type}:g${level}:${path2}:${lc.nextId()}`;
|
|
18311
|
+
for (let k = start; k < units.length; k++) if (!units[k].block) {
|
|
18312
|
+
units[k].block = id;
|
|
18313
|
+
if (cont) units[k].blockOpen = true;
|
|
18314
|
+
}
|
|
18275
18315
|
}
|
|
18276
18316
|
}
|
|
18277
18317
|
};
|
|
@@ -18288,7 +18328,7 @@ register("table", {
|
|
|
18288
18328
|
if (kids) {
|
|
18289
18329
|
const rest2 = buckets.filter((b) => !shown2.has(b));
|
|
18290
18330
|
if (rest2.length) {
|
|
18291
|
-
lc.warn(`${item.name}: ${rest2.length} rows of the group "${gname}" have no root (a cycle or too deep); they are listed at the top level`);
|
|
18331
|
+
lc.warn(`${item.name || item.type}: ${rest2.length} rows of the group "${gname}" have no root (a cycle or too deep); they are listed at the top level`);
|
|
18292
18332
|
rest2.forEach((bk, bi) => node2(bk, bi, rest2, 0, keyPath));
|
|
18293
18333
|
}
|
|
18294
18334
|
}
|
|
@@ -18316,7 +18356,7 @@ register("table", {
|
|
|
18316
18356
|
units[units.length - 1].breakAfter = true;
|
|
18317
18357
|
}
|
|
18318
18358
|
if (item.bookmark && units.length) {
|
|
18319
|
-
const b = evalSafe(item.bookmark, base, lc, `${item.name ||
|
|
18359
|
+
const b = evalSafe(item.bookmark, base, lc, `${item.name || item.type} bookmark`).v;
|
|
18320
18360
|
if (b != null && b !== "" && b !== "#Error") units[0].items.unshift({ t: "bookmark", label: String(b), x: item.x, y: 0, level: item.bookmarkLevel ?? 0 });
|
|
18321
18361
|
}
|
|
18322
18362
|
if (!lc.fixed) lc.regions?.push(region);
|
|
@@ -18411,7 +18451,7 @@ register("container", {
|
|
|
18411
18451
|
const ctx = lc.ctxFor(item);
|
|
18412
18452
|
if (hidden(item, ctx, lc)) return { height: 0, units: [] };
|
|
18413
18453
|
const res = lc.layoutItems(item.items, lc, { dx: item.x });
|
|
18414
|
-
return frame2(item, lc, ctx, res, item.keepTogether !== false ? `c:${item.name}:${lc.nextId()}` : null);
|
|
18454
|
+
return frame2(item, lc, ctx, res, item.keepTogether !== false ? `c:${item.name || item.type}:${lc.nextId()}` : null);
|
|
18415
18455
|
}
|
|
18416
18456
|
});
|
|
18417
18457
|
function frame2(item, lc, ctx, res, blockId0) {
|
|
@@ -18468,7 +18508,7 @@ register("list", {
|
|
|
18468
18508
|
let rows = item.dataSet && lc.dataSets[item.dataSet] || [];
|
|
18469
18509
|
if (item.inheritRows && item.dataSet && ctx.current?.[item.dataSet]) rows = ctx.current[item.dataSet];
|
|
18470
18510
|
else rows = related(rows, ctx);
|
|
18471
|
-
if (item.dataSet && !lc.dataSets[item.dataSet]) lc.warn(`${item.name}: the data set "${item.dataSet}" does not exist`);
|
|
18511
|
+
if (item.dataSet && !lc.dataSets[item.dataSet]) lc.warn(`${item.name || item.type}: the data set "${item.dataSet}" does not exist`);
|
|
18472
18512
|
if (item.filters?.length) rows = applyFilters(rows, item.filters, ctx);
|
|
18473
18513
|
if (item.sort?.length) rows = applySort(rows, item.sort, ctx);
|
|
18474
18514
|
const reps = item.groupBy ? groupRows(rows, item.groupBy, ctx, lc, item.name, item.groupAdjacent === true).map((b) => b.rows) : rows.map((r) => [r]);
|
|
@@ -18497,7 +18537,7 @@ register("list", {
|
|
|
18497
18537
|
} };
|
|
18498
18538
|
const k = i % ncol;
|
|
18499
18539
|
const res = lc.layoutItems(item.items, child, { dx: item.x + k * (item.w + gap) });
|
|
18500
|
-
const fr = frame2({ ...item, x: item.x + k * (item.w + gap), name: `${item.name}[${i + 1}]` }, child, rctx, res, item.keepTogether !== false ? `l:${item.name}:${i}:${lc.nextId()}` : null);
|
|
18540
|
+
const fr = frame2({ ...item, x: item.x + k * (item.w + gap), name: `${item.name || item.type}[${i + 1}]` }, child, rctx, res, item.keepTogether !== false ? `l:${item.name || item.type}:${i}:${lc.nextId()}` : null);
|
|
18501
18541
|
if (ncol > 1) {
|
|
18502
18542
|
if (k === 0) {
|
|
18503
18543
|
cells = { top: y, height: 0, items: [], x0: item.x, x1: item.x + ncol * item.w + (ncol - 1) * gap, block: void 0 };
|
|
@@ -18968,7 +19008,7 @@ register("subreport", {
|
|
|
18968
19008
|
if (hidden(item, ctx, lc)) return { height: 0, units: [] };
|
|
18969
19009
|
const params = {};
|
|
18970
19010
|
for (const [k, v] of Object.entries(item.params || {})) {
|
|
18971
|
-
const r = evalSafe(v, ctx, lc, `${item.name} parameter ${k}`);
|
|
19011
|
+
const r = evalSafe(v, ctx, lc, `${item.name || item.type} parameter ${k}`);
|
|
18972
19012
|
params[k] = r.v instanceof Date ? isoDate(r.v, ctx.timeZone) : r.v;
|
|
18973
19013
|
}
|
|
18974
19014
|
const key = `${item.report}|${JSON.stringify(params)}`;
|
|
@@ -18987,10 +19027,10 @@ register("subreport", {
|
|
|
18987
19027
|
const res = sub.results.get(key);
|
|
18988
19028
|
if (!res) return placeholder(`Subreport "${item.report}" did not load`);
|
|
18989
19029
|
if (res.error) {
|
|
18990
|
-
lc.warn(`${item.name}: ${res.error}`);
|
|
19030
|
+
lc.warn(`${item.name || item.type}: ${res.error}`);
|
|
18991
19031
|
return placeholder(`Subreport "${item.report}": ${res.error}`);
|
|
18992
19032
|
}
|
|
18993
|
-
const block = item.keepTogether ? `s:${item.name}:${lc.nextId()}` : void 0;
|
|
19033
|
+
const block = item.keepTogether ? `s:${item.name || item.type}:${lc.nextId()}` : void 0;
|
|
18994
19034
|
const units = res.units.map((u) => ({ ...u, items: shiftItems(u.items, item.x, 0), ...u.cont ? { cont: shiftItems(u.cont, item.x, 0) } : {}, x0: (u.x0 ?? 0) + item.x, x1: (u.x1 ?? item.w) + item.x, block: u.block || block, tableId: void 0 }));
|
|
18995
19035
|
const tables = res.tables.map((t) => ({ ...t, x0: t.x0 + item.x, x1: t.x1 + item.x, headerItems: shiftItems(t.headerItems, item.x, 0), id: `sub${lc.nextId()}` }));
|
|
18996
19036
|
for (const r of res.regions || []) lc.regions?.push(r);
|
|
@@ -19161,7 +19201,8 @@ function paginate(units, tables, pageH, warn, stats) {
|
|
|
19161
19201
|
if (b) {
|
|
19162
19202
|
b.top = Math.min(b.top, u.top);
|
|
19163
19203
|
b.bottom = Math.max(b.bottom, u.top + u.height);
|
|
19164
|
-
|
|
19204
|
+
if (u.blockOpen) b.open = true;
|
|
19205
|
+
} else blockMap.set(u.block, { top: u.top, bottom: u.top + u.height, open: !!u.blockOpen });
|
|
19165
19206
|
}
|
|
19166
19207
|
const blockUnits = /* @__PURE__ */ new Map();
|
|
19167
19208
|
for (const u of units) if (u.block) {
|
|
@@ -19169,18 +19210,18 @@ function paginate(units, tables, pageH, warn, stats) {
|
|
|
19169
19210
|
if (!l) blockUnits.set(u.block, l = []);
|
|
19170
19211
|
l.push(u);
|
|
19171
19212
|
}
|
|
19172
|
-
const blocks = [...blockMap.values()].filter((b) => b.bottom - b.top <= pageH + EPS2);
|
|
19213
|
+
const blocks = [...blockMap.values()].filter((b) => !b.open && b.bottom - b.top <= pageH + EPS2);
|
|
19173
19214
|
for (const b of blocks) cand.push(b.top, b.bottom);
|
|
19174
19215
|
cand.sort((a, b) => a - b);
|
|
19175
19216
|
const grpRows = /* @__PURE__ */ new Map();
|
|
19176
19217
|
for (const u of units) if (u.grp) {
|
|
19177
19218
|
let g = grpRows.get(u.grp);
|
|
19178
|
-
if (!g) grpRows.set(u.grp, g = { tops: /* @__PURE__ */ new Set(), first: u.top, last: 0, block: u.block || null });
|
|
19219
|
+
if (!g) grpRows.set(u.grp, g = { tops: /* @__PURE__ */ new Set(), first: u.top, last: 0, block: u.block || null, before: u.grpBefore || 0 });
|
|
19179
19220
|
g.tops.add(u.top);
|
|
19180
19221
|
g.last = Math.max(g.last, u.top + u.height);
|
|
19181
19222
|
if (g.block !== (u.block || null)) g.block = void 0;
|
|
19182
19223
|
}
|
|
19183
|
-
const widowGroups = [...grpRows.values()].map((g) => ({ first: g.first, last: g.last, tops: [...g.tops].sort((a, b) => a - b), block: g.block })).filter((g) => g.
|
|
19224
|
+
const widowGroups = [...grpRows.values()].map((g) => ({ first: g.first, last: g.last, tops: [...g.tops].sort((a, b) => a - b), block: g.block, before: g.before, n: g.tops.size + g.before })).filter((g) => g.n >= 4 || !g.before && g.n >= 2 && g.last - g.first <= pageH + EPS2).sort((a, b) => a.first - b.first);
|
|
19184
19225
|
const wFirst = widowGroups.map((g) => g.first);
|
|
19185
19226
|
const wMaxLast = [];
|
|
19186
19227
|
widowGroups.forEach((g, i) => wMaxLast.push(Math.max(i ? wMaxLast[i - 1] : -Infinity, g.last)));
|
|
@@ -19207,9 +19248,9 @@ function paginate(units, tables, pageH, warn, stats) {
|
|
|
19207
19248
|
tick(1);
|
|
19208
19249
|
const g = widowGroups[i];
|
|
19209
19250
|
if (g.last <= y + EPS2 || g.block && !withBlocks) continue;
|
|
19210
|
-
if (g.
|
|
19211
|
-
const above = rowsAbove(g.tops, y);
|
|
19212
|
-
if (above < 2 || g.
|
|
19251
|
+
if (g.n < 4) return false;
|
|
19252
|
+
const above = g.before + rowsAbove(g.tops, y);
|
|
19253
|
+
if (above < 2 || g.n - above < 2) return false;
|
|
19213
19254
|
}
|
|
19214
19255
|
return true;
|
|
19215
19256
|
};
|
|
@@ -19264,7 +19305,7 @@ function paginate(units, tables, pageH, warn, stats) {
|
|
|
19264
19305
|
if (u.block) {
|
|
19265
19306
|
const bl = blockMap.get(u.block);
|
|
19266
19307
|
if (movedBlocks.has(bl)) continue;
|
|
19267
|
-
if (!bl || bl.bottom - bl.top > room + EPS2 || bl.top <= top2 + EPS2) return null;
|
|
19308
|
+
if (!bl || bl.open || bl.bottom - bl.top > room + EPS2 || bl.top <= top2 + EPS2) return null;
|
|
19268
19309
|
movedBlocks.add(bl);
|
|
19269
19310
|
for (const m of blockUnits.get(u.block)) if (!placed.has(m)) moved.push(m);
|
|
19270
19311
|
continue;
|
|
@@ -22009,6 +22050,7 @@ var SCHEMA_ALIAS = "reportwright/report@1";
|
|
|
22009
22050
|
var ITEM_KEYS = new Set("id type name x y w h style styleName items hidden layer locked label alt value dataSet canGrow canShrink action bookmark tooltip keepTogether pageBreakBefore pageBreakAfter pageBreakBetween newSection filters sort groups groupBy groupAdjacent inheritRows columns header detail footer repeatHeader widowControl noRowsText pageBreakEvery cells rows rowGroup rowGroups columnGro\
|
|
22010
22051
|
up columnGroups values value valueFormat rowSort columnSort rowTotals columnTotals cellStyle headerStyle totalStyle corner partProps library part properties overflow overflowTo src fit headingLevel rotate shrinkToFit minFontSize shrinkStep tocDots tocLink tocPage format chartType series seriesGroup category title legend palette stacked valueAxis xTitle maxCategories outliers categorySort categoryF\
|
|
22011
22052
|
ormat showValues labelPosition symbology quietZone report params text toggle initiallyCollapsed collapsible expandLevels repeatColumns columnGap rowHeaderWidth anim animation visual comment notes description".split(" "));
|
|
22053
|
+
var NO_SERIES_CHARTS = /* @__PURE__ */ new Set(["gantt"]);
|
|
22012
22054
|
function looksLikeLink(it) {
|
|
22013
22055
|
if (it.type !== "textbox" || it.action && it.action.type && it.action.type !== "none") return false;
|
|
22014
22056
|
const st = it.style && typeof it.style === "object" ? it.style : {};
|
|
@@ -22137,6 +22179,9 @@ function validate(def) {
|
|
|
22137
22179
|
if (p?.hidden && p.required && (p.default == null || p.default === "") && !p.nullable) {
|
|
22138
22180
|
warnings.push(`Parameter "${p.name}" is hidden and required but has no default: only a URL, the API or a drill-through can set it`);
|
|
22139
22181
|
}
|
|
22182
|
+
if (p?.required && p.nullable && !p.multi && (p.default == null || p.default === "")) {
|
|
22183
|
+
warnings.push(`Parameter "${p.name}" is required and nullable with no default: when no value is given it is null and the report can draw blank; give it a default, or drop "nullable" to require a value`);
|
|
22184
|
+
}
|
|
22140
22185
|
if (p?.type === "date" && typeof p.default === "string" && p.default.trim() && !p.default.startsWith("=") && !toDate(p.default)) {
|
|
22141
22186
|
warnings.push(`Parameter "${p.name}": its default "${p.default}" is not a date; write it as 2026-12-31 (year-month-day)`);
|
|
22142
22187
|
}
|
|
@@ -22217,7 +22262,7 @@ function validate(def) {
|
|
|
22217
22262
|
warnings.push(`${label}: there is no named style "${it.styleName}"${g ? ` (did you mean "${g}"?)` : ""}; it is ignored`);
|
|
22218
22263
|
}
|
|
22219
22264
|
if (Array.isArray(it.sort)) sortIssues(it.sort, label, warnings);
|
|
22220
|
-
if (it.type === "chart" && Array.isArray(it.series) &&
|
|
22265
|
+
if (it.type === "chart" && !NO_SERIES_CHARTS.has(it.chartType) && !(Array.isArray(it.series) && it.series.length)) warnings.push(`${label}: the chart has no series, so it plots a count of its rows; add one, e.g. series: [{ "name": "Value", "value": "=Sum(Fields.Amount)" }]`);
|
|
22221
22266
|
if (it.type === "image" && typeof it.src === "string" && !it.src.startsWith("=") && LOCAL_IMAGE.test(it.src.trim())) warnings.push(`${label}: "${it.src}" is a local file path, which a browser cannot load; embed the image (images: { name: "data:image/png;base64,..." } and src: "embedded:name") or use an https:// address`);
|
|
22222
22267
|
if (it.style != null && (typeof it.style !== "object" || Array.isArray(it.style))) warnings.push(`${label}: "style" must be an object of style properties, such as { "fontWeight": "bold" }; ${JSON.stringify(it.style).slice(0, 40)} is ignored`);
|
|
22223
22268
|
const own = ownKeys(it.type);
|
|
@@ -22260,6 +22305,9 @@ function validate(def) {
|
|
|
22260
22305
|
const n5 = Array.isArray(it.columns) ? it.columns.length : 0;
|
|
22261
22306
|
const rowsOf = [["header", it.header], ["detail", it.detail], ["footer", it.footer], ...(it.groups || []).flatMap((g, gi) => [[`group ${gi + 1} header`, g?.header], [`group ${gi + 1} footer`, g?.footer]])];
|
|
22262
22307
|
for (const [part2, rows] of rowsOf) (Array.isArray(rows) ? rows : []).forEach((row, ri) => {
|
|
22308
|
+
const cells = Array.isArray(row?.cells) ? row.cells : [];
|
|
22309
|
+
const placed = cells.length < n5 && cells.some((c) => Number(c?.colSpan) > 1) ? cells.reduce((s, c) => s + Math.max(1, Math.floor(Number(c?.colSpan)) || 1), 0) : cells.length;
|
|
22310
|
+
if (placed < n5) warnings.push(`${label} ${part2} row ${ri + 1}: the row has ${placed} of ${n5} cells and no colSpan covers the other ${n5 - placed}; add the cells or a colSpan`);
|
|
22263
22311
|
for (const [k, j] of rowCells(row?.cells, n5).covered) warnings.push(`${label} ${part2} row ${ri + 1}: cell ${k} is covered by colSpan of cell ${j}, so it is not drawn (leave it null, or omit the spanned cells: a row with fewer cells than columns places each cell after the previous one's span)`);
|
|
22264
22312
|
});
|
|
22265
22313
|
}
|
|
@@ -22675,7 +22723,7 @@ function* textsOf(def, dataSets) {
|
|
|
22675
22723
|
}
|
|
22676
22724
|
}
|
|
22677
22725
|
}
|
|
22678
|
-
var NO_CJK_FONTS = "Text in Japanese/Chinese/Korean needs the optional CJK fonts: npm run fonts:cjk";
|
|
22726
|
+
var NO_CJK_FONTS = "Text in Japanese/Chinese/Korean needs the optional CJK fonts: npm i @reportwright/fonts-cjk, then npx reportwright-fonts-cjk (npm); in the app, npm run fonts:cjk";
|
|
22679
22727
|
async function render(def0, opts = {}) {
|
|
22680
22728
|
const t0 = Date.now();
|
|
22681
22729
|
const reuseWarnings = [];
|
|
@@ -22746,6 +22794,7 @@ async function render(def0, opts = {}) {
|
|
|
22746
22794
|
const base = { ...BASE_STYLE, ...def.styles?.base || {} };
|
|
22747
22795
|
let idSeq = 0;
|
|
22748
22796
|
const regions = [];
|
|
22797
|
+
const tablesSeen = { n: 0 };
|
|
22749
22798
|
const imageBudget = opts.imageBudget || { seen: /* @__PURE__ */ new Set(), bytes: 0 };
|
|
22750
22799
|
const makeLc = (globals, fixed2) => {
|
|
22751
22800
|
const lc = {
|
|
@@ -22756,6 +22805,7 @@ async function render(def0, opts = {}) {
|
|
|
22756
22805
|
fixed: fixed2,
|
|
22757
22806
|
maxUnitHeight: contentH,
|
|
22758
22807
|
state: opts.state || {},
|
|
22808
|
+
tablesSeen,
|
|
22759
22809
|
regions: opts.exportData || opts.dataOnly ? regions : null,
|
|
22760
22810
|
dataOnly: !!opts.dataOnly,
|
|
22761
22811
|
// exportData: true: table data and cell tags (Excel, CSV, Word, HTML, accessible PDF)
|
|
@@ -22775,14 +22825,16 @@ async function render(def0, opts = {}) {
|
|
|
22775
22825
|
ctxFor: (item) => {
|
|
22776
22826
|
const ds = item.dataSet || defaultDs;
|
|
22777
22827
|
const rows = ds && dataSets[ds] || [];
|
|
22778
|
-
return { ...baseCtx, globals, fields: rows[0] || null, aggRows: rows };
|
|
22828
|
+
return { ...baseCtx, globals, fields: (opts.pageWindow?.first && ds === defaultDs ? opts.pageWindow.first : rows[0]) || null, aggRows: rows };
|
|
22779
22829
|
},
|
|
22780
22830
|
subreports: null,
|
|
22781
22831
|
bodyWidth: opts.bodyWidth ?? page.bodyWidth,
|
|
22782
22832
|
images: def.images || {},
|
|
22783
22833
|
imageBudget,
|
|
22784
|
-
cellItems: { left: 1e5 }
|
|
22834
|
+
cellItems: { left: 1e5 },
|
|
22785
22835
|
// rows of items inside table cells, for the whole render (items/index.js)
|
|
22836
|
+
win: opts.pageWindow || null
|
|
22837
|
+
// paged.js: units carry their row number (dataRow, rowHead), rows and groups continue
|
|
22786
22838
|
};
|
|
22787
22839
|
return lc;
|
|
22788
22840
|
};
|
|
@@ -22871,8 +22923,8 @@ async function render(def0, opts = {}) {
|
|
|
22871
22923
|
u.breakBefore = false;
|
|
22872
22924
|
u.breakAfter = false;
|
|
22873
22925
|
}
|
|
22874
|
-
const
|
|
22875
|
-
parts2.push({ body, slices, g });
|
|
22926
|
+
const slices2 = paginate(body.units, body.tables, g.cH, warn);
|
|
22927
|
+
parts2.push({ body, slices: slices2, g });
|
|
22876
22928
|
if (lc.rowBudget?.cut) break sections;
|
|
22877
22929
|
if (!overflow.more) break;
|
|
22878
22930
|
if (rep + 1 >= REUSE_LIMITS.repeats) {
|
|
@@ -22913,19 +22965,21 @@ async function render(def0, opts = {}) {
|
|
|
22913
22965
|
const headings = [];
|
|
22914
22966
|
const pages2 = [];
|
|
22915
22967
|
list2.forEach(({ part: part2, k, last }, n5) => {
|
|
22916
|
-
const { body, slices, g } = part2;
|
|
22968
|
+
const { body, slices: slices2, g } = part2;
|
|
22917
22969
|
const { pg, colCount, colW, colGap, cH } = g;
|
|
22918
22970
|
const ph = parts2.length === 1 ? pageH : pg.height;
|
|
22919
22971
|
const ml = pg.margins.left, mt = pg.margins.top;
|
|
22920
22972
|
const bodyTop = mt + g.hH;
|
|
22921
22973
|
const items = [];
|
|
22922
22974
|
const cut = lc.rowBudget?.cut;
|
|
22923
|
-
const
|
|
22975
|
+
const win = opts.pageWindow, off = win ? win.offset : 0, all = win ? win.total ?? "…" : null;
|
|
22976
|
+
const globals = { ...baseCtx.globals, PageNumber: n5 - secStart[n5] + 1 + (secStart[n5] ? 0 : off), TotalPages: cut ? "…" : all ?? secLen.get(secStart[n5]), OverallPageNumber: n5 + 1 + off, OverallTotalPages: cut ? "…" : all ?? total };
|
|
22977
|
+
const isFirst = n5 + off === 0, isLast = n5 === total - 1 && (!win || win.final);
|
|
22924
22978
|
const plc = makeLc(globals, true);
|
|
22925
|
-
const band = (section, y0,
|
|
22979
|
+
const band = (section, y0, isFirst2, isLast2) => {
|
|
22926
22980
|
if (!section) return;
|
|
22927
|
-
if (
|
|
22928
|
-
if (
|
|
22981
|
+
if (isFirst2 && section.printOnFirstPage === false) return;
|
|
22982
|
+
if (isLast2 && section.printOnLastPage === false) return;
|
|
22929
22983
|
const capped2 = () => warn(`The page headers and footers would draw more than ${BAND_ITEMS.toLocaleString("en-US")} items in this report; they are left out of the later pages. Make them lighter, or the report shorter.`);
|
|
22930
22984
|
if (bandWork.left <= 0) {
|
|
22931
22985
|
capped2();
|
|
@@ -22946,40 +23000,48 @@ async function render(def0, opts = {}) {
|
|
|
22946
23000
|
for (const u of r.units) if (c.paged) placeItems(u.items, ml, y0 + u.top, items);
|
|
22947
23001
|
else for (const it of shiftItems(u.items, ml, y0 + u.top)) items.push(it);
|
|
22948
23002
|
};
|
|
22949
|
-
band(g.hdr, mt, g.own.h ? k === 0 :
|
|
23003
|
+
band(g.hdr, mt, g.own.h ? k === 0 : isFirst, g.own.h ? last : isLast);
|
|
22950
23004
|
const frozen = [];
|
|
22951
23005
|
for (let c = 0; c < colCount; c++) {
|
|
22952
|
-
const p =
|
|
23006
|
+
const p = slices2[k * colCount + c];
|
|
22953
23007
|
if (!p) break;
|
|
22954
23008
|
const cx = ml + c * (colW + colGap);
|
|
22955
23009
|
for (const t of p.repeat) placeItems(t.headerItems, cx, bodyTop, items);
|
|
22956
23010
|
for (const t of body.tables) {
|
|
22957
23011
|
if (!(t.top < p.bottom - EPS4 && t.bottom > p.top + EPS4)) continue;
|
|
22958
23012
|
const cont = p.repeat.includes(t);
|
|
22959
|
-
let
|
|
23013
|
+
let off2 = 0;
|
|
22960
23014
|
if (!cont) {
|
|
22961
|
-
for (const r of p.repeat) if (t.x0 < r.x1 - EPS4 && r.x0 < t.x1 - EPS4)
|
|
23015
|
+
for (const r of p.repeat) if (t.x0 < r.x1 - EPS4 && r.x0 < t.x1 - EPS4) off2 = Math.max(off2, r.headerHeight);
|
|
22962
23016
|
}
|
|
22963
|
-
const y = cont ? bodyTop : bodyTop +
|
|
22964
|
-
frozen.push({ x: cx + t.x0, y, w: t.x1 - t.x0, h: t.headerHeight, end: bodyTop + (cont ? t.headerHeight :
|
|
23017
|
+
const y = cont ? bodyTop : bodyTop + off2 + t.top - p.top;
|
|
23018
|
+
frozen.push({ x: cx + t.x0, y, w: t.x1 - t.x0, h: t.headerHeight, end: bodyTop + (cont ? t.headerHeight : off2) + Math.min(t.bottom, p.bottom) - p.top });
|
|
22965
23019
|
}
|
|
22966
23020
|
for (const u of p.units) {
|
|
22967
|
-
let
|
|
22968
|
-
for (const t of p.repeat) if (u.x0 < t.x1 - EPS4 && t.x0 < u.x1 - EPS4)
|
|
22969
|
-
if (u.atBottom)
|
|
22970
|
-
if (u.cont && u.top <= p.top + EPS4) placeItems(u.cont, cx, bodyTop +
|
|
22971
|
-
placeItems(u.items, cx, bodyTop +
|
|
23021
|
+
let off2 = 0;
|
|
23022
|
+
for (const t of p.repeat) if (u.x0 < t.x1 - EPS4 && t.x0 < u.x1 - EPS4) off2 = Math.max(off2, t.headerHeight);
|
|
23023
|
+
if (u.atBottom) off2 += Math.max(0, cH - off2 - (p.bottom - p.top));
|
|
23024
|
+
if (u.cont && u.top <= p.top + EPS4) placeItems(u.cont, cx, bodyTop + off2, items);
|
|
23025
|
+
placeItems(u.items, cx, bodyTop + off2 + (u.top - p.top), items);
|
|
22972
23026
|
}
|
|
22973
23027
|
}
|
|
22974
|
-
band(g.ftr, ph - pg.margins.bottom - g.fH, g.own.f ? k === 0 :
|
|
23028
|
+
band(g.ftr, ph - pg.margins.bottom - g.fH, g.own.f ? k === 0 : isFirst, g.own.f ? last : isLast);
|
|
22975
23029
|
let j = 0;
|
|
22976
23030
|
for (let i = 0; i < items.length; i++) {
|
|
22977
23031
|
const it = items[i];
|
|
22978
|
-
if (it.t === "bookmark") (it.heading ? headings : bookmarks2).push({ label: it.label, page: n5 + 1, y: it.y, level: it.level || 0, ...secStart[n5] ? { shown: n5 - secStart[n5] + 1 } : {} });
|
|
23032
|
+
if (it.t === "bookmark") (it.heading ? headings : bookmarks2).push({ label: it.label, page: n5 + 1 + off, y: it.y, level: it.level || 0, ...secStart[n5] ? { shown: n5 - secStart[n5] + 1 } : {} });
|
|
22979
23033
|
else items[j++] = it;
|
|
22980
23034
|
}
|
|
22981
23035
|
items.length = j;
|
|
22982
23036
|
const out = frozen.length ? { items, frozen } : { items };
|
|
23037
|
+
if (win) {
|
|
23038
|
+
const u = slices2[k * colCount]?.units[0];
|
|
23039
|
+
if (u?.dataRow != null) {
|
|
23040
|
+
out.firstRow = u.dataRow;
|
|
23041
|
+
out.rowHead = !!u.rowHead;
|
|
23042
|
+
if (u.headLevel != null) out.headLevel = u.headLevel;
|
|
23043
|
+
}
|
|
23044
|
+
}
|
|
22983
23045
|
if (pg.width !== first.width || ph !== pageH) {
|
|
22984
23046
|
out.width = pg.width;
|
|
22985
23047
|
out.height = ph;
|
|
@@ -23047,7 +23109,7 @@ async function render(def0, opts = {}) {
|
|
|
23047
23109
|
if (m.noGlyph.size) {
|
|
23048
23110
|
const cjk2 = [...m.noGlyph].some((c) => /[\u1100-\u11ff\u2600-\u27bf\u2b00-\u2bff\u3000-\u9fff\uac00-\ud7af\uf900-\ufaff\uff00-\uffef]|[\u{1f000}-\u{1faff}]/u.test(c));
|
|
23049
23111
|
const list2 = [...m.noGlyph].slice(0, 20).join(" ");
|
|
23050
|
-
warn(cjk2 ? `${NO_CJK_FONTS}
|
|
23112
|
+
warn(cjk2 ? `${NO_CJK_FONTS}. Until then these characters show as boxes: ${list2}.` : `No font has these characters, so they show as boxes: ${list2}. Upload a font that has them and use it for this text.`);
|
|
23051
23113
|
}
|
|
23052
23114
|
if (opts.bodyOnly) return { units: result.body.units, tables: result.body.tables, height: result.body.height, regions, warnings, clipped: clipped() };
|
|
23053
23115
|
if (opts.dataOnly) return {
|
|
@@ -23087,6 +23149,7 @@ async function render(def0, opts = {}) {
|
|
|
23087
23149
|
headings: result.headings || [],
|
|
23088
23150
|
pageStarts: result.pageStarts || [],
|
|
23089
23151
|
regions: opts.exportData ? regions : null,
|
|
23152
|
+
hasTables: tablesSeen.n > 0,
|
|
23090
23153
|
name: def.name || "",
|
|
23091
23154
|
partial: cutRows(),
|
|
23092
23155
|
timeZone: timeZone || null,
|
|
@@ -23378,36 +23441,9 @@ function pdfEncryptOptions(pdf) {
|
|
|
23378
23441
|
}
|
|
23379
23442
|
|
|
23380
23443
|
// src/exporters/pdf.js
|
|
23381
|
-
import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as
|
|
23444
|
+
import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as PDFHexString5, PDFRawStream as PDFRawStream2, rgb as rgb3 } from "pdf-lib";
|
|
23382
23445
|
import fontkitModule2 from "@pdf-lib/fontkit";
|
|
23383
23446
|
|
|
23384
|
-
// src/exporters/color.js
|
|
23385
|
-
var NAMED2 = { black: "#000000", white: "#ffffff", red: "#ff0000", green: "#008000", blue: "#0000ff", gray: "#808080", grey: "#808080", orange: "#ffa500", yellow: "#ffff00" };
|
|
23386
|
-
function parseColor(c) {
|
|
23387
|
-
if (!c || c === "none" || c === "transparent") return null;
|
|
23388
|
-
let s = String(c).trim().toLowerCase();
|
|
23389
|
-
if (NAMED2[s]) s = NAMED2[s];
|
|
23390
|
-
let m = /^#([0-9a-f]{3,8})$/.exec(s);
|
|
23391
|
-
if (m) {
|
|
23392
|
-
let h = m[1];
|
|
23393
|
-
if (h.length === 3 || h.length === 4) h = [...h].map((x) => x + x).join("");
|
|
23394
|
-
const n5 = parseInt(h.slice(0, 6), 16);
|
|
23395
|
-
const a = h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;
|
|
23396
|
-
return { r: (n5 >> 16 & 255) / 255, g: (n5 >> 8 & 255) / 255, b: (n5 & 255) / 255, a };
|
|
23397
|
-
}
|
|
23398
|
-
m = /^rgba?\(([^)]+)\)$/.exec(s);
|
|
23399
|
-
if (m) {
|
|
23400
|
-
const [r, g, b, a = 1] = m[1].split(/[\s,/]+/).map(Number);
|
|
23401
|
-
return { r: r / 255, g: g / 255, b: b / 255, a };
|
|
23402
|
-
}
|
|
23403
|
-
return null;
|
|
23404
|
-
}
|
|
23405
|
-
function cssColor(c) {
|
|
23406
|
-
const p = parseColor(c);
|
|
23407
|
-
if (!p) return "none";
|
|
23408
|
-
return `rgba(${Math.round(p.r * 255)},${Math.round(p.g * 255)},${Math.round(p.b * 255)},${p.a})`;
|
|
23409
|
-
}
|
|
23410
|
-
|
|
23411
23447
|
// src/exporters/pdfa.js
|
|
23412
23448
|
import { PDFName, PDFNumber as PDFNumber2, PDFString as PDFString2, PDFHexString as PDFHexString2, PDFArray as PDFArray2, PDFDict as PDFDict2 } from "pdf-lib";
|
|
23413
23449
|
var xml = (s) => String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -23481,6 +23517,35 @@ function setUaMetadata(doc, { title: title2 = "Report", author = void 0, created
|
|
|
23481
23517
|
|
|
23482
23518
|
// src/exporters/svgimage.js
|
|
23483
23519
|
import { pushGraphicsState, popGraphicsState, concatTransformationMatrix, rgb } from "pdf-lib";
|
|
23520
|
+
|
|
23521
|
+
// src/exporters/color.js
|
|
23522
|
+
var NAMED2 = { black: "#000000", white: "#ffffff", red: "#ff0000", green: "#008000", blue: "#0000ff", gray: "#808080", grey: "#808080", orange: "#ffa500", yellow: "#ffff00" };
|
|
23523
|
+
function parseColor(c) {
|
|
23524
|
+
if (!c || c === "none" || c === "transparent") return null;
|
|
23525
|
+
let s = String(c).trim().toLowerCase();
|
|
23526
|
+
if (NAMED2[s]) s = NAMED2[s];
|
|
23527
|
+
let m = /^#([0-9a-f]{3,8})$/.exec(s);
|
|
23528
|
+
if (m) {
|
|
23529
|
+
let h = m[1];
|
|
23530
|
+
if (h.length === 3 || h.length === 4) h = [...h].map((x) => x + x).join("");
|
|
23531
|
+
const n5 = parseInt(h.slice(0, 6), 16);
|
|
23532
|
+
const a = h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;
|
|
23533
|
+
return { r: (n5 >> 16 & 255) / 255, g: (n5 >> 8 & 255) / 255, b: (n5 & 255) / 255, a };
|
|
23534
|
+
}
|
|
23535
|
+
m = /^rgba?\(([^)]+)\)$/.exec(s);
|
|
23536
|
+
if (m) {
|
|
23537
|
+
const [r, g, b, a = 1] = m[1].split(/[\s,/]+/).map(Number);
|
|
23538
|
+
return { r: r / 255, g: g / 255, b: b / 255, a };
|
|
23539
|
+
}
|
|
23540
|
+
return null;
|
|
23541
|
+
}
|
|
23542
|
+
function cssColor(c) {
|
|
23543
|
+
const p = parseColor(c);
|
|
23544
|
+
if (!p) return "none";
|
|
23545
|
+
return `rgba(${Math.round(p.r * 255)},${Math.round(p.g * 255)},${Math.round(p.b * 255)},${p.a})`;
|
|
23546
|
+
}
|
|
23547
|
+
|
|
23548
|
+
// src/exporters/svgimage.js
|
|
23484
23549
|
var mul = (a, b) => [a[0] * b[0] + a[2] * b[1], a[1] * b[0] + a[3] * b[1], a[0] * b[2] + a[2] * b[3], a[1] * b[2] + a[3] * b[3], a[0] * b[4] + a[2] * b[5] + a[4], a[1] * b[4] + a[3] * b[5] + a[5]];
|
|
23485
23550
|
var I = [1, 0, 0, 1, 0, 0];
|
|
23486
23551
|
var TRANSFORMS = /* @__PURE__ */ new Set(["matrix", "translate", "scale", "rotate", "skewX", "skewY"]);
|
|
@@ -24112,7 +24177,7 @@ function cellVisuals(items, used, tables) {
|
|
|
24112
24177
|
|
|
24113
24178
|
// src/exporters/regions.js
|
|
24114
24179
|
function needsTableData(model, what) {
|
|
24115
|
-
if (model && model.regions === null) throw Object.assign(new Error(`${what} needs the report's table data: render it with { exportData: true }`), { code: "NO_EXPORT_DATA" });
|
|
24180
|
+
if (model && model.regions === null && model.hasTables !== false) throw Object.assign(new Error(`${what} needs the report's table data: render it with { exportData: true }`), { code: "NO_EXPORT_DATA" });
|
|
24116
24181
|
}
|
|
24117
24182
|
function mergedRegions(model) {
|
|
24118
24183
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -24547,11 +24612,8 @@ function pngProblem(b) {
|
|
|
24547
24612
|
return null;
|
|
24548
24613
|
}
|
|
24549
24614
|
|
|
24550
|
-
// src/exporters/
|
|
24551
|
-
|
|
24552
|
-
/** @type {any} */
|
|
24553
|
-
fontkitModule2.default || fontkitModule2
|
|
24554
|
-
);
|
|
24615
|
+
// src/exporters/pdfpaint.js
|
|
24616
|
+
import { PDFHexString as PDFHexString4, rgb as rgb2 } from "pdf-lib";
|
|
24555
24617
|
var colors = /* @__PURE__ */ new Map();
|
|
24556
24618
|
var col = (c) => {
|
|
24557
24619
|
if (colors.has(c)) return colors.get(c);
|
|
@@ -24566,138 +24628,460 @@ var n4 = (v) => Math.round(v * 1e4) / 1e4;
|
|
|
24566
24628
|
var hex4 = (id) => id.toString(16).padStart(4, "0");
|
|
24567
24629
|
var KAPPA = 4 * ((Math.SQRT2 - 1) / 3);
|
|
24568
24630
|
var cleanText = (t) => t.replace(/\t|\u0085|\u2028|\u2029/g, " ").replace(/[\b\v]/g, "");
|
|
24569
|
-
|
|
24570
|
-
|
|
24571
|
-
|
|
24572
|
-
|
|
24573
|
-
|
|
24574
|
-
|
|
24575
|
-
|
|
24576
|
-
|
|
24577
|
-
|
|
24578
|
-
|
|
24579
|
-
|
|
24580
|
-
|
|
24581
|
-
|
|
24582
|
-
|
|
24583
|
-
|
|
24584
|
-
|
|
24585
|
-
|
|
24586
|
-
|
|
24587
|
-
|
|
24588
|
-
|
|
24589
|
-
|
|
24590
|
-
const spans2 = /* @__PURE__ */ new WeakMap();
|
|
24591
|
-
const chars = (key) => {
|
|
24592
|
-
let c = used.get(key);
|
|
24593
|
-
if (!c) {
|
|
24594
|
-
c = /* @__PURE__ */ new Set([32]);
|
|
24595
|
-
used.set(key, c);
|
|
24596
|
-
}
|
|
24597
|
-
return c;
|
|
24631
|
+
var formatAt = (run, cl) => {
|
|
24632
|
+
const cp = run.text.codePointAt(cl);
|
|
24633
|
+
return cp !== void 0 && FORMAT_CHAR.test(String.fromCodePoint(cp));
|
|
24634
|
+
};
|
|
24635
|
+
function drawRun(c, run, x, y, size, pf, color2, spans2, texts) {
|
|
24636
|
+
const f4 = pf.embedder.font;
|
|
24637
|
+
const per = 1e3 / size;
|
|
24638
|
+
const span = (text2) => `/Span <</ActualText ${PDFHexString4.fromText(text2).toString()}>> BDC
|
|
24639
|
+
`;
|
|
24640
|
+
c.et();
|
|
24641
|
+
c.paint(color2, null);
|
|
24642
|
+
c.font(pf, size);
|
|
24643
|
+
if (!run.rtl) c.s += span(run.text);
|
|
24644
|
+
c.s += `BT ${n2(x)} ${n2(y)} Td
|
|
24645
|
+
`;
|
|
24646
|
+
let arr = "";
|
|
24647
|
+
let pen = 0, rise = 0;
|
|
24648
|
+
const flush = () => {
|
|
24649
|
+
if (arr) c.s += `[${arr}] TJ
|
|
24650
|
+
`;
|
|
24651
|
+
arr = "";
|
|
24598
24652
|
};
|
|
24599
|
-
|
|
24600
|
-
|
|
24601
|
-
|
|
24602
|
-
|
|
24603
|
-
|
|
24604
|
-
|
|
24605
|
-
|
|
24606
|
-
|
|
24607
|
-
|
|
24608
|
-
|
|
24609
|
-
for (
|
|
24610
|
-
const c = chars(r.font);
|
|
24611
|
-
for (const ch of r.text) c.add(
|
|
24612
|
-
/** @type {number} */
|
|
24613
|
-
ch.codePointAt(0)
|
|
24614
|
-
);
|
|
24615
|
-
let g = shaped.get(r.font);
|
|
24616
|
-
if (!g) {
|
|
24617
|
-
g = /* @__PURE__ */ new Map();
|
|
24618
|
-
shaped.set(r.font, g);
|
|
24619
|
-
}
|
|
24620
|
-
glyphText(r, fontStore2.get(r.font), g, spans2);
|
|
24621
|
-
}
|
|
24653
|
+
const all = run.glyphs;
|
|
24654
|
+
const adv = (id) => f4.getGlyph(id).advanceWidth;
|
|
24655
|
+
let g = all, quietAt = -1;
|
|
24656
|
+
if (run.rtl) {
|
|
24657
|
+
const hasBase = /* @__PURE__ */ new Set();
|
|
24658
|
+
for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
|
|
24659
|
+
const quiet = (i) => spans2?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
|
|
24660
|
+
g = [];
|
|
24661
|
+
for (const late of [false, true]) {
|
|
24662
|
+
if (late) quietAt = g.length;
|
|
24663
|
+
for (let i = 0; i < all.length; i += 4) if (quiet(i) === late) g.push(all[i], all[i + 1], all[i + 2], all[i + 3]);
|
|
24622
24664
|
}
|
|
24665
|
+
if (quietAt === g.length) quietAt = -1;
|
|
24623
24666
|
}
|
|
24624
|
-
const
|
|
24625
|
-
|
|
24626
|
-
|
|
24627
|
-
|
|
24628
|
-
if (
|
|
24629
|
-
|
|
24630
|
-
|
|
24631
|
-
|
|
24632
|
-
|
|
24633
|
-
|
|
24634
|
-
|
|
24635
|
-
|
|
24636
|
-
const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
|
|
24637
|
-
const f4 = fontkit2.create(sub);
|
|
24638
|
-
for (const cp of cps) void f4.glyphForCodePoint(cp).advanceWidth;
|
|
24639
|
-
for (const id of glyphs?.keys() || []) void f4.getGlyph(id).advanceWidth;
|
|
24640
|
-
bytes = sub;
|
|
24641
|
-
} catch {
|
|
24642
|
-
}
|
|
24643
|
-
}
|
|
24644
|
-
const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore2.get(key).postscriptName || "Font"}` });
|
|
24645
|
-
plainEncoding(pf);
|
|
24646
|
-
if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
|
|
24647
|
-
const file = bytes, e2 = (
|
|
24648
|
-
/** @type {any} */
|
|
24649
|
-
pf.embedder
|
|
24650
|
-
);
|
|
24651
|
-
if (!e2.isCFF()) e2.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
|
|
24652
|
-
fonts.set(key, pf);
|
|
24667
|
+
const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
|
|
24668
|
+
let inSpan = false;
|
|
24669
|
+
for (let i = 0; i < g.length; i += 4) {
|
|
24670
|
+
const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
|
|
24671
|
+
if (i === quietAt) {
|
|
24672
|
+
flush();
|
|
24673
|
+
c.s += span("");
|
|
24674
|
+
inSpan = true;
|
|
24675
|
+
} else if (run.rtl && spans2?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
|
|
24676
|
+
flush();
|
|
24677
|
+
c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
|
|
24678
|
+
inSpan = true;
|
|
24653
24679
|
}
|
|
24654
|
-
|
|
24655
|
-
|
|
24656
|
-
|
|
24657
|
-
|
|
24658
|
-
|
|
24659
|
-
const out = await loadImage(src).catch((e2) => ({ img: null, why: `it could not be embedded (${e2?.message || e2})` }));
|
|
24660
|
-
images.set(src, out);
|
|
24661
|
-
return out;
|
|
24662
|
-
};
|
|
24663
|
-
async function loadImage(src) {
|
|
24664
|
-
const local = /^data:/i.test(src);
|
|
24665
|
-
if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
|
|
24666
|
-
if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
|
|
24667
|
-
const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
|
|
24668
|
-
if (!bytes?.length) return { img: null, why: "it could not be loaded" };
|
|
24669
|
-
if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
|
|
24670
|
-
const info = imageInfoOf(bytes);
|
|
24671
|
-
if (info?.type === "svg") {
|
|
24672
|
-
const svg = parseSvg(new TextDecoder().decode(bytes));
|
|
24673
|
-
return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
|
|
24680
|
+
if (gy !== rise) {
|
|
24681
|
+
flush();
|
|
24682
|
+
c.s += `${n4(gy)} Ts
|
|
24683
|
+
`;
|
|
24684
|
+
rise = gy;
|
|
24674
24685
|
}
|
|
24675
|
-
|
|
24676
|
-
|
|
24677
|
-
|
|
24678
|
-
|
|
24686
|
+
const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
|
|
24687
|
+
if (id === 0 && (c.tagged || formatAt(run, cl))) pen = gx;
|
|
24688
|
+
else {
|
|
24689
|
+
arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
|
|
24690
|
+
pen = gx + adv(id) * size / f4.unitsPerEm;
|
|
24679
24691
|
}
|
|
24680
|
-
if (
|
|
24681
|
-
|
|
24682
|
-
|
|
24683
|
-
|
|
24684
|
-
const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
|
|
24685
|
-
const resRef = ctx.register(res);
|
|
24686
|
-
const names = /* @__PURE__ */ new Map();
|
|
24687
|
-
const nameOf = (kind, key, value) => {
|
|
24688
|
-
let n5 = names.get(key);
|
|
24689
|
-
if (!n5) {
|
|
24690
|
-
n5 = `${kind[0]}${names.size + 1}`;
|
|
24691
|
-
names.set(key, n5);
|
|
24692
|
-
res.get(PDFName3.of(kind)).set(PDFName3.of(n5), value());
|
|
24692
|
+
if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
|
|
24693
|
+
flush();
|
|
24694
|
+
c.s += "EMC\n";
|
|
24695
|
+
inSpan = false;
|
|
24693
24696
|
}
|
|
24694
|
-
|
|
24695
|
-
|
|
24696
|
-
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24697
|
+
}
|
|
24698
|
+
flush();
|
|
24699
|
+
if (rise) c.s += "0 Ts\n";
|
|
24700
|
+
c.s += "ET\n";
|
|
24701
|
+
if (!run.rtl) c.s += "EMC\n";
|
|
24702
|
+
}
|
|
24703
|
+
function glyphText(run, font, out, spans2) {
|
|
24704
|
+
const g = run.glyphs;
|
|
24705
|
+
const starts = [...new Set(g.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b);
|
|
24706
|
+
for (let k = 0; k < starts.length; k++) {
|
|
24707
|
+
const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
|
|
24708
|
+
const ids = [];
|
|
24709
|
+
for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
|
|
24710
|
+
const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
|
|
24711
|
+
const rest2 = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
|
|
24712
|
+
const carrier = rest2 ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
|
|
24713
|
+
let ok = !rest2 || carrier !== void 0;
|
|
24714
|
+
const want = /* @__PURE__ */ new Map();
|
|
24715
|
+
for (const id of ids) {
|
|
24716
|
+
const t = own.get(id) ?? (id === carrier ? rest2 : "");
|
|
24717
|
+
if (want.has(id) && want.get(id) !== t) ok = false;
|
|
24718
|
+
want.set(id, t);
|
|
24719
|
+
}
|
|
24720
|
+
for (const [id, t] of want) {
|
|
24721
|
+
if (!out.has(id)) out.set(id, t);
|
|
24722
|
+
else if (out.get(id) !== t) ok = false;
|
|
24723
|
+
}
|
|
24724
|
+
if (!ok && run.rtl && spans2) {
|
|
24725
|
+
let s = spans2.get(run);
|
|
24726
|
+
if (!s) spans2.set(run, s = /* @__PURE__ */ new Set());
|
|
24727
|
+
s.add(starts[k]);
|
|
24728
|
+
}
|
|
24729
|
+
}
|
|
24730
|
+
}
|
|
24731
|
+
function insideClip(it, m) {
|
|
24732
|
+
const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
|
|
24733
|
+
return it.lines.every((l) => l.w != null && !l.runs && l.x >= k.x && l.x + l.w <= k.x + k.w && l.y - asc >= k.y && l.y + desc <= k.y + k.h);
|
|
24734
|
+
}
|
|
24735
|
+
var Content = class {
|
|
24736
|
+
constructor(shared) {
|
|
24737
|
+
this.shared = shared;
|
|
24738
|
+
this._s = "";
|
|
24739
|
+
this.bt = false;
|
|
24740
|
+
this.tx = 0;
|
|
24741
|
+
this.ty = 0;
|
|
24742
|
+
this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
|
|
24743
|
+
this.saved = [];
|
|
24744
|
+
this.lines = null;
|
|
24745
|
+
this.tagged = false;
|
|
24746
|
+
this.artLines = false;
|
|
24747
|
+
}
|
|
24748
|
+
/**
|
|
24749
|
+
* The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
|
|
24750
|
+
* of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
|
|
24751
|
+
*/
|
|
24752
|
+
get s() {
|
|
24753
|
+
this.flushLines();
|
|
24754
|
+
return this._s;
|
|
24755
|
+
}
|
|
24756
|
+
set s(v) {
|
|
24757
|
+
this._s = v;
|
|
24758
|
+
}
|
|
24759
|
+
/**
|
|
24760
|
+
* A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
|
|
24761
|
+
* texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
|
|
24762
|
+
* ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
|
|
24763
|
+
*/
|
|
24764
|
+
line(stroke, w, dash, x1, y1, x2, y2) {
|
|
24765
|
+
if (this.tagged && !this.artLines) {
|
|
24766
|
+
this.paint(null, stroke, w, dash);
|
|
24767
|
+
this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
|
|
24768
|
+
`;
|
|
24769
|
+
return;
|
|
24770
|
+
}
|
|
24771
|
+
const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
|
|
24772
|
+
if (this.lines && this.lines.key !== key) this.flushLines();
|
|
24773
|
+
this.lines ||= { key, stroke, w, dash, segs: [] };
|
|
24774
|
+
const segs = this.lines.segs, last = segs[segs.length - 1];
|
|
24775
|
+
const eq = (a, b) => Math.abs(a - b) < 5e-3;
|
|
24776
|
+
if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
|
|
24777
|
+
else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
|
|
24778
|
+
else segs.push([x1, y1, x2, y2]);
|
|
24779
|
+
}
|
|
24780
|
+
flushLines() {
|
|
24781
|
+
const L = this.lines;
|
|
24782
|
+
if (!L) return;
|
|
24783
|
+
this.lines = null;
|
|
24784
|
+
this.et();
|
|
24785
|
+
const end = this.artLines ? "EMC\n" : "";
|
|
24786
|
+
if (end) this._s += "/Artifact BMC\n";
|
|
24787
|
+
this.paint(null, L.stroke, L.w, L.dash);
|
|
24788
|
+
const g = L.segs;
|
|
24789
|
+
const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
|
|
24790
|
+
if (dy && g.every((q3, i) => q3[1] === q3[3] && n2(q3[0]) === n2(g[0][0]) && n2(q3[2]) === n2(g[0][2]) && Math.abs(q3[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
|
|
24791
|
+
const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
|
|
24792
|
+
`;
|
|
24793
|
+
this._s += `q
|
|
24794
|
+
${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
|
|
24795
|
+
${end}`;
|
|
24796
|
+
return;
|
|
24797
|
+
}
|
|
24798
|
+
this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n" + end;
|
|
24799
|
+
}
|
|
24800
|
+
q() {
|
|
24801
|
+
this.et();
|
|
24802
|
+
this._s += "q\n";
|
|
24803
|
+
this.saved.push({ ...this.st });
|
|
24804
|
+
}
|
|
24805
|
+
Q() {
|
|
24806
|
+
this.et();
|
|
24807
|
+
this._s += "Q\n";
|
|
24808
|
+
this.st = this.saved.pop();
|
|
24809
|
+
}
|
|
24810
|
+
/**
|
|
24811
|
+
* A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
|
|
24812
|
+
* last (in whole hundredths, so nothing drifts): most of a table page is these.
|
|
24813
|
+
* @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
|
|
24814
|
+
*/
|
|
24815
|
+
text(pf, size, color2, x, y, str, array = false) {
|
|
24816
|
+
this.setPaint(color2, null);
|
|
24817
|
+
this.setFont(pf, size);
|
|
24818
|
+
const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
|
|
24819
|
+
if (!this.bt) {
|
|
24820
|
+
this._s += "BT\n";
|
|
24821
|
+
this.bt = true;
|
|
24822
|
+
this.tx = 0;
|
|
24823
|
+
this.ty = 0;
|
|
24824
|
+
}
|
|
24825
|
+
this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
|
|
24826
|
+
` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
|
|
24827
|
+
`;
|
|
24828
|
+
this.tx = X;
|
|
24829
|
+
this.ty = Y;
|
|
24830
|
+
}
|
|
24831
|
+
/** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
|
|
24832
|
+
et() {
|
|
24833
|
+
if (this.bt) {
|
|
24834
|
+
this._s += "ET\n";
|
|
24835
|
+
this.bt = false;
|
|
24836
|
+
}
|
|
24837
|
+
if (this.lines) this.flushLines();
|
|
24838
|
+
}
|
|
24839
|
+
lineWidth(w) {
|
|
24840
|
+
if (this.lines) this.flushLines();
|
|
24841
|
+
this.setLineWidth(w);
|
|
24842
|
+
}
|
|
24843
|
+
setLineWidth(w) {
|
|
24844
|
+
if (this.st.lw !== w) {
|
|
24845
|
+
this._s += `${n3(w)} w
|
|
24846
|
+
`;
|
|
24847
|
+
this.st.lw = w;
|
|
24848
|
+
}
|
|
24849
|
+
}
|
|
24850
|
+
/** the graphics state that sets these opacities, or undefined when they are set already */
|
|
24851
|
+
gsFor(ca, CA) {
|
|
24852
|
+
return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
|
|
24853
|
+
}
|
|
24854
|
+
alpha(ca, CA) {
|
|
24855
|
+
if (this.lines) this.flushLines();
|
|
24856
|
+
this.setAlpha(ca, CA);
|
|
24857
|
+
}
|
|
24858
|
+
setAlpha(ca, CA) {
|
|
24859
|
+
const g = this.gsFor(ca, CA);
|
|
24860
|
+
if (g) {
|
|
24861
|
+
this._s += `/${g} gs
|
|
24862
|
+
`;
|
|
24863
|
+
this.st.ca = ca;
|
|
24864
|
+
this.st.CA = CA;
|
|
24865
|
+
}
|
|
24866
|
+
}
|
|
24867
|
+
/** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
|
|
24868
|
+
paint(fill3, stroke, w = 1, dash = null) {
|
|
24869
|
+
if (this.lines) this.flushLines();
|
|
24870
|
+
this.setPaint(fill3, stroke, w, dash);
|
|
24871
|
+
}
|
|
24872
|
+
setPaint(fill3, stroke, w = 1, dash = null) {
|
|
24873
|
+
const st = this.st;
|
|
24874
|
+
if (fill3 && fill3.rgb !== st.fill) {
|
|
24875
|
+
this._s += `${fill3.rgb} rg
|
|
24876
|
+
`;
|
|
24877
|
+
st.fill = fill3.rgb;
|
|
24878
|
+
}
|
|
24879
|
+
if (stroke) {
|
|
24880
|
+
if (stroke.rgb !== st.stroke) {
|
|
24881
|
+
this._s += `${stroke.rgb} RG
|
|
24882
|
+
`;
|
|
24883
|
+
st.stroke = stroke.rgb;
|
|
24884
|
+
}
|
|
24885
|
+
this.setLineWidth(w);
|
|
24886
|
+
const d = `[${(dash || []).map(n3).join(" ")}] 0`;
|
|
24887
|
+
if (d !== st.dash) {
|
|
24888
|
+
this._s += `${d} d
|
|
24889
|
+
`;
|
|
24890
|
+
st.dash = d;
|
|
24891
|
+
}
|
|
24892
|
+
}
|
|
24893
|
+
this.setAlpha(fill3 ? fill3.opacity : st.ca, stroke ? stroke.opacity : st.CA);
|
|
24894
|
+
}
|
|
24895
|
+
font(pf, size) {
|
|
24896
|
+
if (this.lines) this.flushLines();
|
|
24897
|
+
this.setFont(pf, size);
|
|
24898
|
+
}
|
|
24899
|
+
setFont(pf, size) {
|
|
24900
|
+
const name = this.shared.font(pf);
|
|
24901
|
+
if (name !== this.st.font || size !== this.st.size) {
|
|
24902
|
+
this._s += `/${name} ${n3(size)} Tf
|
|
24903
|
+
`;
|
|
24904
|
+
this.st.font = name;
|
|
24905
|
+
this.st.size = size;
|
|
24906
|
+
}
|
|
24907
|
+
}
|
|
24908
|
+
};
|
|
24909
|
+
function latin1(s) {
|
|
24910
|
+
const B = (
|
|
24911
|
+
/** @type {any} */
|
|
24912
|
+
globalThis.Buffer
|
|
24913
|
+
);
|
|
24914
|
+
if (B) return B.from(s, "latin1");
|
|
24915
|
+
const out = new Uint8Array(s.length);
|
|
24916
|
+
for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
|
|
24917
|
+
return out;
|
|
24918
|
+
}
|
|
24919
|
+
async function deflate(bytes) {
|
|
24920
|
+
if (zslots.free > 0) zslots.free--;
|
|
24921
|
+
else await new Promise((ok) => zslots.wait.push(
|
|
24922
|
+
/** @type {() => void} */
|
|
24923
|
+
ok
|
|
24924
|
+
));
|
|
24925
|
+
try {
|
|
24926
|
+
return await deflateNow(bytes);
|
|
24927
|
+
} finally {
|
|
24928
|
+
const next = zslots.wait.shift();
|
|
24929
|
+
if (next) next();
|
|
24930
|
+
else zslots.free++;
|
|
24931
|
+
}
|
|
24932
|
+
}
|
|
24933
|
+
var zslots = { free: 4, wait: (
|
|
24934
|
+
/** @type {(() => void)[]} */
|
|
24935
|
+
[]
|
|
24936
|
+
) };
|
|
24937
|
+
var NODE_ZLIB = (
|
|
24938
|
+
/** @type {any} */
|
|
24939
|
+
globalThis.process?.getBuiltinModule?.("node:zlib")
|
|
24940
|
+
);
|
|
24941
|
+
async function deflateNow(bytes) {
|
|
24942
|
+
const zlib = NODE_ZLIB;
|
|
24943
|
+
if (zlib) return new Promise((ok, fail2) => zlib.deflate(bytes, { level: 9 }, (e2, z) => e2 ? fail2(e2) : ok(z)));
|
|
24944
|
+
if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
|
|
24945
|
+
return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
|
24946
|
+
}
|
|
24947
|
+
|
|
24948
|
+
// src/exporters/pdf.js
|
|
24949
|
+
var fontkit2 = (
|
|
24950
|
+
/** @type {any} */
|
|
24951
|
+
fontkitModule2.default || fontkitModule2
|
|
24952
|
+
);
|
|
24953
|
+
function exportPdf(model, fontStore2, opt = {}) {
|
|
24954
|
+
return withDeadline(
|
|
24955
|
+
pdfOf(model, fontStore2, opt),
|
|
24956
|
+
/** @type {any} */
|
|
24957
|
+
opt.timeoutMs
|
|
24958
|
+
);
|
|
24959
|
+
}
|
|
24960
|
+
async function pdfOf(model, fontStore2, opt) {
|
|
24961
|
+
const fixed2 = fixedDate(opt);
|
|
24962
|
+
const when = fixed2 ?? /* @__PURE__ */ new Date();
|
|
24963
|
+
const fileId = fixed2 ? await contentId(model, opt, when) : void 0;
|
|
24964
|
+
const doc = await PDFDocument.create({ updateMetadata: false });
|
|
24965
|
+
doc.registerFontkit(fontkit2);
|
|
24966
|
+
doc.setTitle(opt.title || "Report");
|
|
24967
|
+
doc.setProducer("ReportWright");
|
|
24968
|
+
doc.setCreator("ReportWright");
|
|
24969
|
+
if (opt.author) doc.setAuthor(opt.author);
|
|
24970
|
+
setInfoDates(doc, when);
|
|
24971
|
+
if (fileId) doc.context.trailerInfo.ID = doc.context.obj([PDFHexString5.of(fileId), PDFHexString5.of(fileId)]);
|
|
24972
|
+
const used = /* @__PURE__ */ new Map();
|
|
24973
|
+
const shaped = /* @__PURE__ */ new Map();
|
|
24974
|
+
const spans2 = /* @__PURE__ */ new WeakMap();
|
|
24975
|
+
const chars = (key) => {
|
|
24976
|
+
let c = used.get(key);
|
|
24977
|
+
if (!c) {
|
|
24978
|
+
c = /* @__PURE__ */ new Set([32]);
|
|
24979
|
+
used.set(key, c);
|
|
24980
|
+
}
|
|
24981
|
+
return c;
|
|
24982
|
+
};
|
|
24983
|
+
for (const pg of model.pages) for (const it of pg.items.flatMap((i) => i.t === "field" ? i.draw.filter((d) => d.t === "text") : i.t === "text" ? [i] : [])) {
|
|
24984
|
+
for (const l of it.lines) {
|
|
24985
|
+
if (!l.runs) {
|
|
24986
|
+
const c = chars(it.font);
|
|
24987
|
+
for (const ch of l.text) c.add(
|
|
24988
|
+
/** @type {number} */
|
|
24989
|
+
ch.codePointAt(0)
|
|
24990
|
+
);
|
|
24991
|
+
continue;
|
|
24992
|
+
}
|
|
24993
|
+
for (const r of l.runs) {
|
|
24994
|
+
const c = chars(r.font);
|
|
24995
|
+
for (const ch of r.text) c.add(
|
|
24996
|
+
/** @type {number} */
|
|
24997
|
+
ch.codePointAt(0)
|
|
24998
|
+
);
|
|
24999
|
+
let g = shaped.get(r.font);
|
|
25000
|
+
if (!g) {
|
|
25001
|
+
g = /* @__PURE__ */ new Map();
|
|
25002
|
+
shaped.set(r.font, g);
|
|
25003
|
+
}
|
|
25004
|
+
glyphText(r, fontStore2.get(r.font), g, spans2);
|
|
25005
|
+
}
|
|
25006
|
+
}
|
|
25007
|
+
}
|
|
25008
|
+
const fieldFonts = /* @__PURE__ */ new Set();
|
|
25009
|
+
for (const pg of model.pages) for (const it of pg.items) if (it.t === "field") fieldFonts.add(fieldFont(it));
|
|
25010
|
+
const fonts = /* @__PURE__ */ new Map();
|
|
25011
|
+
const font = async (key) => {
|
|
25012
|
+
if (!fonts.has(key)) {
|
|
25013
|
+
const full = fontStore2.bytes.get(key);
|
|
25014
|
+
let bytes = full;
|
|
25015
|
+
if (!bytes) throw new Error(`Font "${key}" is not loaded`);
|
|
25016
|
+
const glyphs = shaped.get(key);
|
|
25017
|
+
if (opt.subset && !fieldFonts.has(key) && !fontStore2.get(key)["OS/2"]?.fsType?.noSubsetting) {
|
|
25018
|
+
const cps = used.get(key) || /* @__PURE__ */ new Set([32]);
|
|
25019
|
+
try {
|
|
25020
|
+
const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
|
|
25021
|
+
const f4 = fontkit2.create(sub);
|
|
25022
|
+
for (const cp of cps) void f4.glyphForCodePoint(cp).advanceWidth;
|
|
25023
|
+
for (const id of glyphs?.keys() || []) void f4.getGlyph(id).advanceWidth;
|
|
25024
|
+
bytes = sub;
|
|
25025
|
+
} catch {
|
|
25026
|
+
}
|
|
25027
|
+
}
|
|
25028
|
+
const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore2.get(key).postscriptName || "Font"}` });
|
|
25029
|
+
plainEncoding(pf);
|
|
25030
|
+
if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
|
|
25031
|
+
const file = bytes, e2 = (
|
|
25032
|
+
/** @type {any} */
|
|
25033
|
+
pf.embedder
|
|
25034
|
+
);
|
|
25035
|
+
if (!e2.isCFF()) e2.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
|
|
25036
|
+
fonts.set(key, pf);
|
|
25037
|
+
}
|
|
25038
|
+
return fonts.get(key);
|
|
25039
|
+
};
|
|
25040
|
+
const images = /* @__PURE__ */ new Map();
|
|
25041
|
+
const image2 = async (src) => {
|
|
25042
|
+
if (images.has(src)) return images.get(src);
|
|
25043
|
+
const out = await loadImage(src).catch((e2) => ({ img: null, why: `it could not be embedded (${e2?.message || e2})` }));
|
|
25044
|
+
images.set(src, out);
|
|
25045
|
+
return out;
|
|
25046
|
+
};
|
|
25047
|
+
async function loadImage(src) {
|
|
25048
|
+
const local = /^data:/i.test(src);
|
|
25049
|
+
if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
|
|
25050
|
+
if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
|
|
25051
|
+
const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
|
|
25052
|
+
if (!bytes?.length) return { img: null, why: "it could not be loaded" };
|
|
25053
|
+
if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
|
|
25054
|
+
const info = imageInfoOf(bytes);
|
|
25055
|
+
if (info?.type === "svg") {
|
|
25056
|
+
const svg = parseSvg(new TextDecoder().decode(bytes));
|
|
25057
|
+
return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
|
|
25058
|
+
}
|
|
25059
|
+
if (info?.type === "png") {
|
|
25060
|
+
const why = "w" in info && !/** @type {any} */
|
|
25061
|
+
info.suspect && info.w * info.h <= IMAGE_LIMITS.pixels ? pngProblem(bytes) : "too large or animated";
|
|
25062
|
+
return why ? { img: null, why: `the PNG is not usable (${why})` } : { img: await doc.embedPng(bytes) };
|
|
25063
|
+
}
|
|
25064
|
+
if (info?.type === "jpeg") return { img: await doc.embedJpg(bytes) };
|
|
25065
|
+
return { img: null, why: info ? `${info.type.toUpperCase()} is not embedded (PNG, JPEG and SVG are)` : "it is not a PNG, JPEG or SVG" };
|
|
25066
|
+
}
|
|
25067
|
+
const ctx = doc.context;
|
|
25068
|
+
const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
|
|
25069
|
+
const resRef = ctx.register(res);
|
|
25070
|
+
const names = /* @__PURE__ */ new Map();
|
|
25071
|
+
const nameOf = (kind, key, value) => {
|
|
25072
|
+
let n5 = names.get(key);
|
|
25073
|
+
if (!n5) {
|
|
25074
|
+
n5 = `${kind[0]}${names.size + 1}`;
|
|
25075
|
+
names.set(key, n5);
|
|
25076
|
+
res.get(PDFName3.of(kind)).set(PDFName3.of(n5), value());
|
|
25077
|
+
}
|
|
25078
|
+
return n5;
|
|
25079
|
+
};
|
|
25080
|
+
const shared = {
|
|
25081
|
+
font: (pf) => nameOf("Font", pf, () => pf.ref),
|
|
25082
|
+
gs: (ca, CA) => nameOf("ExtGState", `gs ${ca} ${CA}`, () => ctx.obj({ Type: "ExtGState", ca, CA })),
|
|
25083
|
+
image: (img) => nameOf("XObject", img, () => img.ref)
|
|
25084
|
+
};
|
|
24701
25085
|
const links = [];
|
|
24702
25086
|
const taken = /* @__PURE__ */ new Set();
|
|
24703
25087
|
const uniqueName = (n5) => {
|
|
@@ -24831,7 +25215,7 @@ async function pdfOf(model, fontStore2, opt) {
|
|
|
24831
25215
|
const form = doc.getForm();
|
|
24832
25216
|
const f4 = await font(fieldFont(it));
|
|
24833
25217
|
const name = uniqueName(it.name);
|
|
24834
|
-
const box = { x: it.x, y: H - it.y - it.h, width: it.w, height: it.h, borderColor:
|
|
25218
|
+
const box = { x: it.x, y: H - it.y - it.h, width: it.w, height: it.h, borderColor: rgb3(0.61, 0.64, 0.69), borderWidth: 0.75, backgroundColor: rgb3(1, 1, 1) };
|
|
24835
25219
|
let field;
|
|
24836
25220
|
if (it.kind === "checkbox") {
|
|
24837
25221
|
field = form.createCheckBox(name);
|
|
@@ -24888,7 +25272,7 @@ async function pdfOf(model, fontStore2, opt) {
|
|
|
24888
25272
|
if (it.required) field.enableRequired();
|
|
24889
25273
|
if (it.readOnly) field.enableReadOnly();
|
|
24890
25274
|
if (tags) {
|
|
24891
|
-
field.acroField.dict.set(PDFName3.of("TU"),
|
|
25275
|
+
field.acroField.dict.set(PDFName3.of("TU"), PDFHexString5.fromText(it.label || it.name || name));
|
|
24892
25276
|
const w = field.acroField.getWidgets()[0];
|
|
24893
25277
|
const ref3 = w && doc.context.getObjectRef(w.dict);
|
|
24894
25278
|
if (ref3) tags.annot(pi, ii, ref3, "field");
|
|
@@ -24962,7 +25346,7 @@ async function pdfOf(model, fontStore2, opt) {
|
|
|
24962
25346
|
const to = l.href ? { A: { Type: "Action", S: "URI", URI: pdfLiteral(asciiUrl(l.href)) } } : { Dest: dest(l.to) };
|
|
24963
25347
|
if (!l.href && !to.Dest) continue;
|
|
24964
25348
|
const annot = doc.context.obj({ Type: "Annot", Subtype: "Link", F: 4, Rect: l.rect, Border: [0, 0, 0], ...to });
|
|
24965
|
-
if (tags) annot.set(PDFName3.of("Contents"),
|
|
25349
|
+
if (tags) annot.set(PDFName3.of("Contents"), PDFHexString5.fromText(String(l.text || l.tip || l.href || "Link")));
|
|
24966
25350
|
const ref2 = doc.context.register(annot);
|
|
24967
25351
|
if (tags) tags.annot(l.pi, l.ii, ref2, "link");
|
|
24968
25352
|
const annots = l.page.node.lookup(PDFName3.of("Annots"));
|
|
@@ -25001,110 +25385,14 @@ function fixedDate(opt) {
|
|
|
25001
25385
|
}
|
|
25002
25386
|
async function contentId(model, opt, when) {
|
|
25003
25387
|
const bytes = new TextEncoder().encode(JSON.stringify([{ ...model, stats: void 0 }, opt.title || "Report", opt.author || "", when.toISOString()]));
|
|
25004
|
-
const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
|
|
25005
|
-
return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
25006
|
-
}
|
|
25007
|
-
function fieldFont(it) {
|
|
25008
|
-
for (const d of it.draw) if (d.t === "text") {
|
|
25009
|
-
for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
|
|
25010
|
-
}
|
|
25011
|
-
return it.font;
|
|
25012
|
-
}
|
|
25013
|
-
function drawRun(c, run, x, y, size, pf, color2, spans2, texts) {
|
|
25014
|
-
const f4 = pf.embedder.font;
|
|
25015
|
-
const per = 1e3 / size;
|
|
25016
|
-
const span = (text2) => `/Span <</ActualText ${PDFHexString4.fromText(text2).toString()}>> BDC
|
|
25017
|
-
`;
|
|
25018
|
-
c.et();
|
|
25019
|
-
c.paint(color2, null);
|
|
25020
|
-
c.font(pf, size);
|
|
25021
|
-
if (!run.rtl) c.s += span(run.text);
|
|
25022
|
-
c.s += `BT ${n2(x)} ${n2(y)} Td
|
|
25023
|
-
`;
|
|
25024
|
-
let arr = "";
|
|
25025
|
-
let pen = 0, rise = 0;
|
|
25026
|
-
const flush = () => {
|
|
25027
|
-
if (arr) c.s += `[${arr}] TJ
|
|
25028
|
-
`;
|
|
25029
|
-
arr = "";
|
|
25030
|
-
};
|
|
25031
|
-
const all = run.glyphs;
|
|
25032
|
-
const adv = (id) => f4.getGlyph(id).advanceWidth;
|
|
25033
|
-
let g = all, quietAt = -1;
|
|
25034
|
-
if (run.rtl) {
|
|
25035
|
-
const hasBase = /* @__PURE__ */ new Set();
|
|
25036
|
-
for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
|
|
25037
|
-
const quiet = (i) => spans2?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
|
|
25038
|
-
g = [];
|
|
25039
|
-
for (const late of [false, true]) {
|
|
25040
|
-
if (late) quietAt = g.length;
|
|
25041
|
-
for (let i = 0; i < all.length; i += 4) if (quiet(i) === late) g.push(all[i], all[i + 1], all[i + 2], all[i + 3]);
|
|
25042
|
-
}
|
|
25043
|
-
if (quietAt === g.length) quietAt = -1;
|
|
25044
|
-
}
|
|
25045
|
-
const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
|
|
25046
|
-
let inSpan = false;
|
|
25047
|
-
for (let i = 0; i < g.length; i += 4) {
|
|
25048
|
-
const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
|
|
25049
|
-
if (i === quietAt) {
|
|
25050
|
-
flush();
|
|
25051
|
-
c.s += span("");
|
|
25052
|
-
inSpan = true;
|
|
25053
|
-
} else if (run.rtl && spans2?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
|
|
25054
|
-
flush();
|
|
25055
|
-
c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
|
|
25056
|
-
inSpan = true;
|
|
25057
|
-
}
|
|
25058
|
-
if (gy !== rise) {
|
|
25059
|
-
flush();
|
|
25060
|
-
c.s += `${n4(gy)} Ts
|
|
25061
|
-
`;
|
|
25062
|
-
rise = gy;
|
|
25063
|
-
}
|
|
25064
|
-
const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
|
|
25065
|
-
if (id === 0 && c.tagged) pen = gx;
|
|
25066
|
-
else {
|
|
25067
|
-
arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
|
|
25068
|
-
pen = gx + adv(id) * size / f4.unitsPerEm;
|
|
25069
|
-
}
|
|
25070
|
-
if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
|
|
25071
|
-
flush();
|
|
25072
|
-
c.s += "EMC\n";
|
|
25073
|
-
inSpan = false;
|
|
25074
|
-
}
|
|
25075
|
-
}
|
|
25076
|
-
flush();
|
|
25077
|
-
if (rise) c.s += "0 Ts\n";
|
|
25078
|
-
c.s += "ET\n";
|
|
25079
|
-
if (!run.rtl) c.s += "EMC\n";
|
|
25388
|
+
const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
|
|
25389
|
+
return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
25080
25390
|
}
|
|
25081
|
-
function
|
|
25082
|
-
const
|
|
25083
|
-
|
|
25084
|
-
for (let k = 0; k < starts.length; k++) {
|
|
25085
|
-
const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
|
|
25086
|
-
const ids = [];
|
|
25087
|
-
for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
|
|
25088
|
-
const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
|
|
25089
|
-
const rest2 = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
|
|
25090
|
-
const carrier = rest2 ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
|
|
25091
|
-
let ok = !rest2 || carrier !== void 0;
|
|
25092
|
-
const want = /* @__PURE__ */ new Map();
|
|
25093
|
-
for (const id of ids) {
|
|
25094
|
-
const t = own.get(id) ?? (id === carrier ? rest2 : "");
|
|
25095
|
-
if (want.has(id) && want.get(id) !== t) ok = false;
|
|
25096
|
-
want.set(id, t);
|
|
25097
|
-
}
|
|
25098
|
-
for (const [id, t] of want) {
|
|
25099
|
-
if (!out.has(id)) out.set(id, t);
|
|
25100
|
-
else if (out.get(id) !== t) ok = false;
|
|
25101
|
-
}
|
|
25102
|
-
if (!ok && run.rtl && spans2) {
|
|
25103
|
-
let s = spans2.get(run);
|
|
25104
|
-
if (!s) spans2.set(run, s = /* @__PURE__ */ new Set());
|
|
25105
|
-
s.add(starts[k]);
|
|
25106
|
-
}
|
|
25391
|
+
function fieldFont(it) {
|
|
25392
|
+
for (const d of it.draw) if (d.t === "text") {
|
|
25393
|
+
for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
|
|
25107
25394
|
}
|
|
25395
|
+
return it.font;
|
|
25108
25396
|
}
|
|
25109
25397
|
var pdfLiteral = (s) => PDFString4.of(String(s).replace(/[\\()]/g, "\\$&"));
|
|
25110
25398
|
function plainEncoding(pf) {
|
|
@@ -25122,7 +25410,7 @@ function plainEncoding(pf) {
|
|
|
25122
25410
|
}
|
|
25123
25411
|
return hex6;
|
|
25124
25412
|
};
|
|
25125
|
-
e2.encodeText = (text2) =>
|
|
25413
|
+
e2.encodeText = (text2) => PDFHexString5.of(e2.hexOf(text2));
|
|
25126
25414
|
e2.widthOfTextAtSize = (text2, size) => {
|
|
25127
25415
|
let w = 0;
|
|
25128
25416
|
for (const ch of text2) w += f4.glyphForCodePoint(
|
|
@@ -25213,7 +25501,7 @@ function addOutline(doc, bookmarks, dest) {
|
|
|
25213
25501
|
if (!Dest) continue;
|
|
25214
25502
|
const level = Math.max(0, Math.min(9, Number(b.level) || 0));
|
|
25215
25503
|
while (stack2[stack2.length - 1].level >= level) stack2.pop();
|
|
25216
|
-
const node2 = { ref: ctx.nextRef(), level, kids: [], Title:
|
|
25504
|
+
const node2 = { ref: ctx.nextRef(), level, kids: [], Title: PDFHexString5.fromText(b.label), Dest };
|
|
25217
25505
|
stack2[stack2.length - 1].kids.push(node2);
|
|
25218
25506
|
stack2.push(node2);
|
|
25219
25507
|
}
|
|
@@ -25244,216 +25532,6 @@ function subsetTag(bytes) {
|
|
|
25244
25532
|
}
|
|
25245
25533
|
return tag4;
|
|
25246
25534
|
}
|
|
25247
|
-
function insideClip(it, m) {
|
|
25248
|
-
const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
|
|
25249
|
-
return it.lines.every((l) => l.w != null && !l.runs && l.x >= k.x && l.x + l.w <= k.x + k.w && l.y - asc >= k.y && l.y + desc <= k.y + k.h);
|
|
25250
|
-
}
|
|
25251
|
-
var Content = class {
|
|
25252
|
-
constructor(shared) {
|
|
25253
|
-
this.shared = shared;
|
|
25254
|
-
this._s = "";
|
|
25255
|
-
this.bt = false;
|
|
25256
|
-
this.tx = 0;
|
|
25257
|
-
this.ty = 0;
|
|
25258
|
-
this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
|
|
25259
|
-
this.saved = [];
|
|
25260
|
-
this.lines = null;
|
|
25261
|
-
this.tagged = false;
|
|
25262
|
-
}
|
|
25263
|
-
/**
|
|
25264
|
-
* The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
|
|
25265
|
-
* of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
|
|
25266
|
-
*/
|
|
25267
|
-
get s() {
|
|
25268
|
-
this.flushLines();
|
|
25269
|
-
return this._s;
|
|
25270
|
-
}
|
|
25271
|
-
set s(v) {
|
|
25272
|
-
this._s = v;
|
|
25273
|
-
}
|
|
25274
|
-
/**
|
|
25275
|
-
* A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
|
|
25276
|
-
* texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
|
|
25277
|
-
* ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
|
|
25278
|
-
*/
|
|
25279
|
-
line(stroke, w, dash, x1, y1, x2, y2) {
|
|
25280
|
-
if (this.tagged) {
|
|
25281
|
-
this.paint(null, stroke, w, dash);
|
|
25282
|
-
this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
|
|
25283
|
-
`;
|
|
25284
|
-
return;
|
|
25285
|
-
}
|
|
25286
|
-
const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
|
|
25287
|
-
if (this.lines && this.lines.key !== key) this.flushLines();
|
|
25288
|
-
this.lines ||= { key, stroke, w, dash, segs: [] };
|
|
25289
|
-
const segs = this.lines.segs, last = segs[segs.length - 1];
|
|
25290
|
-
const eq = (a, b) => Math.abs(a - b) < 5e-3;
|
|
25291
|
-
if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
|
|
25292
|
-
else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
|
|
25293
|
-
else segs.push([x1, y1, x2, y2]);
|
|
25294
|
-
}
|
|
25295
|
-
flushLines() {
|
|
25296
|
-
const L = this.lines;
|
|
25297
|
-
if (!L) return;
|
|
25298
|
-
this.lines = null;
|
|
25299
|
-
this.et();
|
|
25300
|
-
this.paint(null, L.stroke, L.w, L.dash);
|
|
25301
|
-
const g = L.segs;
|
|
25302
|
-
const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
|
|
25303
|
-
if (dy && g.every((q3, i) => q3[1] === q3[3] && n2(q3[0]) === n2(g[0][0]) && n2(q3[2]) === n2(g[0][2]) && Math.abs(q3[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
|
|
25304
|
-
const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
|
|
25305
|
-
`;
|
|
25306
|
-
this._s += `q
|
|
25307
|
-
${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
|
|
25308
|
-
`;
|
|
25309
|
-
return;
|
|
25310
|
-
}
|
|
25311
|
-
this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n";
|
|
25312
|
-
}
|
|
25313
|
-
q() {
|
|
25314
|
-
this.et();
|
|
25315
|
-
this._s += "q\n";
|
|
25316
|
-
this.saved.push({ ...this.st });
|
|
25317
|
-
}
|
|
25318
|
-
Q() {
|
|
25319
|
-
this.et();
|
|
25320
|
-
this._s += "Q\n";
|
|
25321
|
-
this.st = this.saved.pop();
|
|
25322
|
-
}
|
|
25323
|
-
/**
|
|
25324
|
-
* A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
|
|
25325
|
-
* last (in whole hundredths, so nothing drifts): most of a table page is these.
|
|
25326
|
-
* @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
|
|
25327
|
-
*/
|
|
25328
|
-
text(pf, size, color2, x, y, str, array = false) {
|
|
25329
|
-
this.setPaint(color2, null);
|
|
25330
|
-
this.setFont(pf, size);
|
|
25331
|
-
const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
|
|
25332
|
-
if (!this.bt) {
|
|
25333
|
-
this._s += "BT\n";
|
|
25334
|
-
this.bt = true;
|
|
25335
|
-
this.tx = 0;
|
|
25336
|
-
this.ty = 0;
|
|
25337
|
-
}
|
|
25338
|
-
this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
|
|
25339
|
-
` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
|
|
25340
|
-
`;
|
|
25341
|
-
this.tx = X;
|
|
25342
|
-
this.ty = Y;
|
|
25343
|
-
}
|
|
25344
|
-
/** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
|
|
25345
|
-
et() {
|
|
25346
|
-
if (this.bt) {
|
|
25347
|
-
this._s += "ET\n";
|
|
25348
|
-
this.bt = false;
|
|
25349
|
-
}
|
|
25350
|
-
if (this.lines) this.flushLines();
|
|
25351
|
-
}
|
|
25352
|
-
lineWidth(w) {
|
|
25353
|
-
if (this.lines) this.flushLines();
|
|
25354
|
-
this.setLineWidth(w);
|
|
25355
|
-
}
|
|
25356
|
-
setLineWidth(w) {
|
|
25357
|
-
if (this.st.lw !== w) {
|
|
25358
|
-
this._s += `${n3(w)} w
|
|
25359
|
-
`;
|
|
25360
|
-
this.st.lw = w;
|
|
25361
|
-
}
|
|
25362
|
-
}
|
|
25363
|
-
/** the graphics state that sets these opacities, or undefined when they are set already */
|
|
25364
|
-
gsFor(ca, CA) {
|
|
25365
|
-
return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
|
|
25366
|
-
}
|
|
25367
|
-
alpha(ca, CA) {
|
|
25368
|
-
if (this.lines) this.flushLines();
|
|
25369
|
-
this.setAlpha(ca, CA);
|
|
25370
|
-
}
|
|
25371
|
-
setAlpha(ca, CA) {
|
|
25372
|
-
const g = this.gsFor(ca, CA);
|
|
25373
|
-
if (g) {
|
|
25374
|
-
this._s += `/${g} gs
|
|
25375
|
-
`;
|
|
25376
|
-
this.st.ca = ca;
|
|
25377
|
-
this.st.CA = CA;
|
|
25378
|
-
}
|
|
25379
|
-
}
|
|
25380
|
-
/** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
|
|
25381
|
-
paint(fill3, stroke, w = 1, dash = null) {
|
|
25382
|
-
if (this.lines) this.flushLines();
|
|
25383
|
-
this.setPaint(fill3, stroke, w, dash);
|
|
25384
|
-
}
|
|
25385
|
-
setPaint(fill3, stroke, w = 1, dash = null) {
|
|
25386
|
-
const st = this.st;
|
|
25387
|
-
if (fill3 && fill3.rgb !== st.fill) {
|
|
25388
|
-
this._s += `${fill3.rgb} rg
|
|
25389
|
-
`;
|
|
25390
|
-
st.fill = fill3.rgb;
|
|
25391
|
-
}
|
|
25392
|
-
if (stroke) {
|
|
25393
|
-
if (stroke.rgb !== st.stroke) {
|
|
25394
|
-
this._s += `${stroke.rgb} RG
|
|
25395
|
-
`;
|
|
25396
|
-
st.stroke = stroke.rgb;
|
|
25397
|
-
}
|
|
25398
|
-
this.setLineWidth(w);
|
|
25399
|
-
const d = `[${(dash || []).map(n3).join(" ")}] 0`;
|
|
25400
|
-
if (d !== st.dash) {
|
|
25401
|
-
this._s += `${d} d
|
|
25402
|
-
`;
|
|
25403
|
-
st.dash = d;
|
|
25404
|
-
}
|
|
25405
|
-
}
|
|
25406
|
-
this.setAlpha(fill3 ? fill3.opacity : st.ca, stroke ? stroke.opacity : st.CA);
|
|
25407
|
-
}
|
|
25408
|
-
font(pf, size) {
|
|
25409
|
-
if (this.lines) this.flushLines();
|
|
25410
|
-
this.setFont(pf, size);
|
|
25411
|
-
}
|
|
25412
|
-
setFont(pf, size) {
|
|
25413
|
-
const name = this.shared.font(pf);
|
|
25414
|
-
if (name !== this.st.font || size !== this.st.size) {
|
|
25415
|
-
this._s += `/${name} ${n3(size)} Tf
|
|
25416
|
-
`;
|
|
25417
|
-
this.st.font = name;
|
|
25418
|
-
this.st.size = size;
|
|
25419
|
-
}
|
|
25420
|
-
}
|
|
25421
|
-
};
|
|
25422
|
-
function latin1(s) {
|
|
25423
|
-
const B = (
|
|
25424
|
-
/** @type {any} */
|
|
25425
|
-
globalThis.Buffer
|
|
25426
|
-
);
|
|
25427
|
-
if (B) return B.from(s, "latin1");
|
|
25428
|
-
const out = new Uint8Array(s.length);
|
|
25429
|
-
for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
|
|
25430
|
-
return out;
|
|
25431
|
-
}
|
|
25432
|
-
async function deflate(bytes) {
|
|
25433
|
-
if (zslots.free > 0) zslots.free--;
|
|
25434
|
-
else await new Promise((ok) => zslots.wait.push(ok));
|
|
25435
|
-
try {
|
|
25436
|
-
return await deflateNow(bytes);
|
|
25437
|
-
} finally {
|
|
25438
|
-
const next = zslots.wait.shift();
|
|
25439
|
-
if (next) next();
|
|
25440
|
-
else zslots.free++;
|
|
25441
|
-
}
|
|
25442
|
-
}
|
|
25443
|
-
var zslots = { free: 4, wait: (
|
|
25444
|
-
/** @type {(() => void)[]} */
|
|
25445
|
-
[]
|
|
25446
|
-
) };
|
|
25447
|
-
var NODE_ZLIB = (
|
|
25448
|
-
/** @type {any} */
|
|
25449
|
-
globalThis.process?.getBuiltinModule?.("node:zlib")
|
|
25450
|
-
);
|
|
25451
|
-
async function deflateNow(bytes) {
|
|
25452
|
-
const zlib = NODE_ZLIB;
|
|
25453
|
-
if (zlib) return new Promise((ok, fail2) => zlib.deflate(bytes, { level: 9 }, (e2, z) => e2 ? fail2(e2) : ok(z)));
|
|
25454
|
-
if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
|
|
25455
|
-
return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
|
25456
|
-
}
|
|
25457
25535
|
function roundRect(x, y, w, h, r) {
|
|
25458
25536
|
r = Math.min(r, w / 2, h / 2);
|
|
25459
25537
|
return `M ${x + r} ${y} H ${x + w - r} A ${r} ${r} 0 0 1 ${x + w} ${y + r} V ${y + h - r} A ${r} ${r} 0 0 1 ${x + w - r} ${y + h} H ${x + r} A ${r} ${r} 0 0 1 ${x} ${y + h - r} V ${y + r} A ${r} ${r} 0 0 1 ${x + r} ${y} Z`;
|
|
@@ -25503,6 +25581,7 @@ function createSubsetter(loadWasm) {
|
|
|
25503
25581
|
for (const g of opt.glyphs) x.hb_set_add(gs, g);
|
|
25504
25582
|
}
|
|
25505
25583
|
x.hb_subset_input_pin_all_axes_to_default(input, face);
|
|
25584
|
+
x.hb_subset_input_pin_axis_location(input, face, tag3("wght"), opt.weight ?? 400);
|
|
25506
25585
|
const sub = x.hb_subset_or_fail(face, input);
|
|
25507
25586
|
if (!sub) throw new Error("HarfBuzz: subsetting failed");
|
|
25508
25587
|
const res = x.hb_face_reference_blob(sub);
|
|
@@ -25523,6 +25602,7 @@ function createSubsetter(loadWasm) {
|
|
|
25523
25602
|
|
|
25524
25603
|
// src/exporters/htmldata.js
|
|
25525
25604
|
init_format();
|
|
25605
|
+
var dateKey = (d, tz) => tz ? toWall(d, tz) : Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
|
|
25526
25606
|
var MAX_DATA_ROWS = 2e4;
|
|
25527
25607
|
var DATA_STRINGS = { pages: "Pages", tables: "Tables", all: "All", filter: "Filter", toggle: "Show or hide the rows of this group", sortAsc: "Sort ascending", sortDesc: "Sort descending" };
|
|
25528
25608
|
function tablesData(model, o = {}) {
|
|
@@ -25545,7 +25625,7 @@ function tablesData(model, o = {}) {
|
|
|
25545
25625
|
rows: r.rows.map((row) => ({
|
|
25546
25626
|
k: row.kind,
|
|
25547
25627
|
l: row.level || 0,
|
|
25548
|
-
c: row.cells.filter((c) => c.colIndex >= 0).map((c) => [c.colIndex, String(show(c) ?? ""), c.value instanceof Date ? c.value.
|
|
25628
|
+
c: row.cells.filter((c) => c.colIndex >= 0).map((c) => [c.colIndex, String(show(c) ?? ""), c.value instanceof Date ? dateKey(c.value, model.timeZone || void 0) : typeof c.value === "number" ? c.value : String(c.value ?? "").toLowerCase(), c.span || 1])
|
|
25549
25629
|
}))
|
|
25550
25630
|
}));
|
|
25551
25631
|
}
|
|
@@ -25677,13 +25757,29 @@ async function cspHash(text2) {
|
|
|
25677
25757
|
}
|
|
25678
25758
|
|
|
25679
25759
|
// src/exporters/html.js
|
|
25680
|
-
function exportHtml(model,
|
|
25760
|
+
function exportHtml(model, options, legacyOpt) {
|
|
25761
|
+
const isStore = (x) => !!x && typeof x.load === "function" && typeof x.get === "function" && x.bytes instanceof Map;
|
|
25762
|
+
let fontStore2, opt;
|
|
25763
|
+
if (isStore(options)) {
|
|
25764
|
+
if (!warnedLegacy) {
|
|
25765
|
+
warnedLegacy = true;
|
|
25766
|
+
console.warn("[reportwright] DEPRECATED: exportHtml(model, fontStore, options) is replaced by exportHtml(model, { fonts: fontStore, ...options }); the old form is removed in 0.9");
|
|
25767
|
+
}
|
|
25768
|
+
fontStore2 = options;
|
|
25769
|
+
opt = legacyOpt || {};
|
|
25770
|
+
} else {
|
|
25771
|
+
opt = /** @type {any} */
|
|
25772
|
+
options || {};
|
|
25773
|
+
fontStore2 = opt.fonts || opt.fontStore;
|
|
25774
|
+
if (!isStore(fontStore2)) throw new TypeError("exportHtml(model, { fonts }): fonts must be a FontStore (defaultFontStore() or new FontStore(loader)), got " + (fontStore2 === void 0 ? "nothing" : typeof fontStore2));
|
|
25775
|
+
}
|
|
25681
25776
|
return withDeadline(
|
|
25682
25777
|
htmlOf(model, fontStore2, opt),
|
|
25683
25778
|
/** @type {any} */
|
|
25684
25779
|
opt.timeoutMs
|
|
25685
25780
|
);
|
|
25686
25781
|
}
|
|
25782
|
+
var warnedLegacy = false;
|
|
25687
25783
|
async function htmlOf(model, fontStore2, opt) {
|
|
25688
25784
|
const used = /* @__PURE__ */ new Map();
|
|
25689
25785
|
const layout = /* @__PURE__ */ new Set();
|
|
@@ -26435,9 +26531,22 @@ async function xlsxOf(model, opt) {
|
|
|
26435
26531
|
}
|
|
26436
26532
|
|
|
26437
26533
|
// src/exporters/docx.js
|
|
26438
|
-
import {
|
|
26534
|
+
import { Zip, ZipDeflate, strToU8 as strToU83 } from "fflate";
|
|
26439
26535
|
var TW = 20;
|
|
26440
26536
|
var EMU = 12700;
|
|
26537
|
+
var XML_CHUNK = 4 * 1024 * 1024;
|
|
26538
|
+
function slices(s, max) {
|
|
26539
|
+
const out = [];
|
|
26540
|
+
let i = 0;
|
|
26541
|
+
while (s.length - i > max) {
|
|
26542
|
+
const j = s.indexOf(">", i + max);
|
|
26543
|
+
if (j < 0) break;
|
|
26544
|
+
out.push(s.slice(i, j + 1));
|
|
26545
|
+
i = j + 1;
|
|
26546
|
+
}
|
|
26547
|
+
out.push(s.slice(i));
|
|
26548
|
+
return out;
|
|
26549
|
+
}
|
|
26441
26550
|
var esc3 = (s) => String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
26442
26551
|
var hex5 = (c) => {
|
|
26443
26552
|
const m = /^#?([0-9a-f]{6})$/i.exec(String(c || "").trim());
|
|
@@ -26581,9 +26690,9 @@ async function docxOf(model, opt) {
|
|
|
26581
26690
|
const margin = 18;
|
|
26582
26691
|
const media = [];
|
|
26583
26692
|
let docPr = 0;
|
|
26584
|
-
const addMedia = (
|
|
26693
|
+
const addMedia = (bytes2, ext) => {
|
|
26585
26694
|
const rid = `rIdm${media.length + 1}`;
|
|
26586
|
-
media.push({ name: `image${media.length + 1}.${ext}`, bytes, rid });
|
|
26695
|
+
media.push({ name: `image${media.length + 1}.${ext}`, bytes: bytes2, rid });
|
|
26587
26696
|
return rid;
|
|
26588
26697
|
};
|
|
26589
26698
|
const pictureRun = (pic, alt) => {
|
|
@@ -26647,7 +26756,7 @@ async function docxOf(model, opt) {
|
|
|
26647
26756
|
}
|
|
26648
26757
|
for (const f4 of figs) if (!f4.used) blocks.push({ kind: "fig", y: f4.box.y, x: f4.box.x, fig: f4 });
|
|
26649
26758
|
blocks.sort((a, b) => a.y - b.y || a.x - b.x);
|
|
26650
|
-
let
|
|
26759
|
+
let xml2 = "";
|
|
26651
26760
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
26652
26761
|
const b = blocks[bi];
|
|
26653
26762
|
if (b.kind === "fig") {
|
|
@@ -26662,7 +26771,7 @@ async function docxOf(model, opt) {
|
|
|
26662
26771
|
right = pic.x + pic.w;
|
|
26663
26772
|
}
|
|
26664
26773
|
const first = row[0];
|
|
26665
|
-
|
|
26774
|
+
xml2 += `<w:p><w:pPr><w:spacing w:before="0" w:after="80"/>${Math.abs(first.x - margin) > 0.5 ? `<w:ind w:left="${Math.round(Math.max(-margin, first.x - margin) * TW)}"/>` : ""}</w:pPr>${runs}</w:p>`;
|
|
26666
26775
|
} else if (b.kind === "table") {
|
|
26667
26776
|
const pics = /* @__PURE__ */ new Map();
|
|
26668
26777
|
for (const [k, v] of visuals.get(b.key) || []) {
|
|
@@ -26670,19 +26779,19 @@ async function docxOf(model, opt) {
|
|
|
26670
26779
|
const svg = figureSvg({ items: v.items, box: v.box }, opt.fontStore);
|
|
26671
26780
|
pics.set(k, pictureRun({ svg, png: await rasterize(svg, v.box.w, v.box.h, picOpt), w: v.box.w, h: v.box.h }, "Chart in a table cell"));
|
|
26672
26781
|
}
|
|
26673
|
-
|
|
26674
|
-
} else if (b.kind === "rich")
|
|
26782
|
+
xml2 += table(b.cells, b.x - margin, pics);
|
|
26783
|
+
} else if (b.kind === "rich") xml2 += richPara(b.items, b.x - margin);
|
|
26675
26784
|
else {
|
|
26676
26785
|
const row = [b];
|
|
26677
26786
|
const top = (t) => t.it.clip?.y ?? t.y - t.it.size;
|
|
26678
26787
|
while (blocks[bi + 1]?.kind === "text" && Math.abs(top(blocks[bi + 1]) - top(b)) < 3 && blocks[bi + 1].it.clip && b.it.clip) row.push(blocks[++bi]);
|
|
26679
26788
|
row.sort((p, q3) => p.it.clip.x - q3.it.clip.x);
|
|
26680
26789
|
const apart = row.every((r, k) => k === 0 || r.it.clip.x >= row[k - 1].it.clip.x + row[k - 1].it.clip.w - 0.5);
|
|
26681
|
-
if (row.length > 1 && apart)
|
|
26682
|
-
else for (const r of row)
|
|
26790
|
+
if (row.length > 1 && apart) xml2 += layoutRow(row, margin);
|
|
26791
|
+
else for (const r of row) xml2 += para(r.it, (r.it.clip?.x ?? r.x) - margin, r.decor);
|
|
26683
26792
|
}
|
|
26684
26793
|
}
|
|
26685
|
-
body.push(
|
|
26794
|
+
body.push(xml2);
|
|
26686
26795
|
}
|
|
26687
26796
|
const M = margin * TW, V = 36 * TW;
|
|
26688
26797
|
const sectPr = (pg) => {
|
|
@@ -26690,17 +26799,39 @@ async function docxOf(model, opt) {
|
|
|
26690
26799
|
return `<w:sectPr><w:pgSz w:w="${W2}" w:h="${H}"${W2 > H ? ' w:orient="landscape"' : ""}/><w:pgMar w:top="${V}" w:right="${M}" w:bottom="${V}" w:left="${M}" w:header="0" w:footer="0" w:gutter="0"/></w:sectPr>`;
|
|
26691
26800
|
};
|
|
26692
26801
|
const sizeOf = (pg) => `${pg.width ?? model.width}x${pg.height ?? model.height}`;
|
|
26693
|
-
|
|
26802
|
+
const zipOut = [];
|
|
26803
|
+
const zip = new Zip((err, data) => {
|
|
26804
|
+
if (err) throw err;
|
|
26805
|
+
zipOut.push(data);
|
|
26806
|
+
});
|
|
26807
|
+
const put = (name, bytes2) => {
|
|
26808
|
+
const e2 = new ZipDeflate(name, { level: 6 });
|
|
26809
|
+
zip.add(e2);
|
|
26810
|
+
e2.push(bytes2, true);
|
|
26811
|
+
};
|
|
26812
|
+
const parts = [];
|
|
26813
|
+
const max = opt.xmlChunk || XML_CHUNK;
|
|
26814
|
+
let buf = "";
|
|
26815
|
+
const write = (str) => {
|
|
26816
|
+
for (const p of slices(str, max)) {
|
|
26817
|
+
if (buf.length + p.length > max) {
|
|
26818
|
+
parts.push(buf);
|
|
26819
|
+
buf = "";
|
|
26820
|
+
}
|
|
26821
|
+
buf += p;
|
|
26822
|
+
}
|
|
26823
|
+
};
|
|
26824
|
+
write(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26825
|
+
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><w:body>`);
|
|
26694
26826
|
model.pages.forEach((pg, i) => {
|
|
26695
|
-
|
|
26827
|
+
write(body[i]);
|
|
26696
26828
|
const next = model.pages[i + 1];
|
|
26697
26829
|
if (!next) return;
|
|
26698
|
-
|
|
26830
|
+
write(sizeOf(next) !== sizeOf(pg) ? `<w:p><w:pPr>${sectPr(pg)}</w:pPr></w:p>` : '<w:p><w:pPr><w:pageBreakBefore/><w:spacing w:before="0" w:after="0" w:line="20" w:lineRule="exact"/><w:rPr><w:sz w:val="2"/></w:rPr></w:pPr></w:p>');
|
|
26699
26831
|
});
|
|
26700
26832
|
const last = model.pages[model.pages.length - 1] || {};
|
|
26701
|
-
|
|
26702
|
-
|
|
26703
|
-
last)}</w:body></w:document>`;
|
|
26833
|
+
write(`${sectPr(last)}</w:body></w:document>`);
|
|
26834
|
+
parts.push(buf);
|
|
26704
26835
|
const lang = `<w:lang w:val="${esc3(opt.lang || model.locale || "en-US")}"/>`;
|
|
26705
26836
|
const headings = [28, 24, 22, 20, 18, 18].map((sz, i) => `<w:style w:type="paragraph" w:styleId="Heading${i + 1}"><w:name w:val="heading ${i + 1}"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:qFormat/><w:pPr><w:keepNext/><w:outlineLvl w:val="${i}"/></w:pPr><w:rPr><w:b/><w:sz w:val="${sz}"/></w:rPr></w:style>`).join("");
|
|
26706
26837
|
const styles = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -26710,24 +26841,32 @@ name w:val="Normal"/></w:style>${headings}</w:styles>`;
|
|
|
26710
26841
|
const core = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26711
26842
|
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title>${esc3(opt.title || model.name || "Report")}</dc:title>${opt.author ? `<dc:creator>${esc3(opt.author)}</dc:creator>` : ""}<dcterms:created xsi:type=\
|
|
26712
26843
|
"dcterms:W3CDTF">${now}</dcterms:created></cp:coreProperties>`;
|
|
26713
|
-
|
|
26714
|
-
"[Content_Types].xml": strToU83(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26844
|
+
put("[Content_Types].xml", strToU83(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26715
26845
|
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Default Extension="png" ContentType="image/png"/><Default Extension="jpeg" ContentType="image/jpeg"/><Default Extension="svg" ContentType="image/svg+xml"/><Override Part\
|
|
26716
|
-
Name="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/></Types>`)
|
|
26717
|
-
|
|
26718
|
-
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/></Relationships>`)
|
|
26719
|
-
|
|
26720
|
-
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>${media.map((m) => `<Relationship Id="${m.rid}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/${m.name}"/>`).join("")}</Relationships>`)
|
|
26721
|
-
|
|
26722
|
-
|
|
26723
|
-
|
|
26724
|
-
|
|
26725
|
-
|
|
26726
|
-
|
|
26846
|
+
Name="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/></Types>`));
|
|
26847
|
+
put("_rels/.rels", strToU83(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26848
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/></Relationships>`));
|
|
26849
|
+
put("word/_rels/document.xml.rels", strToU83(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26850
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>${media.map((m) => `<Relationship Id="${m.rid}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/${m.name}"/>`).join("")}</Relationships>`));
|
|
26851
|
+
const doc = new ZipDeflate("word/document.xml", { level: 6 });
|
|
26852
|
+
zip.add(doc);
|
|
26853
|
+
for (const p of parts) doc.push(strToU83(p), false);
|
|
26854
|
+
doc.push(new Uint8Array(0), true);
|
|
26855
|
+
put("word/styles.xml", strToU83(styles));
|
|
26856
|
+
put("docProps/core.xml", strToU83(core));
|
|
26857
|
+
for (const m of media) put(`word/media/${m.name}`, m.bytes);
|
|
26858
|
+
zip.end();
|
|
26859
|
+
const total = zipOut.reduce((n5, c) => n5 + c.length, 0), bytes = new Uint8Array(total);
|
|
26860
|
+
let at2 = 0;
|
|
26861
|
+
for (const c of zipOut) {
|
|
26862
|
+
bytes.set(c, at2);
|
|
26863
|
+
at2 += c.length;
|
|
26864
|
+
}
|
|
26865
|
+
return bytes;
|
|
26727
26866
|
}
|
|
26728
26867
|
|
|
26729
26868
|
// src/exporters/pptx.js
|
|
26730
|
-
import { zipSync as
|
|
26869
|
+
import { zipSync as zipSync3, strToU8 as strToU84 } from "fflate";
|
|
26731
26870
|
var EMU2 = 12700;
|
|
26732
26871
|
var e = (v) => Math.round(v * EMU2);
|
|
26733
26872
|
var esc4 = (s) => String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f]/g, "");
|
|
@@ -26910,7 +27049,7 @@ rops/core.xml"/></Relationships>`);
|
|
|
26910
27049
|
="svg" ContentType="image/svg+xml"/><Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/><Override PartName="/ppt/slideMasters/slideMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/><Override PartName="/ppt/slideLayouts/slideLayout1.xml" ContentType="applic\
|
|
26911
27050
|
ation/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/><Override PartName="/ppt/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>${slides.map((n5) => `<Override PartName="/ppt/slides/slide${n5}.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>`).join("")}<Override PartName="/docProps/core.xml" Conte\
|
|
26912
27051
|
ntType="application/vnd.openxmlformats-package.core-properties+xml"/></Types>`);
|
|
26913
|
-
return
|
|
27052
|
+
return zipSync3(files, { level: 6 });
|
|
26914
27053
|
}
|
|
26915
27054
|
var THEME = `${XML2}<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="ReportWright"><a:themeElements><a:clrScheme name="ReportWright"><a:dk1><a:srgbClr val="000000"/></a:dk1><a:lt1><a:srgbClr val="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="1F2328"/></a:dk2><a:lt2><a:srgbClr val="E7E6E6"/></a:lt2><a:accent1><a:srgbClr val="2563EB"/></a:accent1><a:accent2><a:srgbClr val="F5\
|
|
26916
27055
|
9E0B"/></a:accent2><a:accent3><a:srgbClr val="16A34A"/></a:accent3><a:accent4><a:srgbClr val="DC2626"/></a:accent4><a:accent5><a:srgbClr val="7C3AED"/></a:accent5><a:accent6><a:srgbClr val="0891B2"/></a:accent6><a:hlink><a:srgbClr val="0563C1"/></a:hlink><a:folHlink><a:srgbClr val="954F72"/></a:folHlink></a:clrScheme><a:fontScheme name="ReportWright"><a:majorFont><a:latin typeface="Inter"/><a:ea t\
|
|
@@ -26930,6 +27069,7 @@ pw test [folder] [--update] [--layout]
|
|
|
26930
27069
|
render every <folder>/__tests__/*.test.json case and compare it with its snapshot
|
|
26931
27070
|
(the words; --layout: the layout, see the CLI README)
|
|
26932
27071
|
pw diff <old.pw.json> <new.pw.json> [-p name=value]… [-d source=data.json]… [--base URL]
|
|
27072
|
+
SERVER ONLY (the self-hosted app, run in its folder; the npm CLI does not include these):
|
|
26933
27073
|
pw audit verify [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--json] [--public-key file.pem]
|
|
26934
27074
|
check the server's audit log (hash chain, signed checkpoints); run it in the app
|
|
26935
27075
|
folder with the server's PW_STORAGE and PW_AUDIT_KEY / PW_SESSION_SECRET
|
|
@@ -26946,7 +27086,7 @@ pw audit rekey --old-secret S | --old-key file.pem
|
|
|
26946
27086
|
--ua an accessible PDF (PDF/UA-1; with --pdfa, PDF/A-2a) --values Excel totals as values, not formulas
|
|
26947
27087
|
--layout CSV of the printed layout (every table, group lines, totals), not just the data
|
|
26948
27088
|
--static an HTML file without its Tables view (sort, groups, filter)
|
|
26949
|
-
pw migrate-storage --to <url> [--from file|<url>]
|
|
27089
|
+
pw migrate-storage --to <url> [--from file|<url>] (SERVER ONLY, as above)
|
|
26950
27090
|
copy everything (reports and their versions, users, grants, folders, schedules,
|
|
26951
27091
|
jobs, fonts, settings, blobs, the audit log) from one storage to another, e.g. the
|
|
26952
27092
|
files in this folder to sqlite:/srv/pw.db or postgres://…; stop the server first
|
|
@@ -26992,7 +27132,9 @@ var baseHost = (base, internal) => {
|
|
|
26992
27132
|
};
|
|
26993
27133
|
async function renderModel(def, { parameters = {}, data, base, internal = false, now, state, file, exportData = true, dataOnly = false } = {}) {
|
|
26994
27134
|
try {
|
|
26995
|
-
|
|
27135
|
+
const m = await render(withData(def, data), { fontStore, parameters, exportData, dataOnly, baseUrl: base, allowHosts: baseHost(base, internal), now: now ? new Date(now) : void 0, ...state ? { state } : {}, ...file ? { loadReport: siblingLoader(file) } : {} });
|
|
27136
|
+
const seen = /* @__PURE__ */ new Set();
|
|
27137
|
+
return { ...m, warnings: m.warnings.filter((w) => !seen.has(w.toLowerCase()) && seen.add(w.toLowerCase())) };
|
|
26996
27138
|
} catch (e2) {
|
|
26997
27139
|
const relative = /fetch|URL|Invalid URL/i.test(e2.message) && !base;
|
|
26998
27140
|
fail(`${e2.message}${relative ? "\n A data source needs a server: pass --base http://localhost:3000, or push the data with -d source=file.json." : ""}`);
|
|
@@ -27057,7 +27199,7 @@ async function cmdRender(args) {
|
|
|
27057
27199
|
if (encrypt && values.pdfa) usage("a PDF/A file cannot have a password");
|
|
27058
27200
|
if (values.ua && fmt2 !== "pdf") usage("--ua applies to -f pdf only");
|
|
27059
27201
|
if (fmt2 === "pdf") bytes = await exportPdf(model, fontStore, { title: def.name, subset, encrypt, drillBase: values.base, pdfa: values.pdfa ? { icc: fs.readFileSync(path.join(PUB, "icc", "sRGB-v2-magic.icc")) } : void 0, tagged: values.ua ? { lang: def.locale || "en" } : void 0 });
|
|
27060
|
-
else if (fmt2 === "html") bytes = await exportHtml(model, fontStore,
|
|
27202
|
+
else if (fmt2 === "html") bytes = await exportHtml(model, { fonts: fontStore, title: def.name, subset, static: !!values.static, locale: def.locale, currency: def.currency });
|
|
27061
27203
|
else if (fmt2 === "csv") bytes = exportCsv(model, { locale: def.locale, currency: def.currency, layout: !!values.layout });
|
|
27062
27204
|
else if (fmt2 === "xlsx") bytes = await exportXlsx(model, { currency: def.currency, title: def.name, formulas: !values.values, fontStore });
|
|
27063
27205
|
else if (fmt2 === "docx") bytes = await exportDocx(model, { title: def.name, lang: def.locale, fontStore });
|