@uurtech/jdf-cli 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +65 -9
- package/dist/jdf-schema.json +12 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1488,7 +1488,8 @@ function merge(para, meta, pageWmm) {
|
|
|
1488
1488
|
const style = { ...first.style ?? {}, lineHeight, ...indent > 0.5 ? { textIndent: Math.round(indent * 100) / 100 } : {} };
|
|
1489
1489
|
const allText = para.every((e) => e.type === "text" && !e.link);
|
|
1490
1490
|
const y = Math.max(0, first.position.y - (lineHeight - 1) / 2 * lineH);
|
|
1491
|
-
const
|
|
1491
|
+
const height = Math.round(para.length * lineHeight * lineH * 100) / 100;
|
|
1492
|
+
const base = { position: { x, y: Math.round(y * 100) / 100 }, width: Math.round(width * 100) / 100, height, style };
|
|
1492
1493
|
if (allText) {
|
|
1493
1494
|
const content = para.map((e) => String(e.content ?? "").trim().replace(/[ \t]+/g, " ")).join(joiner());
|
|
1494
1495
|
const { height: _hh2, ...firstRest } = first;
|
|
@@ -1767,6 +1768,11 @@ async function walkOps(page, OPS, viewport) {
|
|
|
1767
1768
|
clip: void 0,
|
|
1768
1769
|
fill: "#000000",
|
|
1769
1770
|
stroke: "#000000",
|
|
1771
|
+
// Blend mode from the ExtGState (BM). JDF has no blend modes; a multiply /
|
|
1772
|
+
// darken layer is approximated by opacity ∝ how dark it is (a light-grey
|
|
1773
|
+
// "light streak" over a blue banner becomes nearly transparent instead of
|
|
1774
|
+
// an opaque grey blob), a screen / lighten layer by how light it is.
|
|
1775
|
+
blend: "normal",
|
|
1770
1776
|
lineWidth: 1,
|
|
1771
1777
|
fillAlpha: 1,
|
|
1772
1778
|
strokeAlpha: 1,
|
|
@@ -1780,6 +1786,24 @@ async function walkOps(page, OPS, viewport) {
|
|
|
1780
1786
|
rise: 0
|
|
1781
1787
|
};
|
|
1782
1788
|
const snapshot = () => ({ ...gs, ctm: [...gs.ctm] });
|
|
1789
|
+
const luma = (hex) => {
|
|
1790
|
+
const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex || "");
|
|
1791
|
+
return m ? (0.2126 * parseInt(m[1], 16) + 0.7152 * parseInt(m[2], 16) + 0.0722 * parseInt(m[3], 16)) / 255 : 0.5;
|
|
1792
|
+
};
|
|
1793
|
+
const groupStack = [];
|
|
1794
|
+
const isNormal = (b) => b === "normal" || b === "source-over" || b === "compatible";
|
|
1795
|
+
const fillOpacity = (color) => {
|
|
1796
|
+
let alpha = gs.fillAlpha;
|
|
1797
|
+
let b = gs.blend;
|
|
1798
|
+
for (let q = groupStack.length - 1; q >= 0; q--) {
|
|
1799
|
+
alpha *= groupStack[q].alpha;
|
|
1800
|
+
if (isNormal(b)) b = groupStack[q].blend;
|
|
1801
|
+
}
|
|
1802
|
+
const l = luma(color ?? gs.fill);
|
|
1803
|
+
if (b === "multiply" || b === "darken" || b === "color-burn" || b === "colorburn") return alpha * Math.max(0.08, 1 - l);
|
|
1804
|
+
if (b === "screen" || b === "lighten" || b === "color-dodge" || b === "colordodge") return alpha * Math.max(0.08, l);
|
|
1805
|
+
return alpha;
|
|
1806
|
+
};
|
|
1783
1807
|
const stack = [];
|
|
1784
1808
|
const textOps = [];
|
|
1785
1809
|
const shapes = [];
|
|
@@ -1856,7 +1880,7 @@ async function walkOps(page, OPS, viewport) {
|
|
|
1856
1880
|
gradient: isFill ? gs.fillGradient : void 0,
|
|
1857
1881
|
stroke: isStroke ? gs.stroke : void 0,
|
|
1858
1882
|
strokeWidth: isStroke ? gs.lineWidth * PT_TO_MM3 : void 0,
|
|
1859
|
-
opacity: isFill ?
|
|
1883
|
+
opacity: isFill ? fillOpacity() : gs.strokeAlpha
|
|
1860
1884
|
});
|
|
1861
1885
|
}
|
|
1862
1886
|
pathRects = [];
|
|
@@ -1878,7 +1902,7 @@ async function walkOps(page, OPS, viewport) {
|
|
|
1878
1902
|
gradient: isFill ? gs.fillGradient : void 0,
|
|
1879
1903
|
stroke: isStroke ? gs.stroke : void 0,
|
|
1880
1904
|
strokeWidth: isStroke ? gs.lineWidth * PT_TO_MM3 : void 0,
|
|
1881
|
-
opacity: isFill ?
|
|
1905
|
+
opacity: isFill ? fillOpacity() : gs.strokeAlpha
|
|
1882
1906
|
});
|
|
1883
1907
|
} else if (pathSegments.length === 2 && pathSegments[0].type === "M" && pathSegments[1].type === "L") {
|
|
1884
1908
|
const a = pathSegments[0].pts;
|
|
@@ -1970,7 +1994,7 @@ async function walkOps(page, OPS, viewport) {
|
|
|
1970
1994
|
gradient: isFill ? gs.fillGradient : void 0,
|
|
1971
1995
|
stroke: isStroke ? gs.stroke : void 0,
|
|
1972
1996
|
strokeWidth: isStroke ? gs.lineWidth * PT_TO_MM3 : void 0,
|
|
1973
|
-
opacity: isFill ?
|
|
1997
|
+
opacity: isFill ? fillOpacity() : gs.strokeAlpha,
|
|
1974
1998
|
path: thin ? void 0 : d
|
|
1975
1999
|
});
|
|
1976
2000
|
}
|
|
@@ -1991,11 +2015,15 @@ async function walkOps(page, OPS, viewport) {
|
|
|
1991
2015
|
if (s) Object.assign(gs, s);
|
|
1992
2016
|
} else if (fn === OPS.paintFormXObjectBegin) {
|
|
1993
2017
|
stack.push(snapshot());
|
|
2018
|
+
groupStack.push({ blend: gs.blend, alpha: gs.fillAlpha });
|
|
2019
|
+
gs.blend = "normal";
|
|
2020
|
+
gs.fillAlpha = 1;
|
|
1994
2021
|
const matrix = args[0];
|
|
1995
2022
|
if (Array.isArray(matrix) && matrix.length === 6) gs.ctm = multiplyCtm(matrix, gs.ctm);
|
|
1996
2023
|
} else if (fn === OPS.paintFormXObjectEnd) {
|
|
1997
2024
|
const s = stack.pop();
|
|
1998
2025
|
if (s) Object.assign(gs, s);
|
|
2026
|
+
groupStack.pop();
|
|
1999
2027
|
} else if (fn === OPS.beginText) {
|
|
2000
2028
|
tm = [1, 0, 0, 1, 0, 0];
|
|
2001
2029
|
tlm = [1, 0, 0, 1, 0, 0];
|
|
@@ -2068,6 +2096,7 @@ async function walkOps(page, OPS, viewport) {
|
|
|
2068
2096
|
if (key === "LW") gs.lineWidth = val;
|
|
2069
2097
|
else if (key === "ca") gs.fillAlpha = val;
|
|
2070
2098
|
else if (key === "CA") gs.strokeAlpha = val;
|
|
2099
|
+
else if (key === "BM") gs.blend = String(Array.isArray(val) ? val[0] : val).toLowerCase();
|
|
2071
2100
|
}
|
|
2072
2101
|
}
|
|
2073
2102
|
} else if (fn === OPS.showText) {
|
|
@@ -2152,18 +2181,37 @@ async function walkOps(page, OPS, viewport) {
|
|
|
2152
2181
|
const isStroke = fn === OPS.stroke || fn === OPS.fillStroke || fn === OPS.eoFillStroke || fn === OPS.closeFillStroke || fn === OPS.closeStroke || fn === OPS.closeEOFillStroke;
|
|
2153
2182
|
flushPath(isFill, isStroke);
|
|
2154
2183
|
} else if (fn === OPS.endPath || fn === OPS.clip || fn === OPS.eoClip) {
|
|
2155
|
-
if (fn !== OPS.endPath)
|
|
2184
|
+
if (fn !== OPS.endPath) {
|
|
2185
|
+
const c = clipFromPath();
|
|
2186
|
+
const prev = gs.clip;
|
|
2187
|
+
if (c && prev) {
|
|
2188
|
+
const x0 = Math.max(c.x, prev.x), y0 = Math.max(c.y, prev.y);
|
|
2189
|
+
const x1 = Math.min(c.x + c.w, prev.x + prev.w), y1 = Math.min(c.y + c.h, prev.y + prev.h);
|
|
2190
|
+
if (x1 <= x0 || y1 <= y0) gs.clip = { d: "", x: x0, y: y0, w: 0, h: 0 };
|
|
2191
|
+
else if (c.d || !prev.d) gs.clip = c.d ? c : { d: "", x: x0, y: y0, w: x1 - x0, h: y1 - y0 };
|
|
2192
|
+
else gs.clip = prev;
|
|
2193
|
+
} else gs.clip = c ?? prev;
|
|
2194
|
+
}
|
|
2156
2195
|
pathSegments = [];
|
|
2157
2196
|
pathRects = [];
|
|
2158
2197
|
pathRect = null;
|
|
2159
2198
|
pathStart = null;
|
|
2160
2199
|
pathLast = null;
|
|
2161
2200
|
} else if (fn === OPS.shadingFill) {
|
|
2162
|
-
|
|
2201
|
+
let ir = args[0];
|
|
2202
|
+
if (typeof ir === "string") {
|
|
2203
|
+
try {
|
|
2204
|
+
const store = ir.startsWith("g_") ? page.commonObjs : page.objs;
|
|
2205
|
+
ir = typeof store?.has === "function" && store.has(ir) ? store.get(ir) : null;
|
|
2206
|
+
} catch {
|
|
2207
|
+
ir = null;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2163
2210
|
const g = irToGradient(ir, (x, y) => toViewport(...Object.values(tx(gs.ctm, x, y))));
|
|
2164
2211
|
const avg = Array.isArray(ir) && ir[0] === "RadialAxial" ? averageStops(ir[3]) : null;
|
|
2165
|
-
|
|
2166
|
-
|
|
2212
|
+
const clipArea = gs.clip;
|
|
2213
|
+
if ((g || avg) && !(clipArea && (clipArea.w < 0.5 || clipArea.h < 0.5))) {
|
|
2214
|
+
const area = clipArea ?? { d: "", x: 0, y: 0, w: viewport.width, h: viewport.height };
|
|
2167
2215
|
shapes.push({
|
|
2168
2216
|
seq: opIndex,
|
|
2169
2217
|
kind: area.d ? "path" : "rect",
|
|
@@ -2173,7 +2221,7 @@ async function walkOps(page, OPS, viewport) {
|
|
|
2173
2221
|
height: Math.max(0.1, area.h * PT_TO_MM3),
|
|
2174
2222
|
fill: avg ?? (g ? g.stops[0].color : void 0),
|
|
2175
2223
|
gradient: g ?? void 0,
|
|
2176
|
-
opacity:
|
|
2224
|
+
opacity: fillOpacity(avg ?? g?.stops[0].color),
|
|
2177
2225
|
path: area.d || void 0
|
|
2178
2226
|
});
|
|
2179
2227
|
}
|
|
@@ -2923,12 +2971,14 @@ async function importPdfToJdf(source, title, runtime, options = {}) {
|
|
|
2923
2971
|
runs2.push(run);
|
|
2924
2972
|
});
|
|
2925
2973
|
const style2 = { fontSize: Math.round(first.fontSize * 10) / 10, fontFamily: base.cls.family, lineHeight: 1 };
|
|
2974
|
+
const rowHeight = Math.round(first.fontSize * PT_TO_MM3 * 100) / 100;
|
|
2926
2975
|
if (first.opacity < 0.999) style2.opacity = Math.round(first.opacity * 100) / 100;
|
|
2927
2976
|
const rt = {
|
|
2928
2977
|
type: "richtext",
|
|
2929
2978
|
runs: runs2,
|
|
2930
2979
|
position: { x: Math.max(0, Math.round(first.x * 100) / 100), y: Math.max(0, Math.round(Math.min(...row.map((i) => lines[i].y)) * 100) / 100) },
|
|
2931
2980
|
width: Math.max(2, Math.round(Math.max(first.fontSize * PT_TO_MM3, Math.min(measuredW, cap2)) * 100) / 100),
|
|
2981
|
+
height: rowHeight,
|
|
2932
2982
|
style: style2
|
|
2933
2983
|
};
|
|
2934
2984
|
const dominant = row.map((i) => lines[i]).sort((a, b) => b.text.trim().length - a.text.trim().length)[0];
|
|
@@ -2957,6 +3007,8 @@ async function importPdfToJdf(source, title, runtime, options = {}) {
|
|
|
2957
3007
|
content: l.text,
|
|
2958
3008
|
position: { x: Math.max(0, Math.round(l.x * 100) / 100), y: Math.max(0, Math.round(l.y * 100) / 100) },
|
|
2959
3009
|
width: Math.max(2, Math.round(elWidth * 100) / 100),
|
|
3010
|
+
// One line at lineHeight 1: the box is exactly one em tall.
|
|
3011
|
+
height: Math.round(l.fontSize * PT_TO_MM3 * 100) / 100,
|
|
2960
3012
|
style
|
|
2961
3013
|
};
|
|
2962
3014
|
if ((cls.weight === "bold" || l.bold) && l.text.trim().length <= 120 && !consumedLines.has(lineIdx)) {
|
|
@@ -2975,6 +3027,7 @@ async function importPdfToJdf(source, title, runtime, options = {}) {
|
|
|
2975
3027
|
prev.content = `${prev.content} ${text.content}`.replace(/\s+/g, " ");
|
|
2976
3028
|
prev.tocEntry = prev.content;
|
|
2977
3029
|
prev.width = Math.max(prev.width ?? 0, text.width ?? 0);
|
|
3030
|
+
prev.height = Math.round((text.position.y + (text.height ?? 0) - prev.position.y) * 100) / 100;
|
|
2978
3031
|
return;
|
|
2979
3032
|
}
|
|
2980
3033
|
lineMeta.set(text, { w: Math.max(l.fontSize * PT_TO_MM3, extent(l)), size: l.fontSize, face: fontKey(l.fontName) });
|
|
@@ -3023,6 +3076,9 @@ async function importPdfToJdf(source, title, runtime, options = {}) {
|
|
|
3023
3076
|
elements.push({ type: "signature", ...baseEl, value: "" });
|
|
3024
3077
|
}
|
|
3025
3078
|
}
|
|
3079
|
+
elements.forEach((e, k) => {
|
|
3080
|
+
if (e.id == null) e.id = `p${pi}-e${k + 1}`;
|
|
3081
|
+
});
|
|
3026
3082
|
pages.push({
|
|
3027
3083
|
id: `page-${pi}`,
|
|
3028
3084
|
pageSize: { width: Math.round(pageW * PT_TO_MM3 * 100) / 100, height: Math.round(pageH * PT_TO_MM3 * 100) / 100 },
|
package/dist/jdf-schema.json
CHANGED
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
"type": "object",
|
|
204
204
|
"required": ["type", "name"],
|
|
205
205
|
"properties": {
|
|
206
|
-
"type": { "const": "input" },
|
|
206
|
+
"type": { "const": "input" }, "id": { "type": "string" },
|
|
207
207
|
"name": { "type": "string", "minLength": 1 },
|
|
208
208
|
"inputType": { "type": "string", "enum": ["text","number","email","url","tel","date","time","datetime-local","password","color"] },
|
|
209
209
|
"value": { "type": "string" },
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
"type": "object",
|
|
223
223
|
"required": ["type", "name"],
|
|
224
224
|
"properties": {
|
|
225
|
-
"type": { "const": "textarea" },
|
|
225
|
+
"type": { "const": "textarea" }, "id": { "type": "string" },
|
|
226
226
|
"name": { "type": "string", "minLength": 1 },
|
|
227
227
|
"value": { "type": "string" },
|
|
228
228
|
"placeholder": { "type": "string" },
|
|
@@ -240,7 +240,7 @@
|
|
|
240
240
|
"type": "object",
|
|
241
241
|
"required": ["type", "name"],
|
|
242
242
|
"properties": {
|
|
243
|
-
"type": { "const": "checkbox" },
|
|
243
|
+
"type": { "const": "checkbox" }, "id": { "type": "string" },
|
|
244
244
|
"name": { "type": "string", "minLength": 1 },
|
|
245
245
|
"checked": { "type": "boolean" },
|
|
246
246
|
"label": { "type": "string" },
|
|
@@ -256,7 +256,7 @@
|
|
|
256
256
|
"type": "object",
|
|
257
257
|
"required": ["type", "name", "options"],
|
|
258
258
|
"properties": {
|
|
259
|
-
"type": { "const": "select" },
|
|
259
|
+
"type": { "const": "select" }, "id": { "type": "string" },
|
|
260
260
|
"name": { "type": "string", "minLength": 1 },
|
|
261
261
|
"options": {
|
|
262
262
|
"type": "array",
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
"type": "object",
|
|
286
286
|
"required": ["type", "name"],
|
|
287
287
|
"properties": {
|
|
288
|
-
"type": { "const": "signature" },
|
|
288
|
+
"type": { "const": "signature" }, "id": { "type": "string" },
|
|
289
289
|
"name": { "type": "string", "minLength": 1 },
|
|
290
290
|
"value": { "type": "string" },
|
|
291
291
|
"label": { "type": "string" },
|
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
"type": "object",
|
|
302
302
|
"required": ["type", "content"],
|
|
303
303
|
"properties": {
|
|
304
|
-
"type": { "const": "text" },
|
|
304
|
+
"type": { "const": "text" }, "id": { "type": "string" },
|
|
305
305
|
"content": { "type": "string" },
|
|
306
306
|
"style": { "$ref": "#/definitions/StyleRef" },
|
|
307
307
|
"position": { "$ref": "#/definitions/Position" },
|
|
@@ -318,7 +318,7 @@
|
|
|
318
318
|
"type": "object",
|
|
319
319
|
"required": ["type", "runs"],
|
|
320
320
|
"properties": {
|
|
321
|
-
"type": { "const": "richtext" },
|
|
321
|
+
"type": { "const": "richtext" }, "id": { "type": "string" },
|
|
322
322
|
"runs": {
|
|
323
323
|
"type": "array",
|
|
324
324
|
"items": {
|
|
@@ -395,7 +395,7 @@
|
|
|
395
395
|
"type": "object",
|
|
396
396
|
"required": ["type", "rows"],
|
|
397
397
|
"properties": {
|
|
398
|
-
"type": { "const": "table" },
|
|
398
|
+
"type": { "const": "table" }, "id": { "type": "string" },
|
|
399
399
|
"columns": {
|
|
400
400
|
"type": "array",
|
|
401
401
|
"items": { "type": "object", "properties": { "width": { "oneOf": [{ "type": "string" }, { "type": "number" }] }, "header": { "type": "string" }, "align": { "type": "string", "enum": ["left","center","right","justify"] } } }
|
|
@@ -418,7 +418,7 @@
|
|
|
418
418
|
"type": "object",
|
|
419
419
|
"required": ["type", "items"],
|
|
420
420
|
"properties": {
|
|
421
|
-
"type": { "const": "list" },
|
|
421
|
+
"type": { "const": "list" }, "id": { "type": "string" },
|
|
422
422
|
"items": {
|
|
423
423
|
"type": "array",
|
|
424
424
|
"items": { "type": "object", "required": ["content"], "properties": { "content": { "type": "string" }, "style": { "$ref": "#/definitions/StyleRef" }, "children": { "type": "array", "items": { "$ref": "#/definitions/ListElement/properties/items/items" } }, "listType": { "type": "string", "enum": ["ordered","unordered"] } } }
|
|
@@ -433,7 +433,7 @@
|
|
|
433
433
|
"type": "object",
|
|
434
434
|
"required": ["type", "shape"],
|
|
435
435
|
"properties": {
|
|
436
|
-
"type": { "const": "shape" },
|
|
436
|
+
"type": { "const": "shape" }, "id": { "type": "string" },
|
|
437
437
|
"shape": { "type": "string", "enum": ["rect","circle","ellipse","line","path"] },
|
|
438
438
|
"position": { "$ref": "#/definitions/Position" }, "width": { "type": "number" }, "height": { "type": "number" },
|
|
439
439
|
"fill": { "type": "string" },
|
|
@@ -459,7 +459,7 @@
|
|
|
459
459
|
"type": "object",
|
|
460
460
|
"required": ["type", "title", "elements"],
|
|
461
461
|
"properties": {
|
|
462
|
-
"type": { "const": "collapsible" },
|
|
462
|
+
"type": { "const": "collapsible" }, "id": { "type": "string" },
|
|
463
463
|
"title": { "type": "string" },
|
|
464
464
|
"elements": { "type": "array", "items": { "$ref": "#/definitions/Element" } },
|
|
465
465
|
"expanded": { "type": "boolean" },
|
|
@@ -471,7 +471,7 @@
|
|
|
471
471
|
"type": "object",
|
|
472
472
|
"required": ["type"],
|
|
473
473
|
"properties": {
|
|
474
|
-
"type": { "const": "toc" }, "title": { "type": "string" },
|
|
474
|
+
"type": { "const": "toc" }, "id": { "type": "string" }, "title": { "type": "string" },
|
|
475
475
|
"position": { "$ref": "#/definitions/Position" }, "width": { "type": "number" },
|
|
476
476
|
"depth": { "type": "integer", "minimum": 1, "maximum": 6 },
|
|
477
477
|
"style": { "$ref": "#/definitions/StyleRef" }
|