@webskill/sdk 0.21.0 → 0.22.0
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/abnfDiagram-O67JEVCF-DtYFjfqO.js +109 -0
- package/dist/agent.d.ts +3 -3
- package/dist/agent.js +1012 -130
- package/dist/{approval-DwN2o2QG.js → approval-DWQlDPbY.js} +102 -16
- package/dist/arc-8U_6NQWm.js +130 -0
- package/dist/architecture-7GRP2DOG-RTw1wpAq.js +4 -0
- package/dist/architectureDiagram-NJMV4G6O-XmmXrJAK.js +7473 -0
- package/dist/array-DQfpQNY8.js +8 -0
- package/dist/blockDiagram-BEXU5L5S-D4yjnCD1.js +2582 -0
- package/dist/browser.d.ts +444 -48
- package/dist/browser.js +1771 -91
- package/dist/c4Diagram-YGBWAQC7-BLmA_JSd.js +3668 -0
- package/dist/channel-CZxxLrG7.js +9 -0
- package/dist/chunk-2Q5K7J3B-Ck03gkFR.js +21 -0
- package/dist/chunk-3FUC2YCW-tr6jmbQf.js +530 -0
- package/dist/chunk-5DYCD2WN-Bt97YGTd.js +58 -0
- package/dist/chunk-5VM5RSS4-BBxa48HL.js +21 -0
- package/dist/chunk-6AEJRKK7-JXK89I-O.js +14 -0
- package/dist/chunk-742MDFTN-CPmgCGwC.js +466 -0
- package/dist/chunk-7INBJB4K-C9jq9o66.js +6552 -0
- package/dist/chunk-7M6MHVWA-BrKCWcR1.js +4894 -0
- package/dist/chunk-7PRAP22T-BHED6GVs.js +95 -0
- package/dist/chunk-DUW6YSOI-DoZj78PO.js +19 -0
- package/dist/chunk-FOHPRMQF-Dkbp819z.js +27189 -0
- package/dist/chunk-GNY47TPC-Bpvq1T49.js +87 -0
- package/dist/chunk-GTNCS2PH-CLmh4I2c.js +686 -0
- package/dist/chunk-GWA4HPMP-B6vN3fkL.js +95 -0
- package/dist/chunk-J5ZVWO5B-Bi_Pcobw.js +26 -0
- package/dist/chunk-JWPE2WC7-D1rC79GS.js +12 -0
- package/dist/chunk-LNGE3PJU-D5OIoe3Z.js +2582 -0
- package/dist/chunk-MBY4JIJT-C34L7a4f.js +2276 -0
- package/dist/chunk-NETBCI7D-Cg84k8N8.js +321 -0
- package/dist/chunk-O7XYJQB3-B6K0KOSL.js +8846 -0
- package/dist/chunk-UA2S7LBM-DxHM29_K.js +612 -0
- package/dist/chunk-WEXAMYUT-Ba6jFWhB.js +33 -0
- package/dist/chunk-XXDRQBXY-DPbSy4kg.js +12 -0
- package/dist/chunk-Y2CYZVJY-U3QOMqrW.js +15 -0
- package/dist/chunk-Z7XXMR3K-oLg1h8F3.js +1038 -0
- package/dist/chunk-ZIGJFQKS-DqEFBuHR.js +2215 -0
- package/dist/classDiagram-v2-NBCMYWYE-BqnOWIUt.js +3845 -0
- package/dist/cose-bilkent-JH36ORCC-C0dTAHVK.js +4270 -0
- package/dist/cynefin-OW5HDTMX-B2QvgEQj.js +4 -0
- package/dist/cynefinDiagram-VND7K2PF-yAWc6Z3W.js +479 -0
- package/dist/cytoscape.esm-C64mRh9B.js +28325 -0
- package/dist/dagre-6A5THRUB-D0w2W27v.js +4816 -0
- package/dist/defaultLocale-B_EoOkSF.js +249 -0
- package/dist/diagram-22UHCM2B-DvgzhUzP.js +6115 -0
- package/dist/diagram-3UASUU5V-DWgUB-ef.js +795 -0
- package/dist/diagram-ATOU4E4O-P1olqwIs.js +553 -0
- package/dist/diagram-CDSNMT55-BUlZuLUe.js +402 -0
- package/dist/diagram-MLGK6HIB-6w5qmkGt.js +186 -0
- package/dist/diagram-MPIPVDR6-DEFiSo8o.js +289 -0
- package/dist/dist-UajCDt3n.js +92 -0
- package/dist/ebnfDiagram-ZINNZB2B-CI8liCfR.js +123 -0
- package/dist/elk-276RUBZZ-3SvW6OAK.js +90034 -0
- package/dist/erDiagram-OPXOYQCR-CPTbKhwP.js +2301 -0
- package/dist/eventmodeling-NTZA5JFV-BlyuqGp0.js +4 -0
- package/dist/flowDiagram-KWPJA3E3-CcUJ6HbV.js +18 -0
- package/dist/ganttDiagram-FUAMR5RP-31UjY0KK.js +3939 -0
- package/dist/{toolSource-C9oNuKmr.js → geometry-wx5ZTYzi.js} +162 -12
- package/dist/gitGraph-4MIJSDKK-ChdVlrk7.js +4 -0
- package/dist/gitGraphDiagram-X574FWY7-DKuxJymB.js +1153 -0
- package/dist/governance.d.ts +3 -3
- package/dist/graphlib-tk9gQYuN.js +4194 -0
- package/dist/{index-B8Tgmpwh.d.ts → index-BiO9_XRk.d.ts} +2 -2
- package/dist/{index-CYLt5u4L.d.ts → index-CjwdZQOS.d.ts} +700 -12
- package/dist/{index-DHopiH_m.d.ts → index-YPd8ZSEa.d.ts} +156 -9
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -6
- package/dist/info-A6RAGUB7-CxRAt9S9.js +4 -0
- package/dist/infoDiagram-VRGFBTTK-pRspGfjZ.js +25 -0
- package/dist/init-CMOIWdg-.js +16 -0
- package/dist/ishikawaDiagram-OU5B5YK6-DKerAPAg.js +975 -0
- package/dist/journeyDiagram-ZHPQQLJL-C4MK-YO5.js +1227 -0
- package/dist/kanban-definition-PNTS6WVX-BqsZpMXx.js +1244 -0
- package/dist/katex-BcRRvyh_.js +26465 -0
- package/dist/{kind-DaKqLX2F.js → kind-Dc8x0HWz.js} +54 -7
- package/dist/line-LgV8iVMV.js +48 -0
- package/dist/linear-BWKR0Tqd.js +393 -0
- package/dist/linkedDocument-CIuh_Yp0.js +416 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/{memoryArtifactStore-D6dLeY55.js → memoryArtifactStore-Bs7glPqm.js} +14 -0
- package/dist/mermaid-parser.core-pYR5siSx.js +754 -0
- package/dist/mermaid.core-DMtwGCHy.js +1756 -0
- package/dist/mindmap-definition-NLK3R4M7-CXbD-myG.js +1312 -0
- package/dist/node.d.ts +3 -3
- package/dist/node.js +2 -2
- package/dist/{openUiLibrary-b0i7F_oZ.js → openUiLibrary-B7j3rLrm.js} +1 -1
- package/dist/{openUiSpecLang-CLXJEeRU.js → openUiSpecLang-BSYYnjay.js} +1 -1
- package/dist/ordinal-CxA6GHQS.js +84 -0
- package/dist/packet-AYTQ26CC-BOm08cxl.js +4 -0
- package/dist/path-C27Z2Bjv.js +106 -0
- package/dist/pegDiagram-GJSIUBJH-BLGJOewQ.js +115 -0
- package/dist/pie-WAS4IAKB-Dvg7glpk.js +4 -0
- package/dist/pieDiagram-5QR66LMP-laoaV_PB.js +298 -0
- package/dist/quadrantDiagram-O4NWA36T-Db_wFBkT.js +2236 -0
- package/dist/radar-RG4KPBEZ-BZDaTu06.js +4 -0
- package/dist/railroad-74A4TZTK-C-UhjkOy.js +4 -0
- package/dist/railroad-abnf-HS5TGJTU-dUKVA4OS.js +4 -0
- package/dist/railroad-ebnf-LZEXJU2U-DzQumk18.js +4 -0
- package/dist/railroad-peg-WCYAUIDC-B3vvTWed.js +4 -0
- package/dist/railroadDiagram-XR7U4H2S-BY0sTM4X.js +89 -0
- package/dist/requirementDiagram-PLB6GJNP-3rkQfEhs.js +2474 -0
- package/dist/rough.cjs-AmDd_NQk.js +1395 -0
- package/dist/sankeyDiagram-IPEJSGJF-CGAJhyG2.js +3578 -0
- package/dist/sequenceDiagram-PO4LG4MO-9FJjFX06.js +5522 -0
- package/dist/sizeCapture-INFHLROL-D8PWxdOn.js +56 -0
- package/dist/{skillVersionStore-B24Jjjry-BkOk9wI_.d.ts → skillVersionStore-B24Jjjry-BY1H7Krp.d.ts} +1 -1
- package/dist/src-NkhI3UMl.js +2653 -0
- package/dist/stateDiagram-v2-GCMORJYK-B0O3wc1-.js +2715 -0
- package/dist/swimlanes-2SLR337P-D4EOnrpu.js +6637 -0
- package/dist/swimlanesDiagram-TC7HE7FX-BUx29EJ9.js +30 -0
- package/dist/testing.d.ts +2 -1
- package/dist/testing.js +1 -1
- package/dist/timeline-definition-EJHVYXUP-CrgiiB4C.js +1513 -0
- package/dist/treeView-Q6P3EWNA-C1by-Gzc.js +4 -0
- package/dist/treemap-WGGIJYW6-mC2NZ6ad.js +4 -0
- package/dist/{types-BvTV_05--BW8zDuEk.d.ts → types-CpDRZ0rA-BM5FI9oN.d.ts} +59 -8
- package/dist/ui-react.d.ts +3 -3
- package/dist/ui-react.js +3718 -77
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +2 -2
- package/dist/usecaseDiagram-POWQR4AR-BUt_TQOY.js +14397 -0
- package/dist/vennDiagram-UO4OBE2U-CwXr0wjA.js +2808 -0
- package/dist/wardley-WFR3VGLG-CVSYjq_S.js +4 -0
- package/dist/wardleyDiagram-VNRHLVJA-Cpfd47dQ.js +874 -0
- package/dist/{webSkillApi-Cib6G-94.js → webSkillApi-Dy-Zjv0y.js} +1 -1
- package/dist/{webskillLitCatalog-W06npwej.js → webskillLitCatalog-D5BCiMCU.js} +1 -1
- package/dist/xychartDiagram-PMCCYNJV-e1TeVoc6.js +2704 -0
- package/package.json +1 -1
- package/dist/linkedDocument-C0gj1sMq.js +0 -245
|
@@ -60,10 +60,14 @@ function toActionFrameScopes(scope) {
|
|
|
60
60
|
}];
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
-
* 本版的操作集(FR-25.1 / 0.16.0 FR-13.6 / 0.18.0 FR-10.1
|
|
63
|
+
* 本版的操作集(FR-25.1 / 0.16.0 FR-13.6 / 0.18.0 FR-10.1 / 0.22.0 FR-17.1)。
|
|
64
64
|
* 导航只有 `back` 一个,且它**不接受地址**——可达面被浏览器历史封死(SC-1)。
|
|
65
65
|
*
|
|
66
|
-
* `
|
|
66
|
+
* `drag` 只表达**起点与终点**,没有中途轨迹(0.22.0 FR-17.6 裁定,D64 就此撤销):
|
|
67
|
+
* 轨迹是实现细节不是意图,能画任意路径等于架空 AC-23.2,而且滑块验证码要的正是轨迹——
|
|
68
|
+
* 表达不了轨迹,这个动作就天然做不了人机验证绕过。
|
|
69
|
+
*
|
|
70
|
+
* 这些动作与既有几个走**同一条** policy 路径,
|
|
67
71
|
* 范围白名单、逐次确认、审计三条硬约束因此天然覆盖到它们——
|
|
68
72
|
* 前提是新动作不绕过 policy 直调执行器(AC-25.4 守这一点)。
|
|
69
73
|
* @experimental
|
|
@@ -76,6 +80,8 @@ const PAGE_ACTION_KINDS = [
|
|
|
76
80
|
"set",
|
|
77
81
|
"attach",
|
|
78
82
|
"scroll",
|
|
83
|
+
"hover",
|
|
84
|
+
"drag",
|
|
79
85
|
"back"
|
|
80
86
|
];
|
|
81
87
|
/**
|
|
@@ -139,8 +145,10 @@ function sniffDocumentFormat(bytes, name) {
|
|
|
139
145
|
const lower = (name ?? "").toLowerCase();
|
|
140
146
|
if (lower.endsWith(".docx")) return "docx";
|
|
141
147
|
if (lower.endsWith(".xlsx")) return "xlsx";
|
|
148
|
+
if (lower.endsWith(".pptx")) return "pptx";
|
|
142
149
|
if (containsEntry(bytes, "word/document.xml")) return "docx";
|
|
143
150
|
if (containsEntry(bytes, "xl/workbook.xml")) return "xlsx";
|
|
151
|
+
if (containsEntry(bytes, "ppt/presentation.xml")) return "pptx";
|
|
144
152
|
}
|
|
145
153
|
|
|
146
154
|
//#endregion
|
|
@@ -225,7 +233,7 @@ function asReadMode(raw) {
|
|
|
225
233
|
const READ_DOCUMENT_TOOL = "read_document";
|
|
226
234
|
/** 大图的门槛:低于它的是页眉 logo、印章、项目符号,投它们等于白烧一次多模态请求 @experimental */
|
|
227
235
|
const PDF_LARGE_IMAGE_RATIO = .15;
|
|
228
|
-
const DESCRIPTION = "Read a PDF, Word (.docx)
|
|
236
|
+
const DESCRIPTION = "Read a PDF, Word (.docx), Excel (.xlsx) or PowerPoint (.pptx) document the user attached or downloaded, one batch of units at a time. Pages that have no usable text layer (scans) are rendered as images, so their content is never lost. Pictures on pages whose text is readable are listed under \"deferred\" instead of being returned, because reading them costs an extra round trip; call again with mode=\"images\" to fetch those.";
|
|
229
237
|
const INPUT_SCHEMA = {
|
|
230
238
|
type: "object",
|
|
231
239
|
properties: {
|
|
@@ -243,7 +251,7 @@ const INPUT_SCHEMA = {
|
|
|
243
251
|
},
|
|
244
252
|
block: {
|
|
245
253
|
type: "number",
|
|
246
|
-
description: "Word
|
|
254
|
+
description: "Word and PowerPoint: 0-based block index."
|
|
247
255
|
},
|
|
248
256
|
sheet: {
|
|
249
257
|
type: "number",
|
|
@@ -252,6 +260,10 @@ const INPUT_SCHEMA = {
|
|
|
252
260
|
row: {
|
|
253
261
|
type: "number",
|
|
254
262
|
description: "Excel only: 0-based row index within the sheet."
|
|
263
|
+
},
|
|
264
|
+
slide: {
|
|
265
|
+
type: "number",
|
|
266
|
+
description: "PowerPoint only: 0-based slide index."
|
|
255
267
|
}
|
|
256
268
|
},
|
|
257
269
|
additionalProperties: false
|
|
@@ -269,7 +281,7 @@ const INPUT_SCHEMA = {
|
|
|
269
281
|
required: ["id"],
|
|
270
282
|
additionalProperties: false
|
|
271
283
|
};
|
|
272
|
-
const SYSTEM_PROMPT = "read_document reads an attached or downloaded PDF/Word/Excel document in batches. It returns a \"next\" cursor whenever the document is not finished: keep calling read_document with that cursor until the result has no \"next\", otherwise you have only seen part of the document. Read the text first and answer from it; a result that carries \"deferred\" means those units hold pictures that were not read yet. Fetch them with mode=\"images\" only when the answer depends on what they show, and tell the user the pictures have not been looked at when you answer without them. Never guess an id, and never claim you read a document you only read part of.";
|
|
284
|
+
const SYSTEM_PROMPT = "read_document reads an attached or downloaded PDF/Word/Excel/PowerPoint document in batches. It returns a \"next\" cursor whenever the document is not finished: keep calling read_document with that cursor until the result has no \"next\", otherwise you have only seen part of the document. Read the text first and answer from it; a result that carries \"deferred\" means those units hold pictures that were not read yet. Fetch them with mode=\"images\" only when the answer depends on what they show, and tell the user the pictures have not been looked at when you answer without them. Never guess an id, and never claim you read a document you only read part of.";
|
|
273
285
|
function toolError(e) {
|
|
274
286
|
return {
|
|
275
287
|
ok: false,
|
|
@@ -287,13 +299,13 @@ function aborted(signal) {
|
|
|
287
299
|
/**
|
|
288
300
|
* 逐单元读文档,读不出字的地方出图(0.21.0 分册 22)。
|
|
289
301
|
*
|
|
290
|
-
*
|
|
302
|
+
* 四个端口一个都没接时 `listToolSpecs()` 返回空——模型连这个工具的存在都看不到,
|
|
291
303
|
* 而不是看得到再被拒(AC-22.2)。
|
|
292
304
|
* @experimental
|
|
293
305
|
*/
|
|
294
306
|
function createDocumentToolSource(options) {
|
|
295
307
|
const { files } = options;
|
|
296
|
-
const available = () => options.pdf !== void 0 || options.docx !== void 0 || options.xlsx !== void 0;
|
|
308
|
+
const available = () => options.pdf !== void 0 || options.docx !== void 0 || options.xlsx !== void 0 || options.pptx !== void 0;
|
|
297
309
|
const budgetOf = () => options.budget?.() ?? DOCUMENT_READ_BUDGET;
|
|
298
310
|
return {
|
|
299
311
|
kind: "document-reader",
|
|
@@ -320,13 +332,13 @@ function createDocumentToolSource(options) {
|
|
|
320
332
|
const file = await files.read(id);
|
|
321
333
|
if (file === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `No readable document with id "${id}". It is either not an attachment of the current message, or a download id that has since expired — list the downloads again to get a fresh one.`);
|
|
322
334
|
const format = sniffDocumentFormat(file.bytes, file.name);
|
|
323
|
-
if (format === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `"${file.name}" is not a PDF, Word (.docx)
|
|
335
|
+
if (format === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `"${file.name}" is not a PDF, Word (.docx), Excel (.xlsx) or PowerPoint (.pptx) document, so read_document cannot read it.`);
|
|
324
336
|
const reader = readerFor(format);
|
|
325
337
|
if (reader === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `This environment cannot read ${format.toUpperCase()} documents.`);
|
|
326
338
|
const from = asCursor(args["from"]);
|
|
327
339
|
const mode = asReadMode(args["mode"]);
|
|
328
340
|
const budget = budgetOf();
|
|
329
|
-
const batch = format === "pdf" ? await readPdf(reader, file.bytes, from, mode, budget, signal) : format === "docx" ? await readDocx(reader, file.bytes, from, mode, budget, signal) : await readXlsx(reader, file.bytes, from, mode, budget, signal);
|
|
341
|
+
const batch = format === "pdf" ? await readPdf(reader, file.bytes, from, mode, budget, signal) : format === "docx" ? await readDocx(reader, file.bytes, from, mode, budget, signal) : format === "pptx" ? await readPptx(reader, file.bytes, from, mode, budget, signal) : await readXlsx(reader, file.bytes, from, mode, budget, signal);
|
|
330
342
|
return {
|
|
331
343
|
ok: true,
|
|
332
344
|
content: describe(file.name, format, batch, aborted(signal))
|
|
@@ -335,6 +347,7 @@ function createDocumentToolSource(options) {
|
|
|
335
347
|
function readerFor(format) {
|
|
336
348
|
if (format === "pdf") return options.pdf;
|
|
337
349
|
if (format === "docx") return options.docx;
|
|
350
|
+
if (format === "pptx") return options.pptx;
|
|
338
351
|
return options.xlsx;
|
|
339
352
|
}
|
|
340
353
|
}
|
|
@@ -345,7 +358,8 @@ function asCursor(raw) {
|
|
|
345
358
|
"page",
|
|
346
359
|
"block",
|
|
347
360
|
"sheet",
|
|
348
|
-
"row"
|
|
361
|
+
"row",
|
|
362
|
+
"slide"
|
|
349
363
|
]) {
|
|
350
364
|
const value = raw[key];
|
|
351
365
|
if (typeof value === "number" && Number.isInteger(value) && value >= 0) out[key] = value;
|
|
@@ -455,6 +469,43 @@ async function readXlsx(reader, bytes, from, mode, budget, signal) {
|
|
|
455
469
|
} } : {}
|
|
456
470
|
};
|
|
457
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* pptx 摊平成「第几页第几块」的一条序列,与 xlsx 的表×行同构。
|
|
474
|
+
* 幻灯片真有页,所以坐标保留页号——模型报「第 7 页那张图」时对得上用户看到的东西。
|
|
475
|
+
*/
|
|
476
|
+
async function readPptx(reader, bytes, from, mode, budget, signal) {
|
|
477
|
+
const { slides } = await reader.read(bytes);
|
|
478
|
+
const flat = [];
|
|
479
|
+
slides.forEach((slide, slideIndex) => {
|
|
480
|
+
slide.blocks.forEach((content, blockIndex) => {
|
|
481
|
+
flat.push({
|
|
482
|
+
slide: slideIndex,
|
|
483
|
+
block: blockIndex,
|
|
484
|
+
content
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
const startSlide = from["slide"] ?? 0;
|
|
489
|
+
const startBlock = from["block"] ?? 0;
|
|
490
|
+
const found = flat.findIndex((entry) => entry.slide > startSlide || entry.slide === startSlide && entry.block >= startBlock);
|
|
491
|
+
const start = found === -1 ? flat.length : found;
|
|
492
|
+
const taken = takeBlocks(flat.map((entry) => entry.content), start, mode, budget, signal, (index) => ({
|
|
493
|
+
slide: flat[index].slide,
|
|
494
|
+
block: flat[index].block
|
|
495
|
+
}));
|
|
496
|
+
const stop = flat[taken.stopped];
|
|
497
|
+
return {
|
|
498
|
+
units: taken.units,
|
|
499
|
+
total: flat.length,
|
|
500
|
+
done: taken.stopped,
|
|
501
|
+
skippedImages: taken.skippedImages,
|
|
502
|
+
deferred: taken.deferred,
|
|
503
|
+
...stop ? { next: {
|
|
504
|
+
slide: stop.slide,
|
|
505
|
+
block: stop.block
|
|
506
|
+
} } : {}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
458
509
|
function takeBlocks(blocks, start, mode, budget, signal, locate) {
|
|
459
510
|
const units = [];
|
|
460
511
|
const deferred = [];
|
|
@@ -549,7 +600,7 @@ function describe(name, format, batch, cancelled) {
|
|
|
549
600
|
}, ...images];
|
|
550
601
|
}
|
|
551
602
|
function continuationNote(format, batch, remaining, cancelled) {
|
|
552
|
-
const noun = format === "pdf" ? "page" : format === "
|
|
603
|
+
const noun = format === "pdf" ? "page" : format === "xlsx" ? "row" : "block";
|
|
553
604
|
if (batch.next === void 0) return `Reached the end of the document; all ${batch.total} ${noun}s have been read.`;
|
|
554
605
|
const cursor = JSON.stringify(batch.next);
|
|
555
606
|
return `${cancelled ? "Stopped because the user cancelled the run" : `${remaining} ${noun}(s) still unread`}. Call read_document again with from = ${cursor} to continue.`;
|
|
@@ -562,4 +613,103 @@ function imageIdOf(unit) {
|
|
|
562
613
|
}
|
|
563
614
|
|
|
564
615
|
//#endregion
|
|
565
|
-
|
|
616
|
+
//#region ../agent/src/template/geometry.ts
|
|
617
|
+
/**
|
|
618
|
+
* A1 地址与 OOXML 几何换算(0.22.0 分册 42 · 设计 43 §1.6)。
|
|
619
|
+
*
|
|
620
|
+
* 环境无关,`@webskill/agent` 里可直接单测——几何算错的后果是图溢出单元格,
|
|
621
|
+
* 而那只有人肉打开文件才看得见,所以这一层的覆盖要密。
|
|
622
|
+
*/
|
|
623
|
+
/** 1 px 的 EMU 数(96 DPI) */
|
|
624
|
+
const EMU_PER_PIXEL = 9525;
|
|
625
|
+
/** 1 磅的 EMU 数 */
|
|
626
|
+
const EMU_PER_POINT = 12700;
|
|
627
|
+
/** 1 twip 的 EMU 数 */
|
|
628
|
+
const EMU_PER_TWIP = 635;
|
|
629
|
+
/** 默认字体的最大数字宽度,Excel 列宽换算基准 */
|
|
630
|
+
const MAX_DIGIT_WIDTH = 7;
|
|
631
|
+
const ADDRESS = /^([A-Z]+)([1-9][0-9]*)$/;
|
|
632
|
+
/** @throws WebSkillError 语法不合法 */
|
|
633
|
+
function parseCellAddress(address) {
|
|
634
|
+
const match = ADDRESS.exec(address.trim().toUpperCase());
|
|
635
|
+
if (match === null) throw new WebSkillError("TEMPLATE_ADDRESS_INVALID", `"${address}" is not a valid cell address. Use A1 notation such as B3.`);
|
|
636
|
+
let column = 0;
|
|
637
|
+
for (const letter of match[1] ?? "") column = column * 26 + (letter.charCodeAt(0) - 64);
|
|
638
|
+
return {
|
|
639
|
+
column: column - 1,
|
|
640
|
+
row: Number(match[2]) - 1
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
function formatCellAddress({ column, row }) {
|
|
644
|
+
let letters = "";
|
|
645
|
+
for (let rest = column + 1; rest > 0; rest = Math.floor((rest - 1) / 26)) letters = String.fromCharCode(65 + (rest - 1) % 26) + letters;
|
|
646
|
+
return `${letters}${row + 1}`;
|
|
647
|
+
}
|
|
648
|
+
/** @throws WebSkillError 语法不合法 */
|
|
649
|
+
function parseCellRange(range) {
|
|
650
|
+
const [from = "", to] = range.split(":");
|
|
651
|
+
if (to === void 0) {
|
|
652
|
+
const single = parseCellAddress(from);
|
|
653
|
+
return {
|
|
654
|
+
start: single,
|
|
655
|
+
end: single
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
return {
|
|
659
|
+
start: parseCellAddress(from),
|
|
660
|
+
end: parseCellAddress(to)
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
function isRangeTopLeft(range, address) {
|
|
664
|
+
return range.start.column === address.column && range.start.row === address.row;
|
|
665
|
+
}
|
|
666
|
+
function rangeContains(range, address) {
|
|
667
|
+
return address.column >= range.start.column && address.column <= range.end.column && address.row >= range.start.row && address.row <= range.end.row;
|
|
668
|
+
}
|
|
669
|
+
/** Excel 的列宽单位是字符数,换算成像素(设计 43 §1.6 实测 MDW=7) */
|
|
670
|
+
function columnWidthToPixels(width) {
|
|
671
|
+
return Math.round(width * 7 + 5);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* 等比缩放进框:宽高同时约束、**取两个比例里的小者**。
|
|
675
|
+
*
|
|
676
|
+
* FR-42.11 与 FR-42.19 是同一条口径——xlsx 的合并区和 docx 声明了 `trHeight` 的
|
|
677
|
+
* 表格行都这么算。框的某一边为 0(未声明高度)时那一边不参与约束。
|
|
678
|
+
*/
|
|
679
|
+
function fitWithin(natural, box) {
|
|
680
|
+
const widthRatio = box.width > 0 ? box.width / natural.width : Number.POSITIVE_INFINITY;
|
|
681
|
+
const heightRatio = box.height > 0 ? box.height / natural.height : Number.POSITIVE_INFINITY;
|
|
682
|
+
const ratio = Math.min(widthRatio, heightRatio, 1);
|
|
683
|
+
if (!Number.isFinite(ratio)) return natural;
|
|
684
|
+
return {
|
|
685
|
+
width: Math.floor(natural.width * ratio),
|
|
686
|
+
height: Math.floor(natural.height * ratio)
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
/** PNG / JPEG 的像素尺寸。读文件头,不解码整张图。 */
|
|
690
|
+
function readImageSize(bytes) {
|
|
691
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
692
|
+
if (bytes.length > 24 && view.getUint32(0) === 2303741511) return {
|
|
693
|
+
width: view.getUint32(16),
|
|
694
|
+
height: view.getUint32(20)
|
|
695
|
+
};
|
|
696
|
+
if (bytes.length > 4 && view.getUint16(0) === 65496) return readJpegSize(view, bytes.length);
|
|
697
|
+
}
|
|
698
|
+
function readJpegSize(view, length) {
|
|
699
|
+
let offset = 2;
|
|
700
|
+
while (offset + 9 < length) {
|
|
701
|
+
if (view.getUint8(offset) !== 255) {
|
|
702
|
+
offset += 1;
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
const marker = view.getUint8(offset + 1);
|
|
706
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
707
|
+
width: view.getUint16(offset + 7),
|
|
708
|
+
height: view.getUint16(offset + 5)
|
|
709
|
+
};
|
|
710
|
+
offset += 2 + view.getUint16(offset + 2);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
//#endregion
|
|
715
|
+
export { DOCUMENT_READ_BUDGET as C, toFrameScopes as D, toActionFrameScopes as E, frameLabel as O, sniffDocumentFormat as S, PAGE_DOCUMENT_REF as T, defersImage as _, columnWidthToPixels as a, isPdfTextTrustworthy as b, isRangeTopLeft as c, rangeContains as d, readImageSize as f, asReadMode as g, createDocumentToolSource as h, MAX_DIGIT_WIDTH as i, frameSteps as k, parseCellAddress as l, READ_DOCUMENT_TOOL as m, EMU_PER_POINT as n, fitWithin as o, PDF_LARGE_IMAGE_RATIO as p, EMU_PER_TWIP as r, formatCellAddress as s, EMU_PER_PIXEL as t, parseCellRange as u, takesImage as v, PAGE_ACTION_KINDS as w, measurePdfTextQuality as x, PDF_GARBLED_RATIO as y };
|