@a9i5k4/dsh-literature 0.2.11 → 0.3.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/lib/client.js +10 -10
- package/lib/index.js +1406 -455
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -2626,6 +2626,183 @@ var init_importer = __esm({
|
|
|
2626
2626
|
}
|
|
2627
2627
|
});
|
|
2628
2628
|
|
|
2629
|
+
// src/node/courseware/pptx.js
|
|
2630
|
+
var pptx_exports = {};
|
|
2631
|
+
__export(pptx_exports, {
|
|
2632
|
+
deckToText: () => deckToText,
|
|
2633
|
+
parsePptx: () => parsePptx
|
|
2634
|
+
});
|
|
2635
|
+
import { readFileSync } from "node:fs";
|
|
2636
|
+
import { inflateRawSync } from "node:zlib";
|
|
2637
|
+
function readZipEntries(bytes) {
|
|
2638
|
+
let eocd = -1;
|
|
2639
|
+
for (let i = bytes.length - 22; i >= 0 && i > bytes.length - 66e3; i -= 1) {
|
|
2640
|
+
if (bytes.readUInt32LE(i) === EOCD_SIG) {
|
|
2641
|
+
eocd = i;
|
|
2642
|
+
break;
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
if (eocd < 0) throw new Error("not a zip archive");
|
|
2646
|
+
const count = bytes.readUInt16LE(eocd + 10);
|
|
2647
|
+
let off = bytes.readUInt32LE(eocd + 16);
|
|
2648
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2649
|
+
for (let i = 0; i < count; i += 1) {
|
|
2650
|
+
if (bytes.readUInt32LE(off) !== CD_SIG) break;
|
|
2651
|
+
const method = bytes.readUInt16LE(off + 10);
|
|
2652
|
+
const compSize = bytes.readUInt32LE(off + 20);
|
|
2653
|
+
const nameLen = bytes.readUInt16LE(off + 28);
|
|
2654
|
+
const extraLen = bytes.readUInt16LE(off + 30);
|
|
2655
|
+
const commentLen = bytes.readUInt16LE(off + 32);
|
|
2656
|
+
const localOff = bytes.readUInt32LE(off + 42);
|
|
2657
|
+
const name2 = bytes.slice(off + 46, off + 46 + nameLen).toString("utf8");
|
|
2658
|
+
if (bytes.readUInt32LE(localOff) === LOCAL_SIG) {
|
|
2659
|
+
const lNameLen = bytes.readUInt16LE(localOff + 26);
|
|
2660
|
+
const lExtraLen = bytes.readUInt16LE(localOff + 28);
|
|
2661
|
+
const dataStart = localOff + 30 + lNameLen + lExtraLen;
|
|
2662
|
+
const raw = bytes.slice(dataStart, dataStart + compSize);
|
|
2663
|
+
let data;
|
|
2664
|
+
try {
|
|
2665
|
+
data = method === 0 ? Buffer.from(raw) : inflateRawSync(raw);
|
|
2666
|
+
} catch {
|
|
2667
|
+
data = null;
|
|
2668
|
+
}
|
|
2669
|
+
entries.set(name2, data);
|
|
2670
|
+
}
|
|
2671
|
+
off += 46 + nameLen + extraLen + commentLen;
|
|
2672
|
+
}
|
|
2673
|
+
return entries;
|
|
2674
|
+
}
|
|
2675
|
+
function paragraphsFromSlideXml(xml) {
|
|
2676
|
+
const out = [];
|
|
2677
|
+
const re = /<a:p>([\s\S]*?)<\/a:p>/g;
|
|
2678
|
+
let m;
|
|
2679
|
+
while (m = re.exec(xml)) {
|
|
2680
|
+
const runs = [...m[1].matchAll(/<a:t>([\s\S]*?)<\/a:t>/g)].map((r) => r[1]);
|
|
2681
|
+
const text = runs.join("").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").trim();
|
|
2682
|
+
if (text) out.push(text);
|
|
2683
|
+
}
|
|
2684
|
+
return out;
|
|
2685
|
+
}
|
|
2686
|
+
function isTitleShape(shapeXml) {
|
|
2687
|
+
return /<p:ph[^>]*type="(?:title|ctrTitle)"/.test(shapeXml);
|
|
2688
|
+
}
|
|
2689
|
+
function aspectOf(cx, cy) {
|
|
2690
|
+
const r = cx / cy;
|
|
2691
|
+
if (r > 1.7) return "16:9";
|
|
2692
|
+
if (r > 1.2) return "4:3";
|
|
2693
|
+
return `${r.toFixed(2)}:1`;
|
|
2694
|
+
}
|
|
2695
|
+
function parseChartXml(xml) {
|
|
2696
|
+
const cats = [...xml.matchAll(/<c:pt idx="(\d+)">\s*<c:v>([\s\S]*?)<\/c:v>/g)];
|
|
2697
|
+
const catMatch = xml.match(/<c:cat>([\s\S]*?)<\/c:cat>/);
|
|
2698
|
+
const categories = catMatch ? [...catMatch[1].matchAll(/<c:v>([\s\S]*?)<\/c:v>/g)].map((m) => m[1].trim()) : [];
|
|
2699
|
+
const series = [];
|
|
2700
|
+
for (const m of xml.matchAll(/<c:ser>([\s\S]*?)<\/c:ser>/g)) {
|
|
2701
|
+
const name2 = m[1].match(/<c:tx>[\s\S]*?<c:v>([\s\S]*?)<\/c:v>/)?.[1]?.trim() ?? "";
|
|
2702
|
+
const valBlock = m[1].match(/<c:val>([\s\S]*?)<\/c:val>/)?.[1] ?? "";
|
|
2703
|
+
const values = [...valBlock.matchAll(/<c:v>([\s\S]*?)<\/c:v>/g)].map((v) => Number(v[1]) || 0);
|
|
2704
|
+
if (values.length) series.push({ name: name2, values });
|
|
2705
|
+
}
|
|
2706
|
+
return { categories, series, rawPts: cats.length };
|
|
2707
|
+
}
|
|
2708
|
+
function naturalSlideIndex(name2) {
|
|
2709
|
+
const m = name2.match(/slide(\d+)\.xml$/);
|
|
2710
|
+
return m ? Number(m[1]) : 0;
|
|
2711
|
+
}
|
|
2712
|
+
function parsePptx(input) {
|
|
2713
|
+
const bytes = Buffer.isBuffer(input) ? input : readFileSync(input);
|
|
2714
|
+
const warnings = [];
|
|
2715
|
+
let entries;
|
|
2716
|
+
try {
|
|
2717
|
+
entries = readZipEntries(bytes);
|
|
2718
|
+
} catch (e) {
|
|
2719
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790\u8BE5\u6587\u4EF6\uFF1A${e.message}\uFF08\u82E5\u4E3A\u65E7\u7248 .ppt\uFF0C\u8BF7\u53E6\u5B58\u4E3A .pptx \u6216\u5BFC\u51FA PDF\uFF09`);
|
|
2720
|
+
}
|
|
2721
|
+
if (!entries.has("[Content_Types].xml")) throw new Error("\u4E0D\u662F\u6709\u6548\u7684 .pptx\uFF08\u7F3A\u5C11 OOXML \u5185\u5BB9\u7C7B\u578B\u6E05\u5355\uFF09");
|
|
2722
|
+
const slideNames = [...entries.keys()].filter((n) => /^ppt\/slides\/slide\d+\.xml$/.test(n)).sort((a, b) => naturalSlideIndex(a) - naturalSlideIndex(b));
|
|
2723
|
+
if (!slideNames.length) throw new Error("\u8BE5 .pptx \u4E2D\u6CA1\u6709\u5E7B\u706F\u7247");
|
|
2724
|
+
const pres = entries.get("ppt/presentation.xml")?.toString("utf8") ?? "";
|
|
2725
|
+
const size = pres.match(/<p:sldSz cx="(\d+)" cy="(\d+)"/);
|
|
2726
|
+
const aspect = size ? aspectOf(Number(size[1]), Number(size[2])) : "";
|
|
2727
|
+
const notesOf = /* @__PURE__ */ new Map();
|
|
2728
|
+
for (const name2 of entries.keys()) {
|
|
2729
|
+
const m = name2.match(/^ppt\/notesSlides\/notesSlide(\d+)\.xml$/);
|
|
2730
|
+
if (m) notesOf.set(Number(m[1]), entries.get(name2)?.toString("utf8") ?? "");
|
|
2731
|
+
}
|
|
2732
|
+
const charts = [];
|
|
2733
|
+
for (const name2 of [...entries.keys()].sort()) {
|
|
2734
|
+
const m = name2.match(/^ppt\/charts\/chart(\d+)\.xml$/);
|
|
2735
|
+
if (!m) continue;
|
|
2736
|
+
const xml = entries.get(name2)?.toString("utf8") ?? "";
|
|
2737
|
+
if (!xml) continue;
|
|
2738
|
+
const parsed = parseChartXml(xml);
|
|
2739
|
+
charts.push({ name: name2, ...parsed });
|
|
2740
|
+
}
|
|
2741
|
+
const slides = slideNames.map((name2) => {
|
|
2742
|
+
const n = naturalSlideIndex(name2);
|
|
2743
|
+
const xml = entries.get(name2)?.toString("utf8") ?? "";
|
|
2744
|
+
const shapes = [...xml.matchAll(/<p:sp>[\s\S]*?<\/p:sp>/g)].map((s) => s[0]);
|
|
2745
|
+
let title = "";
|
|
2746
|
+
const body = [];
|
|
2747
|
+
for (const shape of shapes) {
|
|
2748
|
+
const paras = paragraphsFromSlideXml(shape);
|
|
2749
|
+
if (!paras.length) continue;
|
|
2750
|
+
if (!title && isTitleShape(shape)) title = paras.join(" ");
|
|
2751
|
+
else body.push(...paras);
|
|
2752
|
+
}
|
|
2753
|
+
if (!title && body.length) {
|
|
2754
|
+
title = body.shift();
|
|
2755
|
+
}
|
|
2756
|
+
const images = [...xml.matchAll(/<p:pic>[\s\S]*?<\/p:pic>/g)].length;
|
|
2757
|
+
return {
|
|
2758
|
+
index: n,
|
|
2759
|
+
title: title || `\u7B2C ${n} \u9875`,
|
|
2760
|
+
paragraphs: body,
|
|
2761
|
+
notes: (() => {
|
|
2762
|
+
const nx = notesOf.get(n) ?? "";
|
|
2763
|
+
return nx ? paragraphsFromSlideXml(nx) : [];
|
|
2764
|
+
})(),
|
|
2765
|
+
images
|
|
2766
|
+
};
|
|
2767
|
+
});
|
|
2768
|
+
const media = [...entries.keys()].filter((n) => n.startsWith("ppt/media/")).map((n) => ({ name: n }));
|
|
2769
|
+
return {
|
|
2770
|
+
kind: "pptx",
|
|
2771
|
+
slideCount: slides.length,
|
|
2772
|
+
aspect,
|
|
2773
|
+
slides,
|
|
2774
|
+
media,
|
|
2775
|
+
charts,
|
|
2776
|
+
warnings
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
function deckToText(parsed, { maxChars = 4e4 } = {}) {
|
|
2780
|
+
const parts = [];
|
|
2781
|
+
let total = 0;
|
|
2782
|
+
for (const slide of parsed.slides) {
|
|
2783
|
+
const lines = [`## \u7B2C ${slide.index} \u9875 \xB7 ${slide.title}`];
|
|
2784
|
+
lines.push(...slide.paragraphs.map((p) => `- ${p}`));
|
|
2785
|
+
if (slide.notes.length) lines.push(`\uFF08\u8BB2\u8005\u5907\u6CE8\uFF1A${slide.notes.join("\uFF1B")}\uFF09`);
|
|
2786
|
+
if (slide.images) lines.push(`\uFF08\u672C\u9875\u63D2\u56FE ${slide.images} \u5F20\uFF09`);
|
|
2787
|
+
const block = lines.join("\n");
|
|
2788
|
+
if (total + block.length > maxChars) {
|
|
2789
|
+
parts.push("\u2026\uFF08\u8D85\u51FA\u957F\u5EA6\u4E0A\u9650\uFF0C\u5176\u4F59\u9875\u672A\u5305\u542B\uFF09");
|
|
2790
|
+
break;
|
|
2791
|
+
}
|
|
2792
|
+
parts.push(block);
|
|
2793
|
+
total += block.length;
|
|
2794
|
+
}
|
|
2795
|
+
return parts.join("\n\n");
|
|
2796
|
+
}
|
|
2797
|
+
var EOCD_SIG, CD_SIG, LOCAL_SIG;
|
|
2798
|
+
var init_pptx = __esm({
|
|
2799
|
+
"src/node/courseware/pptx.js"() {
|
|
2800
|
+
EOCD_SIG = 101010256;
|
|
2801
|
+
CD_SIG = 33639248;
|
|
2802
|
+
LOCAL_SIG = 67324752;
|
|
2803
|
+
}
|
|
2804
|
+
});
|
|
2805
|
+
|
|
2629
2806
|
// src/node/pipeline.js
|
|
2630
2807
|
var pipeline_exports = {};
|
|
2631
2808
|
__export(pipeline_exports, {
|
|
@@ -2633,6 +2810,7 @@ __export(pipeline_exports, {
|
|
|
2633
2810
|
arxivBase: () => arxivBase,
|
|
2634
2811
|
discardItem: () => discardItem,
|
|
2635
2812
|
fetchItemPdf: () => fetchItemPdf,
|
|
2813
|
+
importDroppedCourseware: () => importDroppedCourseware,
|
|
2636
2814
|
importDroppedPdf: () => importDroppedPdf,
|
|
2637
2815
|
importPdf: () => importPdf,
|
|
2638
2816
|
log: () => log,
|
|
@@ -2933,8 +3111,8 @@ async function saveItem(key, { mode, tags } = {}) {
|
|
|
2933
3111
|
if (wantMode === "dir") {
|
|
2934
3112
|
let buffer = null;
|
|
2935
3113
|
if (current.pdf?.path) {
|
|
2936
|
-
const { readFile:
|
|
2937
|
-
buffer = await
|
|
3114
|
+
const { readFile: readFile7 } = await import("node:fs/promises");
|
|
3115
|
+
buffer = await readFile7(current.pdf.path).catch(() => null);
|
|
2938
3116
|
}
|
|
2939
3117
|
result = await exportToDirectory(current.record, buffer);
|
|
2940
3118
|
const updated2 = await patchItem(key, { state: "saved", saveMode: "dir", export: result, error: null, updatedAt: Date.now() });
|
|
@@ -2944,14 +3122,14 @@ async function saveItem(key, { mode, tags } = {}) {
|
|
|
2944
3122
|
}
|
|
2945
3123
|
let pdfBuffer = null;
|
|
2946
3124
|
if (current.pdf?.path) {
|
|
2947
|
-
const { readFile:
|
|
2948
|
-
pdfBuffer = await
|
|
3125
|
+
const { readFile: readFile7 } = await import("node:fs/promises");
|
|
3126
|
+
pdfBuffer = await readFile7(current.pdf.path).catch(() => null);
|
|
2949
3127
|
}
|
|
2950
3128
|
if (!pdfBuffer) {
|
|
2951
3129
|
const fetched = await fetchItemPdf(key);
|
|
2952
3130
|
if (fetched?.pdf?.path) {
|
|
2953
|
-
const { readFile:
|
|
2954
|
-
pdfBuffer = await
|
|
3131
|
+
const { readFile: readFile7 } = await import("node:fs/promises");
|
|
3132
|
+
pdfBuffer = await readFile7(fetched.pdf.path).catch(() => null);
|
|
2955
3133
|
} else {
|
|
2956
3134
|
const err = fetched?.error ?? failure("fetch_failed", "\u65E0\u6CD5\u83B7\u53D6\u5168\u6587 PDF\uFF0C\u65E0\u6CD5\u4FDD\u5B58\u5230\u6587\u732E\u5E93");
|
|
2957
3135
|
throw Object.assign(new Error(err.message), { code: err.code ?? "fetch_failed", detail: err.detail });
|
|
@@ -3088,6 +3266,48 @@ async function importDroppedPdf(buffer, { filename = "dropped.pdf" } = {}) {
|
|
|
3088
3266
|
emitItem(saved);
|
|
3089
3267
|
return saved;
|
|
3090
3268
|
}
|
|
3269
|
+
async function importDroppedCourseware(buffer, { filename = "deck.pptx" } = {}) {
|
|
3270
|
+
if (!buffer || buffer.length < 4 || buffer.subarray(0, 2).toString("latin1") !== "PK") {
|
|
3271
|
+
throw failure("network", "\u62D6\u5165\u7684\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 .pptx\uFF08\u65E7\u7248 .ppt \u8BF7\u5148\u53E6\u5B58\u4E3A .pptx \u6216\u5BFC\u51FA PDF\uFF09");
|
|
3272
|
+
}
|
|
3273
|
+
const { parsePptx: parsePptx2, deckToText: deckToText2 } = await Promise.resolve().then(() => (init_pptx(), pptx_exports));
|
|
3274
|
+
let parsed;
|
|
3275
|
+
try {
|
|
3276
|
+
parsed = parsePptx2(buffer);
|
|
3277
|
+
} catch (e) {
|
|
3278
|
+
throw failure("network", e?.message ?? "\u8BFE\u4EF6\u89E3\u6790\u5931\u8D25");
|
|
3279
|
+
}
|
|
3280
|
+
const base = String(filename).replace(/\.pptx$/i, "");
|
|
3281
|
+
const title = parsed.slides[0]?.title && parsed.slides[0].title !== "\u7B2C 1 \u9875" ? parsed.slides[0].title : base;
|
|
3282
|
+
const key = `cw_${randomUUID2().slice(0, 8)}`;
|
|
3283
|
+
const path = join5(PDF_DIR, `${key.replace(/[^\w.-]+/g, "_")}.pptx`);
|
|
3284
|
+
await mkdir4(dirname3(path), { recursive: true });
|
|
3285
|
+
await writeFile4(path, buffer);
|
|
3286
|
+
const item = await putItem({
|
|
3287
|
+
key,
|
|
3288
|
+
kind: "courseware",
|
|
3289
|
+
display: title,
|
|
3290
|
+
title,
|
|
3291
|
+
sourceFile: filename,
|
|
3292
|
+
state: "fetched",
|
|
3293
|
+
courseware: {
|
|
3294
|
+
format: "pptx",
|
|
3295
|
+
path,
|
|
3296
|
+
filename,
|
|
3297
|
+
slideCount: parsed.slideCount,
|
|
3298
|
+
aspect: parsed.aspect,
|
|
3299
|
+
outline: parsed.slides.map((s) => ({ index: s.index, title: s.title })),
|
|
3300
|
+
charts: parsed.charts.map((c) => ({ name: c.name, categories: c.categories, series: c.series })),
|
|
3301
|
+
mediaCount: parsed.media.length,
|
|
3302
|
+
text: deckToText2(parsed, { maxChars: 6e4 })
|
|
3303
|
+
},
|
|
3304
|
+
pdf: { path, size: buffer.length, source: "courseware-import", url: "", filename },
|
|
3305
|
+
tags: ["\u8BFE\u4EF6"],
|
|
3306
|
+
createdAt: Date.now()
|
|
3307
|
+
});
|
|
3308
|
+
emitItem(item);
|
|
3309
|
+
return item;
|
|
3310
|
+
}
|
|
3091
3311
|
var FAILURE_MESSAGES;
|
|
3092
3312
|
var init_pipeline = __esm({
|
|
3093
3313
|
"src/node/pipeline.js"() {
|
|
@@ -3136,6 +3356,118 @@ var init_session_track = __esm({
|
|
|
3136
3356
|
}
|
|
3137
3357
|
});
|
|
3138
3358
|
|
|
3359
|
+
// src/node/pyenv.js
|
|
3360
|
+
var pyenv_exports = {};
|
|
3361
|
+
__export(pyenv_exports, {
|
|
3362
|
+
detectPythons: () => detectPythons,
|
|
3363
|
+
figureInterpreter: () => figureInterpreter,
|
|
3364
|
+
installFigureDeps: () => installFigureDeps,
|
|
3365
|
+
venvDir: () => venvDir,
|
|
3366
|
+
venvExists: () => venvExists
|
|
3367
|
+
});
|
|
3368
|
+
import { execFile } from "node:child_process";
|
|
3369
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
3370
|
+
import { join as join6 } from "node:path";
|
|
3371
|
+
import { homedir as homedir3 } from "node:os";
|
|
3372
|
+
function run(cmd, args, { timeout = 2e4 } = {}) {
|
|
3373
|
+
return new Promise((resolve6) => {
|
|
3374
|
+
execFile(cmd, args, { timeout, windowsHide: true }, (err, stdout, stderr) => {
|
|
3375
|
+
resolve6({ ok: !err, out: String(stdout ?? "").trim(), err: String(stderr ?? "").trim(), code: err?.code });
|
|
3376
|
+
});
|
|
3377
|
+
});
|
|
3378
|
+
}
|
|
3379
|
+
async function probe(exe) {
|
|
3380
|
+
const v = await run(exe, ["--version"]);
|
|
3381
|
+
if (!v.ok) return null;
|
|
3382
|
+
const cap = await run(exe, ["-c", 'import venv, ensurepip; print("ok")']);
|
|
3383
|
+
const mpl = await run(exe, ["-c", "import matplotlib; print(matplotlib.__version__)"]);
|
|
3384
|
+
return {
|
|
3385
|
+
exe,
|
|
3386
|
+
version: v.out.split(" ").pop() ?? "",
|
|
3387
|
+
venvCapable: cap.ok,
|
|
3388
|
+
hasMatplotlib: mpl.ok,
|
|
3389
|
+
matplotlibVersion: mpl.ok ? mpl.out : ""
|
|
3390
|
+
};
|
|
3391
|
+
}
|
|
3392
|
+
async function detectPythons({ force = false } = {}) {
|
|
3393
|
+
if (!force && cache.pythons.length && Date.now() - cache.at < CACHE_MS) return cache.pythons;
|
|
3394
|
+
const candidates2 = [];
|
|
3395
|
+
const tryPush = async (exe) => {
|
|
3396
|
+
if (!exe || candidates2.some((c) => c.exe === exe)) return;
|
|
3397
|
+
const p = await probe(exe);
|
|
3398
|
+
if (p) candidates2.push(p);
|
|
3399
|
+
};
|
|
3400
|
+
if (process.platform === "win32") {
|
|
3401
|
+
const py = await run("py", ["-0p"]);
|
|
3402
|
+
if (py.ok) {
|
|
3403
|
+
for (const line of py.out.split("\n")) {
|
|
3404
|
+
const m = line.match(/[-*]\s*(?:Version: .*)?(?:\|\s*)?(.+\.exe)\s*$/i) ?? line.match(/([A-Za-z]:\\[^\s]+python\.exe)/i);
|
|
3405
|
+
if (m?.[1]) await tryPush(m[1].trim());
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
await tryPush("python");
|
|
3410
|
+
await tryPush("python3");
|
|
3411
|
+
if (process.env.WORKBUDDY_PY) await tryPush(process.env.WORKBUDDY_PY);
|
|
3412
|
+
const managed = join6(homedir3(), ".workbuddy", "binaries", "python", "versions");
|
|
3413
|
+
if (existsSync(managed)) {
|
|
3414
|
+
try {
|
|
3415
|
+
for (const v of readdirSync(managed).sort().reverse()) {
|
|
3416
|
+
await tryPush(join6(managed, v, "python.exe"));
|
|
3417
|
+
await tryPush(join6(managed, v, "bin", "python3"));
|
|
3418
|
+
}
|
|
3419
|
+
} catch {
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
cache = { at: Date.now(), pythons: candidates2 };
|
|
3423
|
+
return candidates2;
|
|
3424
|
+
}
|
|
3425
|
+
function venvDir() {
|
|
3426
|
+
return join6(homedir3(), ".dsh", "dsh-literature", "pyvenv");
|
|
3427
|
+
}
|
|
3428
|
+
function venvPython(dir = venvDir()) {
|
|
3429
|
+
return process.platform === "win32" ? join6(dir, "Scripts", "python.exe") : join6(dir, "bin", "python");
|
|
3430
|
+
}
|
|
3431
|
+
function venvExists(dir = venvDir()) {
|
|
3432
|
+
return existsSync(venvPython(dir));
|
|
3433
|
+
}
|
|
3434
|
+
async function figureInterpreter() {
|
|
3435
|
+
if (venvExists()) {
|
|
3436
|
+
const p = await probe(venvPython());
|
|
3437
|
+
if (p?.hasMatplotlib) return { ...p, source: "venv" };
|
|
3438
|
+
if (p) return { ...p, source: "venv", hasMatplotlib: false };
|
|
3439
|
+
}
|
|
3440
|
+
for (const p of await detectPythons()) {
|
|
3441
|
+
if (p.hasMatplotlib) return { ...p, source: "system" };
|
|
3442
|
+
}
|
|
3443
|
+
return null;
|
|
3444
|
+
}
|
|
3445
|
+
async function installFigureDeps(onLog = () => {
|
|
3446
|
+
}) {
|
|
3447
|
+
const pythons = await detectPythons({ force: true });
|
|
3448
|
+
const base = pythons.find((p) => p.venvCapable);
|
|
3449
|
+
if (!base) return { ok: false, error: "\u672A\u627E\u5230\u53EF\u7528\u7684 Python\uFF08\u9700\u8981\u5E26 venv \u6A21\u5757\u7684 Python 3.8+\uFF09" };
|
|
3450
|
+
const dir = venvDir();
|
|
3451
|
+
if (!venvExists(dir)) {
|
|
3452
|
+
onLog("\u521B\u5EFA\u865A\u62DF\u73AF\u5883\u2026");
|
|
3453
|
+
const r2 = await run(base.exe, ["-m", "venv", dir], { timeout: 12e4 });
|
|
3454
|
+
if (!r2.ok) return { ok: false, error: "venv \u521B\u5EFA\u5931\u8D25\uFF1A" + (r2.err || r2.out) };
|
|
3455
|
+
}
|
|
3456
|
+
const py = venvPython(dir);
|
|
3457
|
+
onLog("\u5B89\u88C5 matplotlib\u2026");
|
|
3458
|
+
const r = await run(py, ["-m", "pip", "install", "--disable-pip-version-check", "matplotlib"], { timeout: 3e5 });
|
|
3459
|
+
if (!r.ok) return { ok: false, error: "matplotlib \u5B89\u88C5\u5931\u8D25\uFF1A" + (r.err || r.out).slice(0, 400) };
|
|
3460
|
+
cache = { at: 0, pythons: [] };
|
|
3461
|
+
return { ok: true, python: py, dir };
|
|
3462
|
+
}
|
|
3463
|
+
var CACHE_MS, cache;
|
|
3464
|
+
var init_pyenv = __esm({
|
|
3465
|
+
"src/node/pyenv.js"() {
|
|
3466
|
+
CACHE_MS = 6e4;
|
|
3467
|
+
cache = { at: 0, pythons: [] };
|
|
3468
|
+
}
|
|
3469
|
+
});
|
|
3470
|
+
|
|
3139
3471
|
// node_modules/pdfjs-dist/legacy/build/pdf.mjs
|
|
3140
3472
|
var pdf_exports = {};
|
|
3141
3473
|
__export(pdf_exports, {
|
|
@@ -3583,7 +3915,7 @@ function getColorValues(colors) {
|
|
|
3583
3915
|
}
|
|
3584
3916
|
span.remove();
|
|
3585
3917
|
}
|
|
3586
|
-
function getCurrentTransform(
|
|
3918
|
+
function getCurrentTransform(ctx2) {
|
|
3587
3919
|
const {
|
|
3588
3920
|
a,
|
|
3589
3921
|
b,
|
|
@@ -3591,10 +3923,10 @@ function getCurrentTransform(ctx) {
|
|
|
3591
3923
|
d,
|
|
3592
3924
|
e,
|
|
3593
3925
|
f
|
|
3594
|
-
} =
|
|
3926
|
+
} = ctx2.getTransform();
|
|
3595
3927
|
return [a, b, c, d, e, f];
|
|
3596
3928
|
}
|
|
3597
|
-
function getCurrentTransformInverse(
|
|
3929
|
+
function getCurrentTransformInverse(ctx2) {
|
|
3598
3930
|
const {
|
|
3599
3931
|
a,
|
|
3600
3932
|
b,
|
|
@@ -3602,7 +3934,7 @@ function getCurrentTransformInverse(ctx) {
|
|
|
3602
3934
|
d,
|
|
3603
3935
|
e,
|
|
3604
3936
|
f
|
|
3605
|
-
} =
|
|
3937
|
+
} = ctx2.getTransform().invertSelf();
|
|
3606
3938
|
return [a, b, c, d, e, f];
|
|
3607
3939
|
}
|
|
3608
3940
|
function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) {
|
|
@@ -4050,7 +4382,7 @@ function loadMeshShader() {
|
|
|
4050
4382
|
function drawMeshWithGPU(posData, colData, vertexCount, context, backgroundColor, paddedWidth, paddedHeight, borderSize) {
|
|
4051
4383
|
return _webGPU.draw(posData, colData, vertexCount, context, backgroundColor, paddedWidth, paddedHeight, borderSize);
|
|
4052
4384
|
}
|
|
4053
|
-
function applyBoundingBox(
|
|
4385
|
+
function applyBoundingBox(ctx2, bbox) {
|
|
4054
4386
|
if (!bbox) {
|
|
4055
4387
|
return;
|
|
4056
4388
|
}
|
|
@@ -4058,7 +4390,7 @@ function applyBoundingBox(ctx, bbox) {
|
|
|
4058
4390
|
const height = bbox[3] - bbox[1];
|
|
4059
4391
|
const region = new Path2D();
|
|
4060
4392
|
region.rect(bbox[0], bbox[1], width, height);
|
|
4061
|
-
|
|
4393
|
+
ctx2.clip(region);
|
|
4062
4394
|
}
|
|
4063
4395
|
function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
|
|
4064
4396
|
const coords = context.coords, colors = context.colors;
|
|
@@ -4164,31 +4496,31 @@ function getShadingPattern(IR) {
|
|
|
4164
4496
|
}
|
|
4165
4497
|
throw new Error(`Unknown IR type: ${IR[0]}`);
|
|
4166
4498
|
}
|
|
4167
|
-
function mirrorContextOperations(
|
|
4168
|
-
if (
|
|
4499
|
+
function mirrorContextOperations(ctx2, destCtx) {
|
|
4500
|
+
if (ctx2._removeMirroring) {
|
|
4169
4501
|
throw new Error("Context is already forwarding operations.");
|
|
4170
4502
|
}
|
|
4171
4503
|
const originalMethods = /* @__PURE__ */ new Map();
|
|
4172
4504
|
for (const name2 of ["save", "restore", "rotate", "scale", "translate", "transform", "setTransform", "resetTransform", "clip", "moveTo", "lineTo", "bezierCurveTo", "quadraticCurveTo", "arc", "arcTo", "ellipse", "rect", "roundRect", "closePath", "beginPath"]) {
|
|
4173
|
-
const original =
|
|
4505
|
+
const original = ctx2[name2];
|
|
4174
4506
|
if (typeof original !== "function" || typeof destCtx[name2] !== "function") {
|
|
4175
4507
|
continue;
|
|
4176
4508
|
}
|
|
4177
4509
|
originalMethods.set(name2, original);
|
|
4178
|
-
|
|
4510
|
+
ctx2[name2] = function(...args) {
|
|
4179
4511
|
destCtx[name2](...args);
|
|
4180
4512
|
return original.apply(this, args);
|
|
4181
4513
|
};
|
|
4182
4514
|
}
|
|
4183
|
-
|
|
4515
|
+
ctx2._removeMirroring = () => {
|
|
4184
4516
|
for (const [name2, original] of originalMethods) {
|
|
4185
|
-
|
|
4517
|
+
ctx2[name2] = original;
|
|
4186
4518
|
}
|
|
4187
|
-
delete
|
|
4519
|
+
delete ctx2._removeMirroring;
|
|
4188
4520
|
};
|
|
4189
4521
|
}
|
|
4190
|
-
function drawImageAtIntegerCoords(
|
|
4191
|
-
const [a, b, c, d, tx, ty] = getCurrentTransform(
|
|
4522
|
+
function drawImageAtIntegerCoords(ctx2, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) {
|
|
4523
|
+
const [a, b, c, d, tx, ty] = getCurrentTransform(ctx2);
|
|
4192
4524
|
if (b === 0 && c === 0) {
|
|
4193
4525
|
const tlX = destX * a + tx;
|
|
4194
4526
|
const rTlX = Math.round(tlX);
|
|
@@ -4198,9 +4530,9 @@ function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, de
|
|
|
4198
4530
|
const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
|
|
4199
4531
|
const brY = (destY + destH) * d + ty;
|
|
4200
4532
|
const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4533
|
+
ctx2.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY);
|
|
4534
|
+
ctx2.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight);
|
|
4535
|
+
ctx2.setTransform(a, b, c, d, tx, ty);
|
|
4204
4536
|
return [rWidth, rHeight];
|
|
4205
4537
|
}
|
|
4206
4538
|
if (a === 0 && d === 0) {
|
|
@@ -4212,17 +4544,17 @@ function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, de
|
|
|
4212
4544
|
const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
|
|
4213
4545
|
const brY = (destX + destW) * b + ty;
|
|
4214
4546
|
const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4547
|
+
ctx2.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY);
|
|
4548
|
+
ctx2.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth);
|
|
4549
|
+
ctx2.setTransform(a, b, c, d, tx, ty);
|
|
4218
4550
|
return [rHeight, rWidth];
|
|
4219
4551
|
}
|
|
4220
|
-
|
|
4552
|
+
ctx2.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
|
|
4221
4553
|
const scaleX = Math.hypot(a, b);
|
|
4222
4554
|
const scaleY = Math.hypot(c, d);
|
|
4223
4555
|
return [scaleX * destW, scaleY * destH];
|
|
4224
4556
|
}
|
|
4225
|
-
function putBinaryImageData(
|
|
4557
|
+
function putBinaryImageData(ctx2, imgData) {
|
|
4226
4558
|
const {
|
|
4227
4559
|
width,
|
|
4228
4560
|
height,
|
|
@@ -4231,7 +4563,7 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4231
4563
|
const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
|
|
4232
4564
|
const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
|
|
4233
4565
|
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
|
|
4234
|
-
const chunkImgData =
|
|
4566
|
+
const chunkImgData = ctx2.createImageData(width, FULL_CHUNK_HEIGHT);
|
|
4235
4567
|
let srcPos = 0;
|
|
4236
4568
|
const src = imgData.data;
|
|
4237
4569
|
const dest = chunkImgData.data;
|
|
@@ -4247,7 +4579,7 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4247
4579
|
width,
|
|
4248
4580
|
height: i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight
|
|
4249
4581
|
}));
|
|
4250
|
-
|
|
4582
|
+
ctx2.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
|
|
4251
4583
|
}
|
|
4252
4584
|
} else if (kind === ImageKind.RGBA_32BPP) {
|
|
4253
4585
|
let j = 0;
|
|
@@ -4255,13 +4587,13 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4255
4587
|
for (i = 0; i < fullChunks; i++) {
|
|
4256
4588
|
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
|
|
4257
4589
|
srcPos += elemsInThisChunk;
|
|
4258
|
-
|
|
4590
|
+
ctx2.putImageData(chunkImgData, 0, j);
|
|
4259
4591
|
j += FULL_CHUNK_HEIGHT;
|
|
4260
4592
|
}
|
|
4261
4593
|
if (i < totalChunks) {
|
|
4262
4594
|
elemsInThisChunk = width * partialChunkHeight * 4;
|
|
4263
4595
|
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
|
|
4264
|
-
|
|
4596
|
+
ctx2.putImageData(chunkImgData, 0, j);
|
|
4265
4597
|
}
|
|
4266
4598
|
} else if (kind === ImageKind.RGB_24BPP) {
|
|
4267
4599
|
for (i = 0; i < totalChunks; i++) {
|
|
@@ -4274,15 +4606,15 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4274
4606
|
width,
|
|
4275
4607
|
height: i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight
|
|
4276
4608
|
}));
|
|
4277
|
-
|
|
4609
|
+
ctx2.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
|
|
4278
4610
|
}
|
|
4279
4611
|
} else {
|
|
4280
4612
|
throw new Error(`bad image kind: ${kind}`);
|
|
4281
4613
|
}
|
|
4282
4614
|
}
|
|
4283
|
-
function putBinaryImageMask(
|
|
4615
|
+
function putBinaryImageMask(ctx2, imgData) {
|
|
4284
4616
|
if (imgData.bitmap) {
|
|
4285
|
-
|
|
4617
|
+
ctx2.drawImage(imgData.bitmap, 0, 0);
|
|
4286
4618
|
return;
|
|
4287
4619
|
}
|
|
4288
4620
|
const {
|
|
@@ -4292,7 +4624,7 @@ function putBinaryImageMask(ctx, imgData) {
|
|
|
4292
4624
|
const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
|
|
4293
4625
|
const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
|
|
4294
4626
|
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
|
|
4295
|
-
const chunkImgData =
|
|
4627
|
+
const chunkImgData = ctx2.createImageData(width, FULL_CHUNK_HEIGHT);
|
|
4296
4628
|
let srcPos = 0;
|
|
4297
4629
|
const src = imgData.data;
|
|
4298
4630
|
const dest = chunkImgData.data;
|
|
@@ -4307,7 +4639,7 @@ function putBinaryImageMask(ctx, imgData) {
|
|
|
4307
4639
|
height: i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight,
|
|
4308
4640
|
nonBlackColor: 0
|
|
4309
4641
|
}));
|
|
4310
|
-
|
|
4642
|
+
ctx2.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
|
|
4311
4643
|
}
|
|
4312
4644
|
}
|
|
4313
4645
|
function copyCtxState(sourceCtx, destCtx) {
|
|
@@ -4322,25 +4654,25 @@ function copyCtxState(sourceCtx, destCtx) {
|
|
|
4322
4654
|
destCtx.lineDashOffset = sourceCtx.lineDashOffset;
|
|
4323
4655
|
}
|
|
4324
4656
|
}
|
|
4325
|
-
function resetCtxToDefault(
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
if (
|
|
4336
|
-
|
|
4337
|
-
|
|
4657
|
+
function resetCtxToDefault(ctx2) {
|
|
4658
|
+
ctx2.strokeStyle = ctx2.fillStyle = "#000000";
|
|
4659
|
+
ctx2.fillRule = "nonzero";
|
|
4660
|
+
ctx2.globalAlpha = 1;
|
|
4661
|
+
ctx2.lineWidth = 1;
|
|
4662
|
+
ctx2.lineCap = "butt";
|
|
4663
|
+
ctx2.lineJoin = "miter";
|
|
4664
|
+
ctx2.miterLimit = 10;
|
|
4665
|
+
ctx2.globalCompositeOperation = "source-over";
|
|
4666
|
+
ctx2.font = "10px sans-serif";
|
|
4667
|
+
if (ctx2.setLineDash !== void 0) {
|
|
4668
|
+
ctx2.setLineDash([]);
|
|
4669
|
+
ctx2.lineDashOffset = 0;
|
|
4338
4670
|
}
|
|
4339
4671
|
const {
|
|
4340
4672
|
filter
|
|
4341
|
-
} =
|
|
4673
|
+
} = ctx2;
|
|
4342
4674
|
if (filter !== "none" && filter !== "") {
|
|
4343
|
-
|
|
4675
|
+
ctx2.filter = "none";
|
|
4344
4676
|
}
|
|
4345
4677
|
}
|
|
4346
4678
|
function getImageSmoothingEnabled(transform, interpolate) {
|
|
@@ -5990,10 +6322,10 @@ var init_pdf2 = __esm({
|
|
|
5990
6322
|
var isCallable = __webpack_require__2(4901);
|
|
5991
6323
|
var replacement = /#|\.prototype\./;
|
|
5992
6324
|
var isForced = function(feature, detection) {
|
|
5993
|
-
var value = data[
|
|
6325
|
+
var value = data[normalize2(feature)];
|
|
5994
6326
|
return value === POLYFILL ? true : value === NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection;
|
|
5995
6327
|
};
|
|
5996
|
-
var
|
|
6328
|
+
var normalize2 = isForced.normalize = function(string) {
|
|
5997
6329
|
return String(string).replace(replacement, ".").toLowerCase();
|
|
5998
6330
|
};
|
|
5999
6331
|
var data = isForced.data = {};
|
|
@@ -6363,7 +6695,7 @@ var init_pdf2 = __esm({
|
|
|
6363
6695
|
var defineProperty = Object.defineProperty;
|
|
6364
6696
|
var stringSlice = uncurryThis("".slice);
|
|
6365
6697
|
var replace = uncurryThis("".replace);
|
|
6366
|
-
var
|
|
6698
|
+
var join9 = uncurryThis([].join);
|
|
6367
6699
|
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
|
|
6368
6700
|
return defineProperty(function() {
|
|
6369
6701
|
}, "length", { value: 8 }).length !== 8;
|
|
@@ -6390,7 +6722,7 @@ var init_pdf2 = __esm({
|
|
|
6390
6722
|
}
|
|
6391
6723
|
var state2 = enforceInternalState(value);
|
|
6392
6724
|
if (!hasOwn(state2, "source")) {
|
|
6393
|
-
state2.source =
|
|
6725
|
+
state2.source = join9(TEMPLATE, typeof name2 == "string" ? name2 : "");
|
|
6394
6726
|
}
|
|
6395
6727
|
return value;
|
|
6396
6728
|
};
|
|
@@ -8913,7 +9245,7 @@ var init_pdf2 = __esm({
|
|
|
8913
9245
|
var charAt = uncurryThis("".charAt);
|
|
8914
9246
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
8915
9247
|
var $Array = globalThis2.Array;
|
|
8916
|
-
var
|
|
9248
|
+
var join9 = uncurryThis([].join);
|
|
8917
9249
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
|
|
8918
9250
|
try {
|
|
8919
9251
|
var target = new Uint8Array2();
|
|
@@ -8959,7 +9291,7 @@ var init_pdf2 = __esm({
|
|
|
8959
9291
|
result[written++] = "=";
|
|
8960
9292
|
}
|
|
8961
9293
|
}
|
|
8962
|
-
return
|
|
9294
|
+
return join9(result, "");
|
|
8963
9295
|
}
|
|
8964
9296
|
});
|
|
8965
9297
|
},
|
|
@@ -8971,7 +9303,7 @@ var init_pdf2 = __esm({
|
|
|
8971
9303
|
var anUint8Array = __webpack_require__2(4154);
|
|
8972
9304
|
var notDetached = __webpack_require__2(5169);
|
|
8973
9305
|
var numberToString = uncurryThis(1.1.toString);
|
|
8974
|
-
var
|
|
9306
|
+
var join9 = uncurryThis([].join);
|
|
8975
9307
|
var $Array = Array;
|
|
8976
9308
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
8977
9309
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
|
|
@@ -8991,7 +9323,7 @@ var init_pdf2 = __esm({
|
|
|
8991
9323
|
var hex = numberToString(this[i], 16);
|
|
8992
9324
|
result[i] = hex.length === 1 ? "0" + hex : hex;
|
|
8993
9325
|
}
|
|
8994
|
-
return
|
|
9326
|
+
return join9(result, "");
|
|
8995
9327
|
}
|
|
8996
9328
|
});
|
|
8997
9329
|
},
|
|
@@ -9470,13 +9802,13 @@ var init_pdf2 = __esm({
|
|
|
9470
9802
|
});
|
|
9471
9803
|
}
|
|
9472
9804
|
static get isCanvasFilterSupported() {
|
|
9473
|
-
let
|
|
9805
|
+
let ctx2;
|
|
9474
9806
|
if (this.isOffscreenCanvasSupported) {
|
|
9475
|
-
|
|
9807
|
+
ctx2 = new OffscreenCanvas(1, 1).getContext("2d");
|
|
9476
9808
|
} else if (typeof document !== "undefined") {
|
|
9477
|
-
|
|
9809
|
+
ctx2 = document.createElement("canvas").getContext("2d");
|
|
9478
9810
|
}
|
|
9479
|
-
return shadow(this, "isCanvasFilterSupported",
|
|
9811
|
+
return shadow(this, "isCanvasFilterSupported", ctx2?.filter !== void 0);
|
|
9480
9812
|
}
|
|
9481
9813
|
static get isAlphaColorInputSupported() {
|
|
9482
9814
|
if (typeof document === "undefined") {
|
|
@@ -10623,14 +10955,14 @@ var init_pdf2 = __esm({
|
|
|
10623
10955
|
static get _isSVGFittingCanvas() {
|
|
10624
10956
|
const svg = `data:image/svg+xml;charset=UTF-8,<svg viewBox="0 0 1 1" width="1" height="1" xmlns="${SVG_NS}"><rect width="1" height="1" style="fill:red;"/></svg>`;
|
|
10625
10957
|
const canvas = new OffscreenCanvas(1, 3);
|
|
10626
|
-
const
|
|
10958
|
+
const ctx2 = canvas.getContext("2d", {
|
|
10627
10959
|
willReadFrequently: true
|
|
10628
10960
|
});
|
|
10629
10961
|
const image = new Image();
|
|
10630
10962
|
image.src = svg;
|
|
10631
10963
|
const promise = image.decode().then(() => {
|
|
10632
|
-
|
|
10633
|
-
return new Uint32Array(
|
|
10964
|
+
ctx2.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3);
|
|
10965
|
+
return new Uint32Array(ctx2.getImageData(0, 0, 1, 1).data.buffer)[0] === 0;
|
|
10634
10966
|
});
|
|
10635
10967
|
return shadow(this, "_isSVGFittingCanvas", promise);
|
|
10636
10968
|
}
|
|
@@ -10738,8 +11070,8 @@ var init_pdf2 = __esm({
|
|
|
10738
11070
|
return data;
|
|
10739
11071
|
}
|
|
10740
11072
|
const offscreen = new OffscreenCanvas(canvas.width, canvas.height);
|
|
10741
|
-
const
|
|
10742
|
-
|
|
11073
|
+
const ctx2 = offscreen.getContext("2d");
|
|
11074
|
+
ctx2.drawImage(canvas, 0, 0);
|
|
10743
11075
|
data = {
|
|
10744
11076
|
bitmap: offscreen.transferToImageBitmap(),
|
|
10745
11077
|
id: `image_${this.#baseId}_${this.#id++}`,
|
|
@@ -10772,8 +11104,8 @@ var init_pdf2 = __esm({
|
|
|
10772
11104
|
} = data;
|
|
10773
11105
|
if (!data.url && !data.file) {
|
|
10774
11106
|
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
10775
|
-
const
|
|
10776
|
-
|
|
11107
|
+
const ctx2 = canvas.getContext("bitmaprenderer");
|
|
11108
|
+
ctx2.transferFromImageBitmap(bitmap);
|
|
10777
11109
|
data.blobPromise = canvas.convertToBlob();
|
|
10778
11110
|
}
|
|
10779
11111
|
bitmap.close?.();
|
|
@@ -15670,8 +16002,8 @@ var init_pdf2 = __esm({
|
|
|
15670
16002
|
}
|
|
15671
16003
|
return this;
|
|
15672
16004
|
}
|
|
15673
|
-
pushBaseTransform(
|
|
15674
|
-
this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1),
|
|
16005
|
+
pushBaseTransform(ctx2) {
|
|
16006
|
+
this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx2.getTransform()));
|
|
15675
16007
|
return this;
|
|
15676
16008
|
}
|
|
15677
16009
|
popBaseTransform() {
|
|
@@ -15687,8 +16019,8 @@ var init_pdf2 = __esm({
|
|
|
15687
16019
|
}
|
|
15688
16020
|
return this;
|
|
15689
16021
|
}
|
|
15690
|
-
recordClipBox(idx,
|
|
15691
|
-
const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1),
|
|
16022
|
+
recordClipBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16023
|
+
const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx2.getTransform());
|
|
15692
16024
|
const clipBox = BBOX_INIT.slice();
|
|
15693
16025
|
Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, clipBox);
|
|
15694
16026
|
const intersection = Util.intersect(this.#clipBox, clipBox);
|
|
@@ -15703,12 +16035,12 @@ var init_pdf2 = __esm({
|
|
|
15703
16035
|
}
|
|
15704
16036
|
return this;
|
|
15705
16037
|
}
|
|
15706
|
-
recordBBox(idx,
|
|
16038
|
+
recordBBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
15707
16039
|
const clipBox = this.#clipBox;
|
|
15708
16040
|
if (clipBox[0] === Infinity) {
|
|
15709
16041
|
return this;
|
|
15710
16042
|
}
|
|
15711
|
-
const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1),
|
|
16043
|
+
const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx2.getTransform());
|
|
15712
16044
|
if (clipBox[0] === -Infinity) {
|
|
15713
16045
|
Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, this.#pendingBBox);
|
|
15714
16046
|
return this;
|
|
@@ -15791,7 +16123,7 @@ var init_pdf2 = __esm({
|
|
|
15791
16123
|
inheritPendingDependenciesAsFutureForcedDependencies() {
|
|
15792
16124
|
return this;
|
|
15793
16125
|
}
|
|
15794
|
-
recordCharacterBBox(idx,
|
|
16126
|
+
recordCharacterBBox(idx, ctx2, font, scale = 1, x = 0, y = 0, getMeasure) {
|
|
15795
16127
|
return this;
|
|
15796
16128
|
}
|
|
15797
16129
|
getSimpleIndex(dependencyName) {
|
|
@@ -15890,8 +16222,8 @@ var init_pdf2 = __esm({
|
|
|
15890
16222
|
this.#bboxTracker.endMarkedContent(opIdx, this.#recordDebugMetadataDepenencyAfterRestore);
|
|
15891
16223
|
return this;
|
|
15892
16224
|
}
|
|
15893
|
-
pushBaseTransform(
|
|
15894
|
-
this.#bboxTracker.pushBaseTransform(
|
|
16225
|
+
pushBaseTransform(ctx2) {
|
|
16226
|
+
this.#bboxTracker.pushBaseTransform(ctx2);
|
|
15895
16227
|
return this;
|
|
15896
16228
|
}
|
|
15897
16229
|
popBaseTransform() {
|
|
@@ -15939,15 +16271,15 @@ var init_pdf2 = __esm({
|
|
|
15939
16271
|
this.#bboxTracker.resetBBox(idx);
|
|
15940
16272
|
return this;
|
|
15941
16273
|
}
|
|
15942
|
-
recordClipBox(idx,
|
|
15943
|
-
this.#bboxTracker.recordClipBox(idx,
|
|
16274
|
+
recordClipBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16275
|
+
this.#bboxTracker.recordClipBox(idx, ctx2, minX, maxX, minY, maxY);
|
|
15944
16276
|
return this;
|
|
15945
16277
|
}
|
|
15946
|
-
recordBBox(idx,
|
|
15947
|
-
this.#bboxTracker.recordBBox(idx,
|
|
16278
|
+
recordBBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16279
|
+
this.#bboxTracker.recordBBox(idx, ctx2, minX, maxX, minY, maxY);
|
|
15948
16280
|
return this;
|
|
15949
16281
|
}
|
|
15950
|
-
recordCharacterBBox(idx,
|
|
16282
|
+
recordCharacterBBox(idx, ctx2, font, scale = 1, x = 0, y = 0, getMeasure) {
|
|
15951
16283
|
const fontBBox = font.bbox;
|
|
15952
16284
|
let isBBoxTrustworthy;
|
|
15953
16285
|
let computedBBox;
|
|
@@ -15960,7 +16292,7 @@ var init_pdf2 = __esm({
|
|
|
15960
16292
|
scaleCharBBox(scale, -scale, x, y, computedBBox);
|
|
15961
16293
|
}
|
|
15962
16294
|
if (isBBoxTrustworthy) {
|
|
15963
|
-
return this.recordBBox(idx,
|
|
16295
|
+
return this.recordBBox(idx, ctx2, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]);
|
|
15964
16296
|
}
|
|
15965
16297
|
}
|
|
15966
16298
|
}
|
|
@@ -15972,10 +16304,10 @@ var init_pdf2 = __esm({
|
|
|
15972
16304
|
isBBoxTrustworthy = computedBBox[0] <= x - measure.actualBoundingBoxLeft && computedBBox[2] >= x + measure.actualBoundingBoxRight && computedBBox[1] <= y - measure.actualBoundingBoxAscent && computedBBox[3] >= y + measure.actualBoundingBoxDescent;
|
|
15973
16305
|
this.#fontBBoxTrustworthy.set(font, isBBoxTrustworthy);
|
|
15974
16306
|
if (isBBoxTrustworthy) {
|
|
15975
|
-
return this.recordBBox(idx,
|
|
16307
|
+
return this.recordBBox(idx, ctx2, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]);
|
|
15976
16308
|
}
|
|
15977
16309
|
}
|
|
15978
|
-
return this.recordBBox(idx,
|
|
16310
|
+
return this.recordBBox(idx, ctx2, x - measure.actualBoundingBoxLeft, x + measure.actualBoundingBoxRight, y - measure.actualBoundingBoxAscent, y + measure.actualBoundingBoxDescent);
|
|
15979
16311
|
}
|
|
15980
16312
|
recordFullPageBBox(idx) {
|
|
15981
16313
|
this.#bboxTracker.recordFullPageBBox(idx);
|
|
@@ -16097,8 +16429,8 @@ var init_pdf2 = __esm({
|
|
|
16097
16429
|
endMarkedContent(opIdx) {
|
|
16098
16430
|
return this;
|
|
16099
16431
|
}
|
|
16100
|
-
pushBaseTransform(
|
|
16101
|
-
this.#dependencyTracker.pushBaseTransform(
|
|
16432
|
+
pushBaseTransform(ctx2) {
|
|
16433
|
+
this.#dependencyTracker.pushBaseTransform(ctx2);
|
|
16102
16434
|
return this;
|
|
16103
16435
|
}
|
|
16104
16436
|
popBaseTransform() {
|
|
@@ -16142,21 +16474,21 @@ var init_pdf2 = __esm({
|
|
|
16142
16474
|
}
|
|
16143
16475
|
return this;
|
|
16144
16476
|
}
|
|
16145
|
-
recordClipBox(idx,
|
|
16477
|
+
recordClipBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16146
16478
|
if (!this.#ignoreBBoxes) {
|
|
16147
|
-
this.#dependencyTracker.recordClipBox(this.#opIdx,
|
|
16479
|
+
this.#dependencyTracker.recordClipBox(this.#opIdx, ctx2, minX, maxX, minY, maxY);
|
|
16148
16480
|
}
|
|
16149
16481
|
return this;
|
|
16150
16482
|
}
|
|
16151
|
-
recordBBox(idx,
|
|
16483
|
+
recordBBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16152
16484
|
if (!this.#ignoreBBoxes) {
|
|
16153
|
-
this.#dependencyTracker.recordBBox(this.#opIdx,
|
|
16485
|
+
this.#dependencyTracker.recordBBox(this.#opIdx, ctx2, minX, maxX, minY, maxY);
|
|
16154
16486
|
}
|
|
16155
16487
|
return this;
|
|
16156
16488
|
}
|
|
16157
|
-
recordCharacterBBox(idx,
|
|
16489
|
+
recordCharacterBBox(idx, ctx2, font, scale, x, y, getMeasure) {
|
|
16158
16490
|
if (!this.#ignoreBBoxes) {
|
|
16159
|
-
this.#dependencyTracker.recordCharacterBBox(this.#opIdx,
|
|
16491
|
+
this.#dependencyTracker.recordCharacterBBox(this.#opIdx, ctx2, font, scale, x, y, getMeasure);
|
|
16160
16492
|
}
|
|
16161
16493
|
return this;
|
|
16162
16494
|
}
|
|
@@ -16218,14 +16550,14 @@ var init_pdf2 = __esm({
|
|
|
16218
16550
|
this.#canvasWidth = canvas.width;
|
|
16219
16551
|
this.#canvasHeight = canvas.height;
|
|
16220
16552
|
}
|
|
16221
|
-
record(
|
|
16553
|
+
record(ctx2, width, height, clipBox) {
|
|
16222
16554
|
if (this.#count === this.#capacity) {
|
|
16223
16555
|
this.#capacity *= 2;
|
|
16224
16556
|
const newCoords = new _CanvasImagesTracker.#CoordsArray(this.#capacity * 6);
|
|
16225
16557
|
newCoords.set(this.#coords);
|
|
16226
16558
|
this.#coords = newCoords;
|
|
16227
16559
|
}
|
|
16228
|
-
const transform = getCurrentTransform(
|
|
16560
|
+
const transform = getCurrentTransform(ctx2);
|
|
16229
16561
|
let coords;
|
|
16230
16562
|
if (clipBox[0] !== Infinity) {
|
|
16231
16563
|
const bbox = BBOX_INIT.slice();
|
|
@@ -16451,7 +16783,7 @@ var init_pdf2 = __esm({
|
|
|
16451
16783
|
const canvas = this._document.createElement("canvas");
|
|
16452
16784
|
canvas.width = 1;
|
|
16453
16785
|
canvas.height = 1;
|
|
16454
|
-
const
|
|
16786
|
+
const ctx2 = canvas.getContext("2d");
|
|
16455
16787
|
let called = 0;
|
|
16456
16788
|
function isFontReady(name2, callback) {
|
|
16457
16789
|
if (++called > 30) {
|
|
@@ -16459,9 +16791,9 @@ var init_pdf2 = __esm({
|
|
|
16459
16791
|
callback();
|
|
16460
16792
|
return;
|
|
16461
16793
|
}
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
const imageData =
|
|
16794
|
+
ctx2.font = "30px " + name2;
|
|
16795
|
+
ctx2.fillText(".", 0, 20);
|
|
16796
|
+
const imageData = ctx2.getImageData(0, 0, 1, 1);
|
|
16465
16797
|
if (imageData.data[3] > 0) {
|
|
16466
16798
|
callback();
|
|
16467
16799
|
return;
|
|
@@ -18200,7 +18532,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18200
18532
|
const dist = Math.hypot(this._p0[0] - this._p1[0], this._p0[1] - this._p1[1]);
|
|
18201
18533
|
return dist + this._r1 > this._r0 && dist + this._r0 > this._r1;
|
|
18202
18534
|
}
|
|
18203
|
-
_createGradient(
|
|
18535
|
+
_createGradient(ctx2, transform = null) {
|
|
18204
18536
|
let grad;
|
|
18205
18537
|
let firstPoint = this._p0;
|
|
18206
18538
|
let secondPoint = this._p1;
|
|
@@ -18211,7 +18543,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18211
18543
|
Util.applyTransform(secondPoint, transform);
|
|
18212
18544
|
}
|
|
18213
18545
|
if (this._type === "axial") {
|
|
18214
|
-
grad =
|
|
18546
|
+
grad = ctx2.createLinearGradient(firstPoint[0], firstPoint[1], secondPoint[0], secondPoint[1]);
|
|
18215
18547
|
} else if (this._type === "radial") {
|
|
18216
18548
|
let r0 = this._r0;
|
|
18217
18549
|
let r1 = this._r1;
|
|
@@ -18221,14 +18553,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18221
18553
|
r0 *= scale[0];
|
|
18222
18554
|
r1 *= scale[0];
|
|
18223
18555
|
}
|
|
18224
|
-
grad =
|
|
18556
|
+
grad = ctx2.createRadialGradient(firstPoint[0], firstPoint[1], r0, secondPoint[0], secondPoint[1], r1);
|
|
18225
18557
|
}
|
|
18226
18558
|
for (const colorStop of this._colorStops) {
|
|
18227
18559
|
grad.addColorStop(colorStop[0], colorStop[1]);
|
|
18228
18560
|
}
|
|
18229
18561
|
return grad;
|
|
18230
18562
|
}
|
|
18231
|
-
_createReversedGradient(
|
|
18563
|
+
_createReversedGradient(ctx2, transform = null) {
|
|
18232
18564
|
let firstPoint = this._p1;
|
|
18233
18565
|
let secondPoint = this._p0;
|
|
18234
18566
|
if (transform) {
|
|
@@ -18245,14 +18577,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18245
18577
|
r0 *= scale[0];
|
|
18246
18578
|
r1 *= scale[0];
|
|
18247
18579
|
}
|
|
18248
|
-
const grad =
|
|
18580
|
+
const grad = ctx2.createRadialGradient(firstPoint[0], firstPoint[1], r0, secondPoint[0], secondPoint[1], r1);
|
|
18249
18581
|
const reversedStops = this._colorStops.map(([t, c]) => [1 - t, c]).reverse();
|
|
18250
18582
|
for (const [t, c] of reversedStops) {
|
|
18251
18583
|
grad.addColorStop(t, c);
|
|
18252
18584
|
}
|
|
18253
18585
|
return grad;
|
|
18254
18586
|
}
|
|
18255
|
-
getPattern(
|
|
18587
|
+
getPattern(ctx2, owner, inverse, pathType) {
|
|
18256
18588
|
let pattern;
|
|
18257
18589
|
if (pathType === PathType.STROKE || pathType === PathType.FILL) {
|
|
18258
18590
|
if (this.isOriginBased()) {
|
|
@@ -18267,14 +18599,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18267
18599
|
if (Math.abs(ps) < precision) {
|
|
18268
18600
|
if (this.isRadial()) {
|
|
18269
18601
|
if (Math.abs(n1 - n2) < precision) {
|
|
18270
|
-
return this._createGradient(
|
|
18602
|
+
return this._createGradient(ctx2, transf);
|
|
18271
18603
|
}
|
|
18272
18604
|
} else {
|
|
18273
|
-
return this._createGradient(
|
|
18605
|
+
return this._createGradient(ctx2, transf);
|
|
18274
18606
|
}
|
|
18275
18607
|
}
|
|
18276
18608
|
}
|
|
18277
|
-
const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(
|
|
18609
|
+
const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(ctx2)) || [0, 0, 0, 0];
|
|
18278
18610
|
const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1;
|
|
18279
18611
|
const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1;
|
|
18280
18612
|
const tmpCanvas = owner.canvasFactory.create(width, height);
|
|
@@ -18295,20 +18627,20 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18295
18627
|
}
|
|
18296
18628
|
tmpCtx.fillStyle = this._createGradient(tmpCtx);
|
|
18297
18629
|
tmpCtx.fill();
|
|
18298
|
-
pattern =
|
|
18630
|
+
pattern = ctx2.createPattern(tmpCanvas.canvas, "no-repeat");
|
|
18299
18631
|
owner.canvasFactory.destroy(tmpCanvas);
|
|
18300
18632
|
const domMatrix = new DOMMatrix(inverse);
|
|
18301
18633
|
pattern.setTransform(domMatrix);
|
|
18302
18634
|
} else {
|
|
18303
18635
|
if (this.areConic()) {
|
|
18304
|
-
|
|
18305
|
-
applyBoundingBox(
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18636
|
+
ctx2.save();
|
|
18637
|
+
applyBoundingBox(ctx2, this._bbox);
|
|
18638
|
+
ctx2.fillStyle = this._createReversedGradient(ctx2);
|
|
18639
|
+
ctx2.fillRect(-1e10, -1e10, 2e10, 2e10);
|
|
18640
|
+
ctx2.restore();
|
|
18309
18641
|
}
|
|
18310
|
-
applyBoundingBox(
|
|
18311
|
-
pattern = this._createGradient(
|
|
18642
|
+
applyBoundingBox(ctx2, this._bbox);
|
|
18643
|
+
pattern = this._createGradient(ctx2);
|
|
18312
18644
|
}
|
|
18313
18645
|
return pattern;
|
|
18314
18646
|
}
|
|
@@ -18376,11 +18708,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18376
18708
|
isModifyingCurrentTransform() {
|
|
18377
18709
|
return true;
|
|
18378
18710
|
}
|
|
18379
|
-
getPattern(
|
|
18380
|
-
applyBoundingBox(
|
|
18711
|
+
getPattern(ctx2, owner, inverse, pathType) {
|
|
18712
|
+
applyBoundingBox(ctx2, this._bbox);
|
|
18381
18713
|
const scale = new Float32Array(2);
|
|
18382
18714
|
if (pathType === PathType.SHADING) {
|
|
18383
|
-
Util.singularValueDecompose2dScale(getCurrentTransform(
|
|
18715
|
+
Util.singularValueDecompose2dScale(getCurrentTransform(ctx2), scale);
|
|
18384
18716
|
} else if (this.matrix) {
|
|
18385
18717
|
Util.singularValueDecompose2dScale(this.matrix, scale);
|
|
18386
18718
|
const [matrixScaleX, matrixScaleY] = scale;
|
|
@@ -18392,14 +18724,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18392
18724
|
}
|
|
18393
18725
|
const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.canvasFactory);
|
|
18394
18726
|
if (pathType !== PathType.SHADING) {
|
|
18395
|
-
|
|
18727
|
+
ctx2.setTransform(...owner.baseTransform);
|
|
18396
18728
|
if (this.matrix) {
|
|
18397
|
-
|
|
18729
|
+
ctx2.transform(...this.matrix);
|
|
18398
18730
|
}
|
|
18399
18731
|
}
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
const pattern =
|
|
18732
|
+
ctx2.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
|
|
18733
|
+
ctx2.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
|
|
18734
|
+
const pattern = ctx2.createPattern(temporaryPatternCanvas.canvas, "no-repeat");
|
|
18403
18735
|
owner.canvasFactory.destroy(temporaryPatternCanvas);
|
|
18404
18736
|
return pattern;
|
|
18405
18737
|
}
|
|
@@ -18415,7 +18747,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18415
18747
|
};
|
|
18416
18748
|
TilingPattern = class _TilingPattern {
|
|
18417
18749
|
static MAX_PATTERN_SIZE = 3e3;
|
|
18418
|
-
constructor(IR,
|
|
18750
|
+
constructor(IR, ctx2, canvasGraphicsFactory, baseTransform) {
|
|
18419
18751
|
this.color = IR[1];
|
|
18420
18752
|
this.operatorList = IR[2];
|
|
18421
18753
|
this.matrix = IR[3];
|
|
@@ -18425,7 +18757,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18425
18757
|
this.paintType = IR[7];
|
|
18426
18758
|
this.tilingType = IR[8];
|
|
18427
18759
|
this.needsIsolation = IR[9] ?? true;
|
|
18428
|
-
this.ctx =
|
|
18760
|
+
this.ctx = ctx2;
|
|
18429
18761
|
this.canvasGraphicsFactory = canvasGraphicsFactory;
|
|
18430
18762
|
this.baseTransform = baseTransform;
|
|
18431
18763
|
this.patternBaseMatrix = this.matrix ? Util.transform(baseTransform, this.matrix) : baseTransform;
|
|
@@ -18627,13 +18959,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18627
18959
|
isModifyingCurrentTransform() {
|
|
18628
18960
|
return false;
|
|
18629
18961
|
}
|
|
18630
|
-
getPattern(
|
|
18962
|
+
getPattern(ctx2, owner, inverse, pathType, opIdx) {
|
|
18631
18963
|
const matrix = pathType !== PathType.SHADING ? Util.transform(inverse, this.patternBaseMatrix) : inverse;
|
|
18632
18964
|
const temporaryPatternCanvas = this.createPatternCanvas(owner, opIdx);
|
|
18633
18965
|
let domMatrix = new DOMMatrix(matrix);
|
|
18634
18966
|
domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
|
|
18635
18967
|
domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY);
|
|
18636
|
-
const pattern =
|
|
18968
|
+
const pattern = ctx2.createPattern(temporaryPatternCanvas.canvas, "repeat");
|
|
18637
18969
|
owner.canvasFactory.destroy(temporaryPatternCanvas.canvasEntry);
|
|
18638
18970
|
pattern.setTransform(domMatrix);
|
|
18639
18971
|
return pattern;
|
|
@@ -18910,13 +19242,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18910
19242
|
this.#knockoutElementDepth = 0;
|
|
18911
19243
|
this.#knockoutGroupLevel = 0;
|
|
18912
19244
|
this.cachedPatterns.clear();
|
|
18913
|
-
for (const
|
|
18914
|
-
for (const canvas of
|
|
19245
|
+
for (const cache3 of this._cachedBitmapsMap.values()) {
|
|
19246
|
+
for (const canvas of cache3.values()) {
|
|
18915
19247
|
if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) {
|
|
18916
19248
|
canvas.width = canvas.height = 0;
|
|
18917
19249
|
}
|
|
18918
19250
|
}
|
|
18919
|
-
|
|
19251
|
+
cache3.clear();
|
|
18920
19252
|
}
|
|
18921
19253
|
this._cachedBitmapsMap.clear();
|
|
18922
19254
|
this.#drawFilter();
|
|
@@ -19002,20 +19334,20 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19002
19334
|
};
|
|
19003
19335
|
}
|
|
19004
19336
|
_createMaskCanvas(opIdx, img) {
|
|
19005
|
-
const
|
|
19337
|
+
const ctx2 = this.ctx;
|
|
19006
19338
|
const {
|
|
19007
19339
|
width,
|
|
19008
19340
|
height
|
|
19009
19341
|
} = img;
|
|
19010
19342
|
const fillColor = this.current.fillColor;
|
|
19011
19343
|
const isPatternFill = this.current.patternFill;
|
|
19012
|
-
const currentTransform = getCurrentTransform(
|
|
19013
|
-
let
|
|
19344
|
+
const currentTransform = getCurrentTransform(ctx2);
|
|
19345
|
+
let cache3, cacheKey, scaled, maskCanvas;
|
|
19014
19346
|
if ((img.bitmap || img.data) && img.count > 1) {
|
|
19015
19347
|
const mainKey = img.bitmap || img.data.buffer;
|
|
19016
19348
|
cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]);
|
|
19017
|
-
|
|
19018
|
-
const cachedImage =
|
|
19349
|
+
cache3 = this._cachedBitmapsMap.getOrInsertComputed(mainKey, makeMap);
|
|
19350
|
+
const cachedImage = cache3.get(cacheKey);
|
|
19019
19351
|
if (cachedImage && !isPatternFill) {
|
|
19020
19352
|
const offsetX2 = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]);
|
|
19021
19353
|
const offsetY2 = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]);
|
|
@@ -19054,8 +19386,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19054
19386
|
this.canvasFactory.destroy(maskCanvas);
|
|
19055
19387
|
maskCanvas = null;
|
|
19056
19388
|
}
|
|
19057
|
-
if (
|
|
19058
|
-
|
|
19389
|
+
if (cache3 && isPatternFill) {
|
|
19390
|
+
cache3.set(cacheKey, scaled);
|
|
19059
19391
|
scaledEntry = null;
|
|
19060
19392
|
maskCanvas = null;
|
|
19061
19393
|
}
|
|
@@ -19070,15 +19402,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19070
19402
|
}
|
|
19071
19403
|
fillCtx.globalCompositeOperation = "source-in";
|
|
19072
19404
|
const inverse = Util.transform(getCurrentTransformInverse(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]);
|
|
19073
|
-
fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(
|
|
19405
|
+
fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx2, this, inverse, PathType.FILL, opIdx) : fillColor;
|
|
19074
19406
|
fillCtx.fillRect(0, 0, width, height);
|
|
19075
|
-
if (
|
|
19076
|
-
|
|
19407
|
+
if (cache3 && !isPatternFill) {
|
|
19408
|
+
cache3.set(cacheKey, fillCanvas.canvas);
|
|
19077
19409
|
}
|
|
19078
19410
|
this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill);
|
|
19079
19411
|
return {
|
|
19080
19412
|
canvas: fillCanvas.canvas,
|
|
19081
|
-
canvasEntry:
|
|
19413
|
+
canvasEntry: cache3 && !isPatternFill ? null : fillCanvas,
|
|
19082
19414
|
offsetX: Math.round(offsetX),
|
|
19083
19415
|
offsetY: Math.round(offsetY)
|
|
19084
19416
|
};
|
|
@@ -19105,10 +19437,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19105
19437
|
}
|
|
19106
19438
|
setDash(opIdx, dashArray, dashPhase) {
|
|
19107
19439
|
this.dependencyTracker?.recordSimpleData("dash", opIdx);
|
|
19108
|
-
const
|
|
19109
|
-
if (
|
|
19110
|
-
|
|
19111
|
-
|
|
19440
|
+
const ctx2 = this.ctx;
|
|
19441
|
+
if (ctx2.setLineDash !== void 0) {
|
|
19442
|
+
ctx2.setLineDash(dashArray);
|
|
19443
|
+
ctx2.lineDashOffset = dashPhase;
|
|
19112
19444
|
}
|
|
19113
19445
|
}
|
|
19114
19446
|
setRenderingIntent(opIdx, intent) {
|
|
@@ -19307,10 +19639,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19307
19639
|
const scratchCanvas = this.canvasFactory.create(drawnWidth, drawnHeight);
|
|
19308
19640
|
this.smaskScratchCanvas = scratchCanvas;
|
|
19309
19641
|
this.suspendedCtx = this.ctx;
|
|
19310
|
-
const
|
|
19311
|
-
|
|
19312
|
-
copyCtxState(this.suspendedCtx,
|
|
19313
|
-
mirrorContextOperations(
|
|
19642
|
+
const ctx2 = this.ctx = scratchCanvas.context;
|
|
19643
|
+
ctx2.setTransform(this.suspendedCtx.getTransform());
|
|
19644
|
+
copyCtxState(this.suspendedCtx, ctx2);
|
|
19645
|
+
mirrorContextOperations(ctx2, this.suspendedCtx);
|
|
19314
19646
|
this._ensurePreparedSMask(this.current.activeSMask);
|
|
19315
19647
|
this.setGState(opIdx, [["BM", "source-over"]]);
|
|
19316
19648
|
}
|
|
@@ -19379,11 +19711,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19379
19711
|
}
|
|
19380
19712
|
return entry;
|
|
19381
19713
|
}
|
|
19382
|
-
const
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
|
|
19386
|
-
|
|
19714
|
+
const ctx2 = entry.context;
|
|
19715
|
+
ctx2.save();
|
|
19716
|
+
ctx2.setTransform(1, 0, 0, 1, 0, 0);
|
|
19717
|
+
ctx2.clearRect(0, 0, width, height);
|
|
19718
|
+
ctx2.restore();
|
|
19387
19719
|
return entry;
|
|
19388
19720
|
}
|
|
19389
19721
|
#compositeKnockoutSurface(destCtx, surfaceCanvas, options = {}) {
|
|
@@ -19523,7 +19855,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19523
19855
|
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
|
19524
19856
|
this.ctx.restore();
|
|
19525
19857
|
}
|
|
19526
|
-
composeSMask(
|
|
19858
|
+
composeSMask(ctx2, smask, layerCtx, layerBox) {
|
|
19527
19859
|
const layerOffsetX = layerBox[0];
|
|
19528
19860
|
const layerOffsetY = layerBox[1];
|
|
19529
19861
|
const layerWidth = layerBox[2] - layerOffsetX;
|
|
@@ -19566,15 +19898,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19566
19898
|
} else {
|
|
19567
19899
|
this.genericComposeSMask(smask, layerCtx, layerWidth, layerHeight, layerOffsetX, layerOffsetY);
|
|
19568
19900
|
}
|
|
19569
|
-
if (!
|
|
19901
|
+
if (!ctx2) {
|
|
19570
19902
|
return;
|
|
19571
19903
|
}
|
|
19572
|
-
|
|
19573
|
-
|
|
19574
|
-
|
|
19575
|
-
|
|
19576
|
-
|
|
19577
|
-
|
|
19904
|
+
ctx2.save();
|
|
19905
|
+
ctx2.globalAlpha = 1;
|
|
19906
|
+
ctx2.globalCompositeOperation = smask.blendMode || "source-over";
|
|
19907
|
+
ctx2.setTransform(1, 0, 0, 1, 0, 0);
|
|
19908
|
+
ctx2.drawImage(layerCtx.canvas, layerOffsetX, layerOffsetY, layerWidth, layerHeight, layerOffsetX, layerOffsetY, layerWidth, layerHeight);
|
|
19909
|
+
ctx2.restore();
|
|
19578
19910
|
}
|
|
19579
19911
|
_applySMaskOOBAlpha(layerCtx, layerOffsetX, layerOffsetY, layerWidth, layerHeight, maskX0, maskY0, maskX1, maskY1, alpha) {
|
|
19580
19912
|
const hasInnerCutout = maskX0 < maskX1 && maskY0 < maskY1;
|
|
@@ -19681,21 +20013,21 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19681
20013
|
}
|
|
19682
20014
|
stroke(opIdx, path, consumePath = true) {
|
|
19683
20015
|
const started = consumePath && this.#beginKnockoutElement(this.current.strokeAlpha);
|
|
19684
|
-
const
|
|
20016
|
+
const ctx2 = this.ctx;
|
|
19685
20017
|
const strokeColor = this.current.strokeColor;
|
|
19686
|
-
|
|
20018
|
+
ctx2.globalAlpha = this.current.strokeAlpha;
|
|
19687
20019
|
if (this.contentVisible) {
|
|
19688
20020
|
if (typeof strokeColor === "object" && strokeColor?.getPattern) {
|
|
19689
|
-
const baseTransform = strokeColor.isModifyingCurrentTransform() ?
|
|
19690
|
-
|
|
19691
|
-
|
|
20021
|
+
const baseTransform = strokeColor.isModifyingCurrentTransform() ? ctx2.getTransform() : null;
|
|
20022
|
+
ctx2.save();
|
|
20023
|
+
ctx2.strokeStyle = strokeColor.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.STROKE, opIdx);
|
|
19692
20024
|
if (baseTransform) {
|
|
19693
20025
|
const newPath = new Path2D();
|
|
19694
|
-
newPath.addPath(path,
|
|
20026
|
+
newPath.addPath(path, ctx2.getTransform().invertSelf().multiplySelf(baseTransform));
|
|
19695
20027
|
path = newPath;
|
|
19696
20028
|
}
|
|
19697
20029
|
this.rescaleAndStroke(path, false);
|
|
19698
|
-
|
|
20030
|
+
ctx2.restore();
|
|
19699
20031
|
} else {
|
|
19700
20032
|
this.rescaleAndStroke(path, true);
|
|
19701
20033
|
}
|
|
@@ -19704,7 +20036,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19704
20036
|
if (consumePath) {
|
|
19705
20037
|
this.consumePath(opIdx, path, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx)));
|
|
19706
20038
|
}
|
|
19707
|
-
|
|
20039
|
+
ctx2.globalAlpha = this.current.fillAlpha;
|
|
19708
20040
|
this.#endKnockoutElement(started);
|
|
19709
20041
|
}
|
|
19710
20042
|
closeStroke(opIdx, path) {
|
|
@@ -19712,7 +20044,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19712
20044
|
}
|
|
19713
20045
|
fill(opIdx, path, consumePath = true) {
|
|
19714
20046
|
const started = consumePath && this.#beginKnockoutElement(this.current.fillAlpha);
|
|
19715
|
-
const
|
|
20047
|
+
const ctx2 = this.ctx;
|
|
19716
20048
|
const fillColor = this.current.fillColor;
|
|
19717
20049
|
const isPatternFill = this.current.patternFill;
|
|
19718
20050
|
let needRestore = false;
|
|
@@ -19731,27 +20063,27 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19731
20063
|
this.#endKnockoutElement(started);
|
|
19732
20064
|
return;
|
|
19733
20065
|
}
|
|
19734
|
-
const baseTransform = fillColor.isModifyingCurrentTransform() ?
|
|
20066
|
+
const baseTransform = fillColor.isModifyingCurrentTransform() ? ctx2.getTransform() : null;
|
|
19735
20067
|
this.dependencyTracker?.save(opIdx);
|
|
19736
|
-
|
|
19737
|
-
|
|
20068
|
+
ctx2.save();
|
|
20069
|
+
ctx2.fillStyle = fillColor.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.FILL, opIdx);
|
|
19738
20070
|
if (baseTransform) {
|
|
19739
20071
|
const newPath = new Path2D();
|
|
19740
|
-
newPath.addPath(path,
|
|
20072
|
+
newPath.addPath(path, ctx2.getTransform().invertSelf().multiplySelf(baseTransform));
|
|
19741
20073
|
path = newPath;
|
|
19742
20074
|
}
|
|
19743
20075
|
needRestore = true;
|
|
19744
20076
|
}
|
|
19745
20077
|
if (this.contentVisible && intersect !== null) {
|
|
19746
20078
|
if (this.pendingEOFill) {
|
|
19747
|
-
|
|
20079
|
+
ctx2.fill(path, "evenodd");
|
|
19748
20080
|
this.pendingEOFill = false;
|
|
19749
20081
|
} else {
|
|
19750
|
-
|
|
20082
|
+
ctx2.fill(path);
|
|
19751
20083
|
}
|
|
19752
20084
|
}
|
|
19753
20085
|
if (needRestore) {
|
|
19754
|
-
|
|
20086
|
+
ctx2.restore();
|
|
19755
20087
|
this.dependencyTracker?.restore(opIdx);
|
|
19756
20088
|
}
|
|
19757
20089
|
if (consumePath) {
|
|
@@ -19807,7 +20139,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19807
20139
|
}
|
|
19808
20140
|
endText(opIdx) {
|
|
19809
20141
|
const paths = this.pendingTextPaths;
|
|
19810
|
-
const
|
|
20142
|
+
const ctx2 = this.ctx;
|
|
19811
20143
|
if (this.dependencyTracker) {
|
|
19812
20144
|
const {
|
|
19813
20145
|
dependencyTracker
|
|
@@ -19819,7 +20151,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19819
20151
|
}
|
|
19820
20152
|
if (paths !== void 0) {
|
|
19821
20153
|
const newPath = new Path2D();
|
|
19822
|
-
const invTransf =
|
|
20154
|
+
const invTransf = ctx2.getTransform().invertSelf();
|
|
19823
20155
|
for (const {
|
|
19824
20156
|
transform,
|
|
19825
20157
|
x,
|
|
@@ -19832,7 +20164,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19832
20164
|
}
|
|
19833
20165
|
newPath.addPath(path, new DOMMatrix(transform).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize));
|
|
19834
20166
|
}
|
|
19835
|
-
|
|
20167
|
+
ctx2.clip(newPath);
|
|
19836
20168
|
}
|
|
19837
20169
|
delete this.pendingTextPaths;
|
|
19838
20170
|
}
|
|
@@ -19924,7 +20256,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19924
20256
|
return newPath;
|
|
19925
20257
|
}
|
|
19926
20258
|
paintChar(opIdx, character, x, y, patternFillTransform, patternStrokeTransform) {
|
|
19927
|
-
const
|
|
20259
|
+
const ctx2 = this.ctx;
|
|
19928
20260
|
const current = this.current;
|
|
19929
20261
|
const font = current.font;
|
|
19930
20262
|
const textRenderingMode = current.textRenderingMode;
|
|
@@ -19938,25 +20270,25 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19938
20270
|
path = font.getPathGenerator(this.commonObjs, character);
|
|
19939
20271
|
}
|
|
19940
20272
|
if (path && (font.disableFontFace || patternFill || patternStroke)) {
|
|
19941
|
-
|
|
19942
|
-
|
|
19943
|
-
|
|
19944
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20273
|
+
ctx2.save();
|
|
20274
|
+
ctx2.translate(x, y);
|
|
20275
|
+
ctx2.scale(fontSize, -fontSize);
|
|
20276
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font);
|
|
19945
20277
|
let currentTransform;
|
|
19946
20278
|
if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19947
20279
|
if (patternFillTransform) {
|
|
19948
|
-
currentTransform =
|
|
19949
|
-
|
|
20280
|
+
currentTransform = ctx2.getTransform();
|
|
20281
|
+
ctx2.setTransform(...patternFillTransform);
|
|
19950
20282
|
const scaledPath = this.#getScaledPath(path, currentTransform, patternFillTransform);
|
|
19951
|
-
|
|
20283
|
+
ctx2.fill(scaledPath);
|
|
19952
20284
|
} else {
|
|
19953
|
-
|
|
20285
|
+
ctx2.fill(path);
|
|
19954
20286
|
}
|
|
19955
20287
|
}
|
|
19956
20288
|
if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19957
20289
|
if (patternStrokeTransform) {
|
|
19958
|
-
currentTransform ||=
|
|
19959
|
-
|
|
20290
|
+
currentTransform ||= ctx2.getTransform();
|
|
20291
|
+
ctx2.setTransform(...patternStrokeTransform);
|
|
19960
20292
|
const {
|
|
19961
20293
|
a,
|
|
19962
20294
|
b,
|
|
@@ -19966,44 +20298,44 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19966
20298
|
const invPatternTransform = Util.inverseTransform(patternStrokeTransform);
|
|
19967
20299
|
const transf = Util.transform([a, b, c, d, 0, 0], invPatternTransform);
|
|
19968
20300
|
Util.singularValueDecompose2dScale(transf, XY);
|
|
19969
|
-
|
|
19970
|
-
|
|
20301
|
+
ctx2.lineWidth *= Math.max(XY[0], XY[1]) / fontSize;
|
|
20302
|
+
ctx2.stroke(this.#getScaledPath(path, currentTransform, patternStrokeTransform));
|
|
19971
20303
|
} else {
|
|
19972
|
-
|
|
19973
|
-
|
|
20304
|
+
ctx2.lineWidth /= fontSize;
|
|
20305
|
+
ctx2.stroke(path);
|
|
19974
20306
|
}
|
|
19975
20307
|
}
|
|
19976
|
-
|
|
20308
|
+
ctx2.restore();
|
|
19977
20309
|
} else {
|
|
19978
20310
|
if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19979
|
-
|
|
19980
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20311
|
+
ctx2.fillText(character, x, y);
|
|
20312
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font, fontSize, x, y, () => ctx2.measureText(character));
|
|
19981
20313
|
}
|
|
19982
20314
|
if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19983
20315
|
if (this.dependencyTracker) {
|
|
19984
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20316
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font, fontSize, x, y, () => ctx2.measureText(character)).recordDependencies(opIdx, Dependencies.stroke);
|
|
19985
20317
|
}
|
|
19986
|
-
|
|
20318
|
+
ctx2.strokeText(character, x, y);
|
|
19987
20319
|
}
|
|
19988
20320
|
}
|
|
19989
20321
|
if (isAddToPathSet) {
|
|
19990
20322
|
const paths = this.pendingTextPaths ||= [];
|
|
19991
20323
|
paths.push({
|
|
19992
|
-
transform: getCurrentTransform(
|
|
20324
|
+
transform: getCurrentTransform(ctx2),
|
|
19993
20325
|
x,
|
|
19994
20326
|
y,
|
|
19995
20327
|
fontSize,
|
|
19996
20328
|
path
|
|
19997
20329
|
});
|
|
19998
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20330
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font, fontSize, x, y);
|
|
19999
20331
|
}
|
|
20000
20332
|
}
|
|
20001
20333
|
get isFontSubpixelAAEnabled() {
|
|
20002
20334
|
const tmpCanvas = this.canvasFactory.create(10, 10);
|
|
20003
|
-
const
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
const data =
|
|
20335
|
+
const ctx2 = tmpCanvas.context;
|
|
20336
|
+
ctx2.scale(1.5, 1);
|
|
20337
|
+
ctx2.fillText("I", 0, 10);
|
|
20338
|
+
const data = ctx2.getImageData(0, 0, 10, 10).data;
|
|
20007
20339
|
this.canvasFactory.destroy(tmpCanvas);
|
|
20008
20340
|
let enabled = false;
|
|
20009
20341
|
for (let i = 3; i < data.length; i += 4) {
|
|
@@ -20036,7 +20368,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20036
20368
|
return;
|
|
20037
20369
|
}
|
|
20038
20370
|
const started = this.#beginKnockoutElement(current.fillAlpha);
|
|
20039
|
-
const
|
|
20371
|
+
const ctx2 = this.ctx;
|
|
20040
20372
|
const fontSizeScale = current.fontSizeScale;
|
|
20041
20373
|
const charSpacing = current.charSpacing;
|
|
20042
20374
|
const wordSpacing = current.wordSpacing;
|
|
@@ -20048,15 +20380,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20048
20380
|
const defaultVMetrics = font.defaultVMetrics;
|
|
20049
20381
|
const widthAdvanceScale = fontSize * current.fontMatrix[0];
|
|
20050
20382
|
const simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
|
|
20051
|
-
|
|
20383
|
+
ctx2.save();
|
|
20052
20384
|
if (current.textMatrix) {
|
|
20053
|
-
|
|
20385
|
+
ctx2.transform(...current.textMatrix);
|
|
20054
20386
|
}
|
|
20055
|
-
|
|
20387
|
+
ctx2.translate(current.x, current.y + current.textRise);
|
|
20056
20388
|
if (fontDirection > 0) {
|
|
20057
|
-
|
|
20389
|
+
ctx2.scale(textHScale, -1);
|
|
20058
20390
|
} else {
|
|
20059
|
-
|
|
20391
|
+
ctx2.scale(textHScale, 1);
|
|
20060
20392
|
}
|
|
20061
20393
|
let patternFillTransform, patternStrokeTransform;
|
|
20062
20394
|
const fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
|
|
@@ -20072,23 +20404,23 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20072
20404
|
lineWidth /= scale;
|
|
20073
20405
|
}
|
|
20074
20406
|
if (fontSizeScale !== 1) {
|
|
20075
|
-
|
|
20407
|
+
ctx2.scale(fontSizeScale, fontSizeScale);
|
|
20076
20408
|
lineWidth /= fontSizeScale;
|
|
20077
20409
|
}
|
|
20078
|
-
|
|
20410
|
+
ctx2.lineWidth = lineWidth;
|
|
20079
20411
|
if (needsFill && current.patternFill) {
|
|
20080
|
-
|
|
20081
|
-
const pattern = current.fillColor.getPattern(
|
|
20082
|
-
patternFillTransform = getCurrentTransform(
|
|
20083
|
-
|
|
20084
|
-
|
|
20412
|
+
ctx2.save();
|
|
20413
|
+
const pattern = current.fillColor.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.FILL, opIdx);
|
|
20414
|
+
patternFillTransform = getCurrentTransform(ctx2);
|
|
20415
|
+
ctx2.restore();
|
|
20416
|
+
ctx2.fillStyle = pattern;
|
|
20085
20417
|
}
|
|
20086
20418
|
if (needsStroke && current.patternStroke) {
|
|
20087
|
-
|
|
20088
|
-
const pattern = current.strokeColor.getPattern(
|
|
20089
|
-
patternStrokeTransform = getCurrentTransform(
|
|
20090
|
-
|
|
20091
|
-
|
|
20419
|
+
ctx2.save();
|
|
20420
|
+
const pattern = current.strokeColor.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.STROKE, opIdx);
|
|
20421
|
+
patternStrokeTransform = getCurrentTransform(ctx2);
|
|
20422
|
+
ctx2.restore();
|
|
20423
|
+
ctx2.strokeStyle = pattern;
|
|
20092
20424
|
}
|
|
20093
20425
|
if (font.isInvalidPDFjsFont) {
|
|
20094
20426
|
const chars = [];
|
|
@@ -20098,13 +20430,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20098
20430
|
width += glyph.width;
|
|
20099
20431
|
}
|
|
20100
20432
|
const joinedChars = chars.join("");
|
|
20101
|
-
|
|
20433
|
+
ctx2.fillText(joinedChars, 0, 0);
|
|
20102
20434
|
if (this.dependencyTracker !== null) {
|
|
20103
|
-
const measure =
|
|
20435
|
+
const measure = ctx2.measureText(joinedChars);
|
|
20104
20436
|
this.dependencyTracker.recordBBox(opIdx, this.ctx, -measure.actualBoundingBoxLeft, measure.actualBoundingBoxRight, -measure.actualBoundingBoxAscent, measure.actualBoundingBoxDescent).recordShowTextOperation(opIdx);
|
|
20105
20437
|
}
|
|
20106
20438
|
current.x += width * widthAdvanceScale * textHScale;
|
|
20107
|
-
|
|
20439
|
+
ctx2.restore();
|
|
20108
20440
|
this.compose();
|
|
20109
20441
|
this.#endKnockoutElement(started);
|
|
20110
20442
|
return;
|
|
@@ -20135,13 +20467,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20135
20467
|
}
|
|
20136
20468
|
let measure;
|
|
20137
20469
|
if (font.remeasure && width > 0) {
|
|
20138
|
-
measure =
|
|
20470
|
+
measure = ctx2.measureText(character);
|
|
20139
20471
|
const measuredWidth = measure.width * 1e3 / fontSize * fontSizeScale;
|
|
20140
20472
|
if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
|
|
20141
20473
|
const characterScaleX = width / measuredWidth;
|
|
20142
20474
|
restoreNeeded = true;
|
|
20143
|
-
|
|
20144
|
-
|
|
20475
|
+
ctx2.save();
|
|
20476
|
+
ctx2.scale(characterScaleX, 1);
|
|
20145
20477
|
scaledX /= characterScaleX;
|
|
20146
20478
|
} else if (width !== measuredWidth) {
|
|
20147
20479
|
scaledX += (width - measuredWidth) / 2e3 * fontSize / fontSizeScale;
|
|
@@ -20149,10 +20481,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20149
20481
|
}
|
|
20150
20482
|
if (this.contentVisible && (glyph.isInFont || font.missingFile)) {
|
|
20151
20483
|
if (simpleFillText && !accent) {
|
|
20152
|
-
|
|
20153
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20484
|
+
ctx2.fillText(character, scaledX, scaledY);
|
|
20485
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, measure ? {
|
|
20154
20486
|
bbox: null
|
|
20155
|
-
} : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ??
|
|
20487
|
+
} : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ?? ctx2.measureText(character));
|
|
20156
20488
|
} else {
|
|
20157
20489
|
this.paintChar(opIdx, character, scaledX, scaledY, patternFillTransform, patternStrokeTransform);
|
|
20158
20490
|
if (accent) {
|
|
@@ -20165,7 +20497,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20165
20497
|
const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection;
|
|
20166
20498
|
x += charWidth;
|
|
20167
20499
|
if (restoreNeeded) {
|
|
20168
|
-
|
|
20500
|
+
ctx2.restore();
|
|
20169
20501
|
}
|
|
20170
20502
|
}
|
|
20171
20503
|
if (vertical) {
|
|
@@ -20173,13 +20505,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20173
20505
|
} else {
|
|
20174
20506
|
current.x += x * textHScale;
|
|
20175
20507
|
}
|
|
20176
|
-
|
|
20508
|
+
ctx2.restore();
|
|
20177
20509
|
this.compose();
|
|
20178
20510
|
this.dependencyTracker?.recordShowTextOperation(opIdx);
|
|
20179
20511
|
this.#endKnockoutElement(started);
|
|
20180
20512
|
}
|
|
20181
20513
|
showType3Text(opIdx, glyphs) {
|
|
20182
|
-
const
|
|
20514
|
+
const ctx2 = this.ctx;
|
|
20183
20515
|
const current = this.current;
|
|
20184
20516
|
const font = current.font;
|
|
20185
20517
|
const fontSize = current.fontSize;
|
|
@@ -20197,12 +20529,12 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20197
20529
|
}
|
|
20198
20530
|
this._cachedScaleForStroking[0] = -1;
|
|
20199
20531
|
this._cachedGetSinglePixelWidth = null;
|
|
20200
|
-
|
|
20532
|
+
ctx2.save();
|
|
20201
20533
|
if (current.textMatrix) {
|
|
20202
|
-
|
|
20534
|
+
ctx2.transform(...current.textMatrix);
|
|
20203
20535
|
}
|
|
20204
|
-
|
|
20205
|
-
|
|
20536
|
+
ctx2.translate(current.x, current.y + current.textRise);
|
|
20537
|
+
ctx2.scale(textHScale, fontDirection);
|
|
20206
20538
|
const dependencyTracker = this.dependencyTracker;
|
|
20207
20539
|
this.dependencyTracker = dependencyTracker ? new CanvasNestedDependencyTracker(dependencyTracker, opIdx) : null;
|
|
20208
20540
|
for (i = 0; i < glyphsLength; ++i) {
|
|
@@ -20221,20 +20553,20 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20221
20553
|
this.save();
|
|
20222
20554
|
if (operatorList.fnArray[0] === OPS.setCharWidth) {
|
|
20223
20555
|
current.fillAlpha = current.strokeAlpha = 1;
|
|
20224
|
-
|
|
20556
|
+
ctx2.globalAlpha = 1;
|
|
20225
20557
|
}
|
|
20226
|
-
|
|
20227
|
-
|
|
20558
|
+
ctx2.scale(fontSize, fontSize);
|
|
20559
|
+
ctx2.transform(...fontMatrix);
|
|
20228
20560
|
this.executeOperatorList(operatorList);
|
|
20229
20561
|
this.restore();
|
|
20230
20562
|
}
|
|
20231
20563
|
const p = [glyph.width, 0];
|
|
20232
20564
|
Util.applyTransform(p, fontMatrix);
|
|
20233
20565
|
width = p[0] * fontSize + spacing;
|
|
20234
|
-
|
|
20566
|
+
ctx2.translate(width, 0);
|
|
20235
20567
|
current.x += width * textHScale;
|
|
20236
20568
|
}
|
|
20237
|
-
|
|
20569
|
+
ctx2.restore();
|
|
20238
20570
|
if (dependencyTracker) {
|
|
20239
20571
|
this.dependencyTracker = dependencyTracker;
|
|
20240
20572
|
}
|
|
@@ -20253,7 +20585,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20253
20585
|
if (IR[0] === "TilingPattern") {
|
|
20254
20586
|
const baseTransform = this.baseTransform || getCurrentTransform(this.ctx);
|
|
20255
20587
|
const canvasGraphicsFactory = {
|
|
20256
|
-
createCanvasGraphics: (
|
|
20588
|
+
createCanvasGraphics: (ctx2, renderingOpIdx) => new _CanvasGraphics(ctx2, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {
|
|
20257
20589
|
optionalContentConfig: this.optionalContentConfig,
|
|
20258
20590
|
markedContentStack: this.markedContentStack
|
|
20259
20591
|
}, void 0, void 0, this.dependencyTracker ? new CanvasNestedDependencyTracker(this.dependencyTracker, renderingOpIdx, true) : null)
|
|
@@ -20309,16 +20641,16 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20309
20641
|
return;
|
|
20310
20642
|
}
|
|
20311
20643
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20312
|
-
const
|
|
20644
|
+
const ctx2 = this.ctx;
|
|
20313
20645
|
this.save(opIdx);
|
|
20314
20646
|
const pattern = this._getPattern(opIdx, objId);
|
|
20315
|
-
|
|
20316
|
-
const inv = getCurrentTransformInverse(
|
|
20647
|
+
ctx2.fillStyle = pattern.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.SHADING, opIdx);
|
|
20648
|
+
const inv = getCurrentTransformInverse(ctx2);
|
|
20317
20649
|
if (inv) {
|
|
20318
20650
|
const {
|
|
20319
20651
|
width,
|
|
20320
20652
|
height
|
|
20321
|
-
} =
|
|
20653
|
+
} = ctx2.canvas;
|
|
20322
20654
|
const minMax = F32_BBOX_INIT.slice();
|
|
20323
20655
|
Util.axialAlignedBoundingBox([0, 0, width, height], inv, minMax);
|
|
20324
20656
|
const [x0, y0, x1, y1] = minMax;
|
|
@@ -20490,19 +20822,19 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20490
20822
|
}
|
|
20491
20823
|
this.groupLevel--;
|
|
20492
20824
|
const groupCtx = this.ctx;
|
|
20493
|
-
const
|
|
20825
|
+
const ctx2 = this.groupStack.pop();
|
|
20494
20826
|
const groupMeta = this.#groupStackMeta.pop();
|
|
20495
20827
|
if (groupMeta) {
|
|
20496
20828
|
this.#knockoutGroupLevel = groupMeta.savedKnockoutLevel;
|
|
20497
20829
|
}
|
|
20498
|
-
if (
|
|
20830
|
+
if (ctx2 === null) {
|
|
20499
20831
|
this.restore(opIdx);
|
|
20500
20832
|
return;
|
|
20501
20833
|
}
|
|
20502
20834
|
if (group.isGray) {
|
|
20503
20835
|
this.#convertGroupToGray(groupCtx);
|
|
20504
20836
|
}
|
|
20505
|
-
this.ctx =
|
|
20837
|
+
this.ctx = ctx2;
|
|
20506
20838
|
this.ctx.imageSmoothingEnabled = false;
|
|
20507
20839
|
this.dependencyTracker?.popBaseTransform();
|
|
20508
20840
|
if (group.smask) {
|
|
@@ -20532,7 +20864,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20532
20864
|
} = groupCtx.canvas;
|
|
20533
20865
|
const colorEntry = this.canvasFactory.create(width, height);
|
|
20534
20866
|
const colorCtx = colorEntry.context;
|
|
20535
|
-
colorCtx.drawImage(
|
|
20867
|
+
colorCtx.drawImage(ctx2.canvas, groupMeta.offsetX, groupMeta.offsetY, width, height, 0, 0, width, height);
|
|
20536
20868
|
colorCtx.globalCompositeOperation = "source-over";
|
|
20537
20869
|
colorCtx.drawImage(groupCtx.canvas, 0, 0);
|
|
20538
20870
|
const shapeMaskEntry = this.#createKnockoutMaskCanvas(groupCtx.canvas);
|
|
@@ -20706,14 +21038,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20706
21038
|
img = this.getObject(opIdx, img.data, img);
|
|
20707
21039
|
img.count = count;
|
|
20708
21040
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20709
|
-
const
|
|
21041
|
+
const ctx2 = this.ctx;
|
|
20710
21042
|
const mask = this._createMaskCanvas(opIdx, img);
|
|
20711
21043
|
const maskCanvas = mask.canvas;
|
|
20712
|
-
|
|
20713
|
-
|
|
20714
|
-
|
|
21044
|
+
ctx2.save();
|
|
21045
|
+
ctx2.setTransform(1, 0, 0, 1, 0, 0);
|
|
21046
|
+
ctx2.drawImage(maskCanvas, mask.offsetX, mask.offsetY);
|
|
20715
21047
|
this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, mask.offsetX, mask.offsetX + maskCanvas.width, mask.offsetY, mask.offsetY + maskCanvas.height).recordOperation(opIdx);
|
|
20716
|
-
|
|
21048
|
+
ctx2.restore();
|
|
20717
21049
|
if (mask.canvasEntry) {
|
|
20718
21050
|
this.canvasFactory.destroy(mask.canvasEntry);
|
|
20719
21051
|
}
|
|
@@ -20726,19 +21058,19 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20726
21058
|
}
|
|
20727
21059
|
img = this.getObject(opIdx, img.data, img);
|
|
20728
21060
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20729
|
-
const
|
|
20730
|
-
|
|
20731
|
-
const currentTransform = getCurrentTransform(
|
|
20732
|
-
|
|
21061
|
+
const ctx2 = this.ctx;
|
|
21062
|
+
ctx2.save();
|
|
21063
|
+
const currentTransform = getCurrentTransform(ctx2);
|
|
21064
|
+
ctx2.transform(scaleX, skewX, skewY, scaleY, 0, 0);
|
|
20733
21065
|
const mask = this._createMaskCanvas(opIdx, img);
|
|
20734
|
-
|
|
21066
|
+
ctx2.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]);
|
|
20735
21067
|
this.dependencyTracker?.resetBBox(opIdx);
|
|
20736
21068
|
for (let i = 0, ii = positions.length; i < ii; i += 2) {
|
|
20737
21069
|
const trans = Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]);
|
|
20738
|
-
|
|
21070
|
+
ctx2.drawImage(mask.canvas, trans[4], trans[5]);
|
|
20739
21071
|
this.dependencyTracker?.recordBBox(opIdx, this.ctx, trans[4], trans[4] + mask.canvas.width, trans[5], trans[5] + mask.canvas.height);
|
|
20740
21072
|
}
|
|
20741
|
-
|
|
21073
|
+
ctx2.restore();
|
|
20742
21074
|
if (mask.canvasEntry) {
|
|
20743
21075
|
this.canvasFactory.destroy(mask.canvasEntry);
|
|
20744
21076
|
}
|
|
@@ -20751,7 +21083,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20751
21083
|
return;
|
|
20752
21084
|
}
|
|
20753
21085
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20754
|
-
const
|
|
21086
|
+
const ctx2 = this.ctx;
|
|
20755
21087
|
const fillColor = this.current.fillColor;
|
|
20756
21088
|
const isPatternFill = this.current.patternFill;
|
|
20757
21089
|
this.dependencyTracker?.resetBBox(opIdx).recordDependencies(opIdx, Dependencies.transformAndFill);
|
|
@@ -20768,16 +21100,16 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20768
21100
|
const img = this.getObject(opIdx, data, image);
|
|
20769
21101
|
putBinaryImageMask(maskCtx, img);
|
|
20770
21102
|
maskCtx.globalCompositeOperation = "source-in";
|
|
20771
|
-
maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(
|
|
21103
|
+
maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(ctx2), PathType.FILL, opIdx) : fillColor;
|
|
20772
21104
|
maskCtx.fillRect(0, 0, width, height);
|
|
20773
21105
|
maskCtx.restore();
|
|
20774
|
-
|
|
20775
|
-
|
|
20776
|
-
|
|
20777
|
-
drawImageAtIntegerCoords(
|
|
21106
|
+
ctx2.save();
|
|
21107
|
+
ctx2.transform(...transform);
|
|
21108
|
+
ctx2.scale(1, -1);
|
|
21109
|
+
drawImageAtIntegerCoords(ctx2, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
|
|
20778
21110
|
this.canvasFactory.destroy(maskCanvas);
|
|
20779
|
-
this.dependencyTracker?.recordBBox(opIdx,
|
|
20780
|
-
|
|
21111
|
+
this.dependencyTracker?.recordBBox(opIdx, ctx2, 0, width, 0, height);
|
|
21112
|
+
ctx2.restore();
|
|
20781
21113
|
}
|
|
20782
21114
|
this.compose();
|
|
20783
21115
|
this.dependencyTracker?.recordOperation(opIdx);
|
|
@@ -20817,13 +21149,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20817
21149
|
}
|
|
20818
21150
|
this.paintInlineImageXObjectGroup(opIdx, imgData, map);
|
|
20819
21151
|
}
|
|
20820
|
-
applyTransferMapsToCanvas(
|
|
21152
|
+
applyTransferMapsToCanvas(ctx2) {
|
|
20821
21153
|
if (this.current.transferMaps !== "none") {
|
|
20822
|
-
|
|
20823
|
-
|
|
20824
|
-
|
|
21154
|
+
ctx2.filter = this.current.transferMaps;
|
|
21155
|
+
ctx2.drawImage(ctx2.canvas, 0, 0);
|
|
21156
|
+
ctx2.filter = "none";
|
|
20825
21157
|
}
|
|
20826
|
-
return
|
|
21158
|
+
return ctx2.canvas;
|
|
20827
21159
|
}
|
|
20828
21160
|
applyTransferMapsToBitmap(imgData) {
|
|
20829
21161
|
if (this.current.transferMaps === "none") {
|
|
@@ -20854,15 +21186,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20854
21186
|
const width = imgData.width;
|
|
20855
21187
|
const height = imgData.height;
|
|
20856
21188
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20857
|
-
const
|
|
21189
|
+
const ctx2 = this.ctx;
|
|
20858
21190
|
this.save(opIdx);
|
|
20859
21191
|
const {
|
|
20860
21192
|
filter
|
|
20861
|
-
} =
|
|
21193
|
+
} = ctx2;
|
|
20862
21194
|
if (filter !== "none" && filter !== "") {
|
|
20863
|
-
|
|
21195
|
+
ctx2.filter = "none";
|
|
20864
21196
|
}
|
|
20865
|
-
|
|
21197
|
+
ctx2.scale(1 / width, -1 / height);
|
|
20866
21198
|
let imgToPaint;
|
|
20867
21199
|
let inlineImgCanvas = null;
|
|
20868
21200
|
if (imgData.bitmap) {
|
|
@@ -20875,13 +21207,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20875
21207
|
imgToPaint = this.applyTransferMapsToCanvas(tmpCanvas.context);
|
|
20876
21208
|
inlineImgCanvas = tmpCanvas;
|
|
20877
21209
|
}
|
|
20878
|
-
const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(
|
|
20879
|
-
|
|
21210
|
+
const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(ctx2));
|
|
21211
|
+
ctx2.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(ctx2), imgData.interpolate);
|
|
20880
21212
|
if (this.dependencyTracker) {
|
|
20881
|
-
this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx,
|
|
20882
|
-
this.imagesTracker?.record(
|
|
21213
|
+
this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx, ctx2, 0, width, -height, 0).recordDependencies(opIdx, Dependencies.imageXObject).recordOperation(opIdx);
|
|
21214
|
+
this.imagesTracker?.record(ctx2, width, height, this.dependencyTracker.clipBox);
|
|
20883
21215
|
}
|
|
20884
|
-
drawImageAtIntegerCoords(
|
|
21216
|
+
drawImageAtIntegerCoords(ctx2, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height);
|
|
20885
21217
|
if (scaled.tmpCanvas) {
|
|
20886
21218
|
this.canvasFactory.destroy(scaled.tmpCanvas);
|
|
20887
21219
|
}
|
|
@@ -20897,7 +21229,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20897
21229
|
return;
|
|
20898
21230
|
}
|
|
20899
21231
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20900
|
-
const
|
|
21232
|
+
const ctx2 = this.ctx;
|
|
20901
21233
|
let imgToPaint;
|
|
20902
21234
|
let inlineImgCanvas = null;
|
|
20903
21235
|
if (imgData.bitmap) {
|
|
@@ -20912,12 +21244,12 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20912
21244
|
}
|
|
20913
21245
|
this.dependencyTracker?.resetBBox(opIdx);
|
|
20914
21246
|
for (const entry of map) {
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
drawImageAtIntegerCoords(
|
|
20919
|
-
this.dependencyTracker?.recordBBox(opIdx,
|
|
20920
|
-
|
|
21247
|
+
ctx2.save();
|
|
21248
|
+
ctx2.transform(...entry.transform);
|
|
21249
|
+
ctx2.scale(1, -1);
|
|
21250
|
+
drawImageAtIntegerCoords(ctx2, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
|
|
21251
|
+
this.dependencyTracker?.recordBBox(opIdx, ctx2, 0, 1, -1, 0);
|
|
21252
|
+
ctx2.restore();
|
|
20921
21253
|
}
|
|
20922
21254
|
if (inlineImgCanvas) {
|
|
20923
21255
|
this.canvasFactory.destroy(inlineImgCanvas);
|
|
@@ -20976,13 +21308,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20976
21308
|
if (!this.pendingClip) {
|
|
20977
21309
|
this.compose(clipBox);
|
|
20978
21310
|
}
|
|
20979
|
-
const
|
|
21311
|
+
const ctx2 = this.ctx;
|
|
20980
21312
|
if (this.pendingClip) {
|
|
20981
21313
|
if (!isEmpty) {
|
|
20982
21314
|
if (this.pendingClip === EO_CLIP) {
|
|
20983
|
-
|
|
21315
|
+
ctx2.clip(path, "evenodd");
|
|
20984
21316
|
} else {
|
|
20985
|
-
|
|
21317
|
+
ctx2.clip(path);
|
|
20986
21318
|
}
|
|
20987
21319
|
}
|
|
20988
21320
|
this.pendingClip = null;
|
|
@@ -21057,36 +21389,36 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
21057
21389
|
}
|
|
21058
21390
|
rescaleAndStroke(path, saveRestore) {
|
|
21059
21391
|
const {
|
|
21060
|
-
ctx,
|
|
21392
|
+
ctx: ctx2,
|
|
21061
21393
|
current: {
|
|
21062
21394
|
lineWidth
|
|
21063
21395
|
}
|
|
21064
21396
|
} = this;
|
|
21065
21397
|
const [scaleX, scaleY] = this.getScaleForStroking();
|
|
21066
21398
|
if (scaleX === scaleY) {
|
|
21067
|
-
|
|
21068
|
-
|
|
21399
|
+
ctx2.lineWidth = (lineWidth || 1) * scaleX;
|
|
21400
|
+
ctx2.stroke(path);
|
|
21069
21401
|
return;
|
|
21070
21402
|
}
|
|
21071
21403
|
const SCALE_MATRIX = _CanvasGraphics.#SCALE_MATRIX ??= new DOMMatrix();
|
|
21072
|
-
const dashes =
|
|
21404
|
+
const dashes = ctx2.getLineDash();
|
|
21073
21405
|
if (saveRestore) {
|
|
21074
|
-
|
|
21406
|
+
ctx2.save();
|
|
21075
21407
|
}
|
|
21076
|
-
|
|
21408
|
+
ctx2.scale(scaleX, scaleY);
|
|
21077
21409
|
SCALE_MATRIX.a = 1 / scaleX;
|
|
21078
21410
|
SCALE_MATRIX.d = 1 / scaleY;
|
|
21079
21411
|
const newPath = new Path2D();
|
|
21080
21412
|
newPath.addPath(path, SCALE_MATRIX);
|
|
21081
21413
|
if (dashes.length > 0) {
|
|
21082
21414
|
const scale = Math.max(scaleX, scaleY);
|
|
21083
|
-
|
|
21084
|
-
|
|
21415
|
+
ctx2.setLineDash(dashes.map((x) => x / scale));
|
|
21416
|
+
ctx2.lineDashOffset /= scale;
|
|
21085
21417
|
}
|
|
21086
|
-
|
|
21087
|
-
|
|
21418
|
+
ctx2.lineWidth = lineWidth || 1;
|
|
21419
|
+
ctx2.stroke(newPath);
|
|
21088
21420
|
if (saveRestore) {
|
|
21089
|
-
|
|
21421
|
+
ctx2.restore();
|
|
21090
21422
|
}
|
|
21091
21423
|
}
|
|
21092
21424
|
isContentVisible() {
|
|
@@ -22785,7 +23117,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22785
23117
|
const {
|
|
22786
23118
|
div,
|
|
22787
23119
|
properties,
|
|
22788
|
-
ctx
|
|
23120
|
+
ctx: ctx2
|
|
22789
23121
|
} = params;
|
|
22790
23122
|
const {
|
|
22791
23123
|
style
|
|
@@ -22798,10 +23130,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22798
23130
|
canvasWidth,
|
|
22799
23131
|
fontSize
|
|
22800
23132
|
} = properties;
|
|
22801
|
-
_TextLayer.#ensureCtxFont(
|
|
23133
|
+
_TextLayer.#ensureCtxFont(ctx2, fontSize * this.#scale, fontFamily);
|
|
22802
23134
|
const {
|
|
22803
23135
|
width
|
|
22804
|
-
} =
|
|
23136
|
+
} = ctx2.measureText(div.textContent);
|
|
22805
23137
|
if (width > 0) {
|
|
22806
23138
|
style.setProperty("--scale-x", canvasWidth * this.#scale / width);
|
|
22807
23139
|
}
|
|
@@ -22823,30 +23155,30 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22823
23155
|
this.#canvasContexts.clear();
|
|
22824
23156
|
}
|
|
22825
23157
|
static #getCtx(lang = null) {
|
|
22826
|
-
let
|
|
22827
|
-
if (!
|
|
23158
|
+
let ctx2 = this.#canvasContexts.get(lang ||= "");
|
|
23159
|
+
if (!ctx2) {
|
|
22828
23160
|
const canvas = document.createElement("canvas");
|
|
22829
23161
|
canvas.style.cssText = "position:absolute;top:0;left:0;width:0;height:0;display:none;letter-spacing:normal;word-spacing:normal";
|
|
22830
23162
|
canvas.lang = lang;
|
|
22831
23163
|
document.body.append(canvas);
|
|
22832
|
-
|
|
23164
|
+
ctx2 = canvas.getContext("2d", {
|
|
22833
23165
|
alpha: false,
|
|
22834
23166
|
willReadFrequently: true
|
|
22835
23167
|
});
|
|
22836
|
-
this.#canvasContexts.set(lang,
|
|
22837
|
-
this.#canvasCtxFonts.set(
|
|
23168
|
+
this.#canvasContexts.set(lang, ctx2);
|
|
23169
|
+
this.#canvasCtxFonts.set(ctx2, {
|
|
22838
23170
|
size: 0,
|
|
22839
23171
|
family: ""
|
|
22840
23172
|
});
|
|
22841
23173
|
}
|
|
22842
|
-
return
|
|
23174
|
+
return ctx2;
|
|
22843
23175
|
}
|
|
22844
|
-
static #ensureCtxFont(
|
|
22845
|
-
const cached3 = this.#canvasCtxFonts.get(
|
|
23176
|
+
static #ensureCtxFont(ctx2, size, family) {
|
|
23177
|
+
const cached3 = this.#canvasCtxFonts.get(ctx2);
|
|
22846
23178
|
if (size === cached3.size && family === cached3.family) {
|
|
22847
23179
|
return;
|
|
22848
23180
|
}
|
|
22849
|
-
|
|
23181
|
+
ctx2.font = `${size}px ${family}`;
|
|
22850
23182
|
cached3.size = size;
|
|
22851
23183
|
cached3.family = family;
|
|
22852
23184
|
}
|
|
@@ -22869,13 +23201,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22869
23201
|
if (cachedAscent) {
|
|
22870
23202
|
return cachedAscent;
|
|
22871
23203
|
}
|
|
22872
|
-
const
|
|
22873
|
-
|
|
22874
|
-
this.#ensureCtxFont(
|
|
22875
|
-
const metrics =
|
|
23204
|
+
const ctx2 = this.#getCtx(lang);
|
|
23205
|
+
ctx2.canvas.width = ctx2.canvas.height = DEFAULT_FONT_SIZE;
|
|
23206
|
+
this.#ensureCtxFont(ctx2, DEFAULT_FONT_SIZE, fontFamily);
|
|
23207
|
+
const metrics = ctx2.measureText("");
|
|
22876
23208
|
const ascent = metrics.fontBoundingBoxAscent;
|
|
22877
23209
|
const descent = Math.abs(metrics.fontBoundingBoxDescent);
|
|
22878
|
-
|
|
23210
|
+
ctx2.canvas.width = ctx2.canvas.height = 0;
|
|
22879
23211
|
let ratio = 0.8;
|
|
22880
23212
|
if (ascent) {
|
|
22881
23213
|
ratio = ascent / (ascent + descent);
|
|
@@ -32615,8 +32947,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32615
32947
|
newWidth = Math.ceil(prevWidth / 2);
|
|
32616
32948
|
newHeight = Math.ceil(prevHeight / 2);
|
|
32617
32949
|
const offscreen2 = new OffscreenCanvas(newWidth, newHeight);
|
|
32618
|
-
const
|
|
32619
|
-
|
|
32950
|
+
const ctx3 = offscreen2.getContext("2d");
|
|
32951
|
+
ctx3.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
|
|
32620
32952
|
prevWidth = newWidth;
|
|
32621
32953
|
prevHeight = newHeight;
|
|
32622
32954
|
if (bitmap !== originalBitmap) {
|
|
@@ -32629,14 +32961,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32629
32961
|
newHeight = Math.round(newHeight * ratio);
|
|
32630
32962
|
}
|
|
32631
32963
|
const offscreen = new OffscreenCanvas(newWidth, newHeight);
|
|
32632
|
-
const
|
|
32964
|
+
const ctx2 = offscreen.getContext("2d", {
|
|
32633
32965
|
willReadFrequently: true
|
|
32634
32966
|
});
|
|
32635
|
-
|
|
32636
|
-
|
|
32637
|
-
|
|
32638
|
-
|
|
32639
|
-
const grayImage =
|
|
32967
|
+
ctx2.fillStyle = "white";
|
|
32968
|
+
ctx2.fillRect(0, 0, newWidth, newHeight);
|
|
32969
|
+
ctx2.filter = "grayscale(1)";
|
|
32970
|
+
ctx2.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, newWidth, newHeight);
|
|
32971
|
+
const grayImage = ctx2.getImageData(0, 0, newWidth, newHeight).data;
|
|
32640
32972
|
const uint8Buf = this.#toUint8(grayImage);
|
|
32641
32973
|
return [uint8Buf, newWidth, newHeight];
|
|
32642
32974
|
}
|
|
@@ -32646,11 +32978,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32646
32978
|
fontWeight
|
|
32647
32979
|
}, pageWidth, pageHeight, rotation, innerMargin) {
|
|
32648
32980
|
let canvas = new OffscreenCanvas(1, 1);
|
|
32649
|
-
let
|
|
32981
|
+
let ctx2 = canvas.getContext("2d", {
|
|
32650
32982
|
alpha: false
|
|
32651
32983
|
});
|
|
32652
32984
|
const fontSize = 200;
|
|
32653
|
-
const font =
|
|
32985
|
+
const font = ctx2.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
32654
32986
|
const {
|
|
32655
32987
|
actualBoundingBoxLeft,
|
|
32656
32988
|
actualBoundingBoxRight,
|
|
@@ -32659,22 +32991,22 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32659
32991
|
fontBoundingBoxAscent,
|
|
32660
32992
|
fontBoundingBoxDescent,
|
|
32661
32993
|
width
|
|
32662
|
-
} =
|
|
32994
|
+
} = ctx2.measureText(text);
|
|
32663
32995
|
const SCALE = 1.5;
|
|
32664
32996
|
const canvasWidth = Math.ceil(Math.max(Math.abs(actualBoundingBoxLeft) + Math.abs(actualBoundingBoxRight) || 0, width) * SCALE);
|
|
32665
32997
|
const canvasHeight = Math.ceil(Math.max(Math.abs(actualBoundingBoxAscent) + Math.abs(actualBoundingBoxDescent) || fontSize, Math.abs(fontBoundingBoxAscent) + Math.abs(fontBoundingBoxDescent) || fontSize) * SCALE);
|
|
32666
32998
|
canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
|
|
32667
|
-
|
|
32999
|
+
ctx2 = canvas.getContext("2d", {
|
|
32668
33000
|
alpha: true,
|
|
32669
33001
|
willReadFrequently: true
|
|
32670
33002
|
});
|
|
32671
|
-
|
|
32672
|
-
|
|
32673
|
-
|
|
32674
|
-
|
|
32675
|
-
|
|
32676
|
-
|
|
32677
|
-
const uint8Buf = this.#toUint8(
|
|
33003
|
+
ctx2.font = font;
|
|
33004
|
+
ctx2.filter = "grayscale(1)";
|
|
33005
|
+
ctx2.fillStyle = "white";
|
|
33006
|
+
ctx2.fillRect(0, 0, canvasWidth, canvasHeight);
|
|
33007
|
+
ctx2.fillStyle = "black";
|
|
33008
|
+
ctx2.fillText(text, canvasWidth * (SCALE - 1) / 2, canvasHeight * (3 - SCALE) / 2);
|
|
33009
|
+
const uint8Buf = this.#toUint8(ctx2.getImageData(0, 0, canvasWidth, canvasHeight).data);
|
|
32678
33010
|
const histogram = this.#getHistogram(uint8Buf);
|
|
32679
33011
|
const threshold = this.#guessThreshold(histogram);
|
|
32680
33012
|
const contourList = this.#findContours(uint8Buf, canvasWidth, canvasHeight, threshold);
|
|
@@ -33640,8 +33972,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33640
33972
|
if (!this.#isSvg) {
|
|
33641
33973
|
bitmap = this.#scaleBitmap(scaledWidth, scaledHeight);
|
|
33642
33974
|
}
|
|
33643
|
-
const
|
|
33644
|
-
|
|
33975
|
+
const ctx2 = canvas.getContext("2d");
|
|
33976
|
+
ctx2.filter = this._uiManager.hcmFilter;
|
|
33645
33977
|
let white = "white", black = "#cfcfd8";
|
|
33646
33978
|
if (this._uiManager.hcmFilter !== "none") {
|
|
33647
33979
|
black = "black";
|
|
@@ -33659,9 +33991,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33659
33991
|
patternCtx.fillStyle = black;
|
|
33660
33992
|
patternCtx.fillRect(0, 0, boxDimWidth, boxDimHeight);
|
|
33661
33993
|
patternCtx.fillRect(boxDimWidth, boxDimHeight, boxDimWidth, boxDimHeight);
|
|
33662
|
-
|
|
33663
|
-
|
|
33664
|
-
|
|
33994
|
+
ctx2.fillStyle = ctx2.createPattern(pattern, "repeat");
|
|
33995
|
+
ctx2.fillRect(0, 0, scaledWidth, scaledHeight);
|
|
33996
|
+
ctx2.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight);
|
|
33665
33997
|
}
|
|
33666
33998
|
let imageData = null;
|
|
33667
33999
|
if (createImageData) {
|
|
@@ -33716,8 +34048,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33716
34048
|
newHeight = Math.ceil(newHeight / 2);
|
|
33717
34049
|
}
|
|
33718
34050
|
const offscreen = new OffscreenCanvas(newWidth, newHeight);
|
|
33719
|
-
const
|
|
33720
|
-
|
|
34051
|
+
const ctx2 = offscreen.getContext("2d");
|
|
34052
|
+
ctx2.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
|
|
33721
34053
|
bitmap = offscreen.transferToImageBitmap();
|
|
33722
34054
|
}
|
|
33723
34055
|
return bitmap;
|
|
@@ -33738,9 +34070,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33738
34070
|
canvas.width = scaledWidth;
|
|
33739
34071
|
canvas.height = scaledHeight;
|
|
33740
34072
|
const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(scaledWidth, scaledHeight);
|
|
33741
|
-
const
|
|
33742
|
-
|
|
33743
|
-
|
|
34073
|
+
const ctx2 = canvas.getContext("2d");
|
|
34074
|
+
ctx2.filter = this._uiManager.hcmFilter;
|
|
34075
|
+
ctx2.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight);
|
|
33744
34076
|
}
|
|
33745
34077
|
#serializeBitmap(toUrl) {
|
|
33746
34078
|
if (toUrl) {
|
|
@@ -33755,8 +34087,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33755
34087
|
width: canvas.width,
|
|
33756
34088
|
height: canvas.height
|
|
33757
34089
|
} = this.#bitmap);
|
|
33758
|
-
const
|
|
33759
|
-
|
|
34090
|
+
const ctx2 = canvas.getContext("2d");
|
|
34091
|
+
ctx2.drawImage(this.#bitmap, 0, 0);
|
|
33760
34092
|
return canvas.toDataURL();
|
|
33761
34093
|
}
|
|
33762
34094
|
if (this.#isSvg) {
|
|
@@ -33764,8 +34096,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33764
34096
|
const width = Math.round(this.width * pageWidth * PixelsPerInch.PDF_TO_CSS_UNITS);
|
|
33765
34097
|
const height = Math.round(this.height * pageHeight * PixelsPerInch.PDF_TO_CSS_UNITS);
|
|
33766
34098
|
const offscreen = new OffscreenCanvas(width, height);
|
|
33767
|
-
const
|
|
33768
|
-
|
|
34099
|
+
const ctx2 = offscreen.getContext("2d");
|
|
34100
|
+
ctx2.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height);
|
|
33769
34101
|
return offscreen.transferToImageBitmap();
|
|
33770
34102
|
}
|
|
33771
34103
|
return structuredClone(this.#bitmap);
|
|
@@ -35264,10 +35596,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
35264
35596
|
const imageY2 = Math.floor((y1 + height / this.#pageHeight) * pageCanvas.height);
|
|
35265
35597
|
imgElement.width = imageX2 - imageX1;
|
|
35266
35598
|
imgElement.height = imageY2 - imageY1;
|
|
35267
|
-
const
|
|
35268
|
-
|
|
35269
|
-
|
|
35270
|
-
|
|
35599
|
+
const ctx2 = imgElement.getContext("2d");
|
|
35600
|
+
ctx2.setTransform(...inverseTransform);
|
|
35601
|
+
ctx2.translate(-imageX1, -imageY1);
|
|
35602
|
+
ctx2.drawImage(pageCanvas, 0, 0);
|
|
35271
35603
|
});
|
|
35272
35604
|
return container;
|
|
35273
35605
|
}
|
|
@@ -35385,7 +35717,7 @@ async function pdfjs() {
|
|
|
35385
35717
|
return pdfjsPromise;
|
|
35386
35718
|
}
|
|
35387
35719
|
async function extractPdfText(pdfPath, { maxChars = DEFAULT_MAX_CHARS, force = false } = {}) {
|
|
35388
|
-
const hit =
|
|
35720
|
+
const hit = cache2.get(pdfPath);
|
|
35389
35721
|
if (!force && hit && Date.now() - hit.at < CACHE_TTL_MS) return hit.text;
|
|
35390
35722
|
const data = new Uint8Array(await readFile4(pdfPath));
|
|
35391
35723
|
const getDocument2 = (await pdfjs()).getDocument;
|
|
@@ -35407,16 +35739,16 @@ async function extractPdfText(pdfPath, { maxChars = DEFAULT_MAX_CHARS, force = f
|
|
|
35407
35739
|
doc.cleanup?.();
|
|
35408
35740
|
}
|
|
35409
35741
|
const text = chunks.join("\n").trim();
|
|
35410
|
-
|
|
35742
|
+
cache2.set(pdfPath, { text, at: Date.now() });
|
|
35411
35743
|
return text;
|
|
35412
35744
|
}
|
|
35413
|
-
var DEFAULT_MAX_CHARS, CACHE_TTL_MS,
|
|
35745
|
+
var DEFAULT_MAX_CHARS, CACHE_TTL_MS, cache2, pdfjsPromise;
|
|
35414
35746
|
var init_pdf_text = __esm({
|
|
35415
35747
|
"src/node/pdf-text.js"() {
|
|
35416
35748
|
init_log();
|
|
35417
35749
|
DEFAULT_MAX_CHARS = 12e4;
|
|
35418
35750
|
CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
35419
|
-
|
|
35751
|
+
cache2 = /* @__PURE__ */ new Map();
|
|
35420
35752
|
pdfjsPromise = null;
|
|
35421
35753
|
}
|
|
35422
35754
|
});
|
|
@@ -35425,7 +35757,8 @@ var init_pdf_text = __esm({
|
|
|
35425
35757
|
var ai_exports = {};
|
|
35426
35758
|
__export(ai_exports, {
|
|
35427
35759
|
askAi: () => askAi,
|
|
35428
|
-
buildPrompt: () => buildPrompt
|
|
35760
|
+
buildPrompt: () => buildPrompt,
|
|
35761
|
+
sendFigure: () => sendFigure
|
|
35429
35762
|
});
|
|
35430
35763
|
function buildPrompt({ title, action, question = "", selection = "", text = "" }) {
|
|
35431
35764
|
const head = `\u3010\u6587\u732E\u52A9\u624B \xB7 ${title}\u3011`;
|
|
@@ -35472,7 +35805,7 @@ ${text}
|
|
|
35472
35805
|
"""`;
|
|
35473
35806
|
}
|
|
35474
35807
|
}
|
|
35475
|
-
async function askAi(
|
|
35808
|
+
async function askAi(ctx2, { key, action = "ask", question = "", selection = "", sessionId = null } = {}) {
|
|
35476
35809
|
const entry = await getItem(String(key ?? ""));
|
|
35477
35810
|
if (!entry) throw Object.assign(new Error("\u6761\u76EE\u4E0D\u5B58\u5728"), { code: "not_found" });
|
|
35478
35811
|
if (!["translate", "explain", "summarize", "tldr", "ask"].includes(action)) action = "ask";
|
|
@@ -35480,7 +35813,7 @@ async function askAi(ctx, { key, action = "ask", question = "", selection = "",
|
|
|
35480
35813
|
if (!sid) {
|
|
35481
35814
|
throw Object.assign(new Error("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u5BF9\u8BDD\uFF0C\u8BF7\u5148\u5F00\u59CB\u4E00\u4E2A\u5BF9\u8BDD\u518D\u8BD5"), { code: "no_session" });
|
|
35482
35815
|
}
|
|
35483
|
-
const agent =
|
|
35816
|
+
const agent = ctx2?.agents?.get?.(sid);
|
|
35484
35817
|
if (!agent || typeof agent.steer !== "function") {
|
|
35485
35818
|
throw Object.assign(new Error("\u5F53\u524D\u5BF9\u8BDD\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5"), { code: "no_session" });
|
|
35486
35819
|
}
|
|
@@ -35517,6 +35850,38 @@ async function askAi(ctx, { key, action = "ask", question = "", selection = "",
|
|
|
35517
35850
|
log(`ai ask steered (${action}) into session ${sid}`);
|
|
35518
35851
|
return { ok: true, sessionId: sid, action };
|
|
35519
35852
|
}
|
|
35853
|
+
async function sendFigure(ctx2, { png, caption = "", title = "\u793A\u610F\u56FE", sessionId = null } = {}) {
|
|
35854
|
+
if (!png || !png.length) throw Object.assign(new Error("\u6CA1\u6709\u56FE\u7247\u6570\u636E"), { code: "no_image" });
|
|
35855
|
+
const sid = sessionId && String(sessionId) || recentSession();
|
|
35856
|
+
if (!sid) throw Object.assign(new Error("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u5BF9\u8BDD\uFF0C\u8BF7\u5148\u5F00\u59CB\u4E00\u4E2A\u5BF9\u8BDD\u518D\u8BD5"), { code: "no_session" });
|
|
35857
|
+
const agent = ctx2?.agents?.get?.(sid);
|
|
35858
|
+
if (!agent || typeof agent.steer !== "function") {
|
|
35859
|
+
throw Object.assign(new Error("\u5F53\u524D\u5BF9\u8BDD\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5"), { code: "no_session" });
|
|
35860
|
+
}
|
|
35861
|
+
if (!ctx2?.attachments?.saveImages) {
|
|
35862
|
+
throw Object.assign(new Error("\u5BBF\u4E3B\u4E0D\u652F\u6301\u56FE\u7247\u9644\u4EF6"), { code: "no_attachments" });
|
|
35863
|
+
}
|
|
35864
|
+
let bytes = png;
|
|
35865
|
+
const limits = ctx2.attachments.imageLimits ?? {};
|
|
35866
|
+
const maxBytes = limits.maxImageBytes ?? 5 * 1024 * 1024;
|
|
35867
|
+
if (bytes.length > maxBytes) {
|
|
35868
|
+
throw Object.assign(new Error(`\u56FE\u7247\u8D85\u8FC7\u5BBF\u4E3B\u5927\u5C0F\u9650\u5236\uFF08${bytes.length} > ${maxBytes} \u5B57\u8282\uFF09`), { code: "too_large" });
|
|
35869
|
+
}
|
|
35870
|
+
const mediaType = limits.mediaTypes?.length ? limits.mediaTypes.includes("image/png") ? "image/png" : limits.mediaTypes[0] : "image/png";
|
|
35871
|
+
const [ref] = await ctx2.attachments.saveImages([{ data: new Uint8Array(bytes), mediaType, name: title.slice(0, 60) }]);
|
|
35872
|
+
if (!ref) throw Object.assign(new Error("\u56FE\u7247\u9644\u4EF6\u521B\u5EFA\u5931\u8D25"), { code: "no_attachments" });
|
|
35873
|
+
const text = `\u3010\u6587\u732E\u52A9\u624B \xB7 ${title}\u3011
|
|
35874
|
+
${caption || "\u6839\u636E\u6570\u636E\u751F\u6210\u7684\u793A\u610F\u56FE\u3002"}
|
|
35875
|
+
\uFF08\u56FE\u7531\u63D2\u4EF6\u6839\u636E\u539F\u59CB\u6570\u636E\u7ED8\u5236\uFF0C\u975E\u539F\u6587\u63D2\u56FE\uFF09`;
|
|
35876
|
+
try {
|
|
35877
|
+
const { createUserMessage } = await import("@deepseek-ai/dsh-llm");
|
|
35878
|
+
agent.steer(createUserMessage({ content: [{ type: "text", text }, { type: "image", attachment: ref }], source: { kind: "user" } }));
|
|
35879
|
+
} catch {
|
|
35880
|
+
agent.steer({ content: [{ type: "text", text }, { type: "image", attachment: ref }], source: { kind: "user" }, role: "user", id: `lit_fig_${Date.now()}` });
|
|
35881
|
+
}
|
|
35882
|
+
log(`figure steered into session ${sid}`);
|
|
35883
|
+
return { ok: true, sessionId: sid };
|
|
35884
|
+
}
|
|
35520
35885
|
var FULLTEXT_ACTIONS, MAX_CONTEXT_CHARS;
|
|
35521
35886
|
var init_ai = __esm({
|
|
35522
35887
|
"src/node/ai.js"() {
|
|
@@ -35538,13 +35903,13 @@ __export(doctor_selfheal_exports, {
|
|
|
35538
35903
|
pipeAvailable: () => pipeAvailable
|
|
35539
35904
|
});
|
|
35540
35905
|
import { createHash } from "node:crypto";
|
|
35541
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
35542
|
-
import { join as
|
|
35543
|
-
import { homedir as
|
|
35906
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "node:fs";
|
|
35907
|
+
import { join as join8 } from "node:path";
|
|
35908
|
+
import { homedir as homedir4 } from "node:os";
|
|
35544
35909
|
import { spawn } from "node:child_process";
|
|
35545
35910
|
import net from "node:net";
|
|
35546
35911
|
function doctorRoot() {
|
|
35547
|
-
return process.env.DSH_DOCTOR_HOME?.trim() ||
|
|
35912
|
+
return process.env.DSH_DOCTOR_HOME?.trim() || join8(homedir4(), ".dsh-doctor");
|
|
35548
35913
|
}
|
|
35549
35914
|
function doctorPipeName(root = doctorRoot()) {
|
|
35550
35915
|
const hash = createHash("sha256").update(root).digest("hex").slice(0, 16);
|
|
@@ -35569,16 +35934,16 @@ function pipeAvailable(pipe, timeoutMs = 1500) {
|
|
|
35569
35934
|
});
|
|
35570
35935
|
}
|
|
35571
35936
|
function findDoctorCli() {
|
|
35572
|
-
const profilesDir =
|
|
35937
|
+
const profilesDir = join8(homedir4(), ".dsh", "profiles");
|
|
35573
35938
|
let entries = [];
|
|
35574
35939
|
try {
|
|
35575
|
-
entries =
|
|
35940
|
+
entries = readdirSync2(profilesDir);
|
|
35576
35941
|
} catch {
|
|
35577
35942
|
return "";
|
|
35578
35943
|
}
|
|
35579
35944
|
for (const name2 of entries) {
|
|
35580
|
-
const candidate =
|
|
35581
|
-
if (
|
|
35945
|
+
const candidate = join8(profilesDir, name2, "node_modules", "@linxin666", "dsh-doctor", "lib", "cli.mjs");
|
|
35946
|
+
if (existsSync2(candidate)) return candidate;
|
|
35582
35947
|
}
|
|
35583
35948
|
return "";
|
|
35584
35949
|
}
|
|
@@ -35769,7 +36134,7 @@ async function readJsonBody2(req) {
|
|
|
35769
36134
|
const { readJsonBody: read } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
35770
36135
|
return read(req);
|
|
35771
36136
|
}
|
|
35772
|
-
async function handler(req, res,
|
|
36137
|
+
async function handler(req, res, ctx2) {
|
|
35773
36138
|
if (!isLoopbackRequest(req)) {
|
|
35774
36139
|
writeJson(res, 403, { error: "forbidden: loopback-only", code: "forbidden" });
|
|
35775
36140
|
return;
|
|
@@ -35787,6 +36152,29 @@ async function handler(req, res, ctx) {
|
|
|
35787
36152
|
await handleEvents(req, res);
|
|
35788
36153
|
return;
|
|
35789
36154
|
}
|
|
36155
|
+
if (head === "activate" && activation) {
|
|
36156
|
+
activation.activate("panel-open");
|
|
36157
|
+
writeJson(res, 200, { ok: true, active: true });
|
|
36158
|
+
return;
|
|
36159
|
+
}
|
|
36160
|
+
if (head === "pyenv" && methodOk(req, "GET")) {
|
|
36161
|
+
const { detectPythons: detectPythons2, figureInterpreter: figureInterpreter2, venvExists: venvExists2, venvDir: venvDir2 } = await Promise.resolve().then(() => (init_pyenv(), pyenv_exports));
|
|
36162
|
+
const pythons = await detectPythons2();
|
|
36163
|
+
const fig = await figureInterpreter2();
|
|
36164
|
+
writeJson(res, 200, {
|
|
36165
|
+
pythons,
|
|
36166
|
+
venv: { exists: venvExists2(), dir: venvDir2() },
|
|
36167
|
+
figure: fig ? { exe: fig.exe, version: fig.version, source: fig.source, hasMatplotlib: fig.hasMatplotlib } : null
|
|
36168
|
+
});
|
|
36169
|
+
return;
|
|
36170
|
+
}
|
|
36171
|
+
if (head === "install-deps" && methodOk(req, "POST")) {
|
|
36172
|
+
const { installFigureDeps: installFigureDeps2 } = await Promise.resolve().then(() => (init_pyenv(), pyenv_exports));
|
|
36173
|
+
const logs = [];
|
|
36174
|
+
const result = await installFigureDeps2((m) => logs.push(m));
|
|
36175
|
+
writeJson(res, result.ok ? 200 : 500, { ...result, logs });
|
|
36176
|
+
return;
|
|
36177
|
+
}
|
|
35790
36178
|
if (head === "state" && methodOk(req, "GET")) {
|
|
35791
36179
|
await handleState(res);
|
|
35792
36180
|
return;
|
|
@@ -35936,6 +36324,11 @@ async function handler(req, res, ctx) {
|
|
|
35936
36324
|
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
35937
36325
|
const filename = url.searchParams.get("filename") || "dropped.pdf";
|
|
35938
36326
|
const buffer = await readRawBody(req, 128 * 1024 * 1024);
|
|
36327
|
+
if (buffer.length > 4 && buffer.subarray(0, 2).toString("latin1") === "PK" && /\.pptx$/i.test(filename)) {
|
|
36328
|
+
const item2 = await importDroppedCourseware(buffer, { filename });
|
|
36329
|
+
writeJson(res, 200, { item: item2 });
|
|
36330
|
+
return;
|
|
36331
|
+
}
|
|
35939
36332
|
const item = await importDroppedPdf(buffer, { filename });
|
|
35940
36333
|
writeJson(res, 200, { item });
|
|
35941
36334
|
return;
|
|
@@ -35999,7 +36392,7 @@ async function handler(req, res, ctx) {
|
|
|
35999
36392
|
if (sub === "ask" && methodOk(req, "POST")) {
|
|
36000
36393
|
const body = await readJsonBody2(req);
|
|
36001
36394
|
const { askAi: askAi2 } = await Promise.resolve().then(() => (init_ai(), ai_exports));
|
|
36002
|
-
const result = await askAi2(
|
|
36395
|
+
const result = await askAi2(ctx2, {
|
|
36003
36396
|
key: String(body?.key ?? ""),
|
|
36004
36397
|
action: String(body?.action ?? "ask"),
|
|
36005
36398
|
question: String(body?.question ?? ""),
|
|
@@ -36022,11 +36415,11 @@ async function handler(req, res, ctx) {
|
|
|
36022
36415
|
else res.end();
|
|
36023
36416
|
}
|
|
36024
36417
|
}
|
|
36025
|
-
function registerRoutes(
|
|
36026
|
-
const disposers = [
|
|
36027
|
-
if (typeof
|
|
36418
|
+
function registerRoutes(ctx2, { activation: activation2 } = {}) {
|
|
36419
|
+
const disposers = [ctx2.webServer.register({ kind: "prefix", path: PREFIX2, handler: (req, res) => handler(req, res, ctx2) })];
|
|
36420
|
+
if (typeof ctx2.on === "function") {
|
|
36028
36421
|
disposers.push(
|
|
36029
|
-
|
|
36422
|
+
ctx2.on("session/event", (session) => {
|
|
36030
36423
|
noteSession(session);
|
|
36031
36424
|
})
|
|
36032
36425
|
);
|
|
@@ -36038,76 +36431,472 @@ function registerRoutes(ctx) {
|
|
|
36038
36431
|
// src/node/tools.js
|
|
36039
36432
|
init_pipeline();
|
|
36040
36433
|
init_db();
|
|
36434
|
+
|
|
36435
|
+
// src/node/store/search.js
|
|
36436
|
+
function tokenize(text) {
|
|
36437
|
+
const s = String(text ?? "").toLowerCase();
|
|
36438
|
+
const out = /* @__PURE__ */ new Set();
|
|
36439
|
+
for (const m of s.matchAll(/[a-z0-9][a-z0-9._-]*/g)) {
|
|
36440
|
+
if (m[0].length >= 2) out.add(m[0]);
|
|
36441
|
+
}
|
|
36442
|
+
const cjkRuns = s.match(/[\u3400-\u4dbf\u4e00-\u9fff\u3040-\u30ff]+/g) ?? [];
|
|
36443
|
+
for (const run2 of cjkRuns) {
|
|
36444
|
+
for (let i = 0; i < run2.length; i += 1) {
|
|
36445
|
+
out.add(run2[i]);
|
|
36446
|
+
if (i + 1 < run2.length) out.add(run2.slice(i, i + 2));
|
|
36447
|
+
}
|
|
36448
|
+
}
|
|
36449
|
+
return [...out];
|
|
36450
|
+
}
|
|
36451
|
+
var WEIGHTS = {
|
|
36452
|
+
title: 3,
|
|
36453
|
+
authors: 2,
|
|
36454
|
+
container: 2,
|
|
36455
|
+
abstract: 1,
|
|
36456
|
+
tags: 1
|
|
36457
|
+
};
|
|
36458
|
+
function fieldText(item, field) {
|
|
36459
|
+
const rec = item.record ?? {};
|
|
36460
|
+
switch (field) {
|
|
36461
|
+
case "title":
|
|
36462
|
+
return rec.title ?? item.title ?? item.display ?? "";
|
|
36463
|
+
case "authors":
|
|
36464
|
+
return (rec.authors ?? []).map((a) => `${a.lastName ?? ""} ${a.firstName ?? ""}`.trim()).join(" ");
|
|
36465
|
+
case "container":
|
|
36466
|
+
return rec.container ?? "";
|
|
36467
|
+
case "abstract":
|
|
36468
|
+
return rec.abstract ?? "";
|
|
36469
|
+
case "tags":
|
|
36470
|
+
return (item.tags ?? []).join(" ");
|
|
36471
|
+
default:
|
|
36472
|
+
return "";
|
|
36473
|
+
}
|
|
36474
|
+
}
|
|
36475
|
+
function searchItems2(items, query, { limit = 20 } = {}) {
|
|
36476
|
+
const terms = tokenize(query);
|
|
36477
|
+
if (!terms.length) return [];
|
|
36478
|
+
const scored = [];
|
|
36479
|
+
for (const item of items) {
|
|
36480
|
+
let score = 0;
|
|
36481
|
+
let matched = false;
|
|
36482
|
+
for (const [field, weight] of Object.entries(WEIGHTS)) {
|
|
36483
|
+
const text = String(fieldText(item, field)).toLowerCase();
|
|
36484
|
+
if (!text) continue;
|
|
36485
|
+
for (const t of terms) {
|
|
36486
|
+
if (text.includes(t)) {
|
|
36487
|
+
matched = true;
|
|
36488
|
+
score += weight * (t.length >= 2 ? 2 : 1);
|
|
36489
|
+
}
|
|
36490
|
+
}
|
|
36491
|
+
}
|
|
36492
|
+
if (!matched) continue;
|
|
36493
|
+
const rec = item.record ?? {};
|
|
36494
|
+
scored.push({
|
|
36495
|
+
key: item.key,
|
|
36496
|
+
title: rec.title ?? item.title ?? item.display ?? "(\u65E0\u6807\u9898)",
|
|
36497
|
+
authors: (rec.authors ?? []).slice(0, 3).map((a) => a.lastName ?? "").filter(Boolean).join(", "),
|
|
36498
|
+
year: rec.year ?? item.year ?? null,
|
|
36499
|
+
container: rec.container ?? "",
|
|
36500
|
+
snippet: snippetFor(item, terms),
|
|
36501
|
+
state: item.state ?? "",
|
|
36502
|
+
score
|
|
36503
|
+
});
|
|
36504
|
+
}
|
|
36505
|
+
scored.sort((a, b) => b.score !== a.score ? b.score - a.score : a.key < b.key ? -1 : 1);
|
|
36506
|
+
return scored.slice(0, Math.max(1, Math.min(limit, 50)));
|
|
36507
|
+
}
|
|
36508
|
+
function snippetFor(item, terms) {
|
|
36509
|
+
const rec = item.record ?? {};
|
|
36510
|
+
const source = rec.abstract || rec.title || "";
|
|
36511
|
+
if (!source) return "";
|
|
36512
|
+
const lower = source.toLowerCase();
|
|
36513
|
+
let at = -1;
|
|
36514
|
+
for (const t of terms) {
|
|
36515
|
+
const i = lower.indexOf(t);
|
|
36516
|
+
if (i >= 0 && (at < 0 || i < at)) at = i;
|
|
36517
|
+
}
|
|
36518
|
+
if (at < 0) return String(source).slice(0, 160);
|
|
36519
|
+
const start = Math.max(0, at - 60);
|
|
36520
|
+
const head = start > 0 ? "\u2026" : "";
|
|
36521
|
+
return head + String(source).slice(start, start + 220).trim();
|
|
36522
|
+
}
|
|
36523
|
+
|
|
36524
|
+
// src/node/tools.js
|
|
36041
36525
|
init_normalize();
|
|
36042
36526
|
init_log();
|
|
36527
|
+
import { writeFile as writeFile5, mkdtemp, readFile as readFile6, rm } from "node:fs/promises";
|
|
36528
|
+
import { tmpdir } from "node:os";
|
|
36529
|
+
import { join as join7 } from "node:path";
|
|
36043
36530
|
function textResult(value) {
|
|
36044
36531
|
return {
|
|
36045
36532
|
schema: { type: "string" },
|
|
36046
36533
|
render: (_args, v) => [{ type: "text", text: String(v) }]
|
|
36047
36534
|
};
|
|
36048
36535
|
}
|
|
36049
|
-
function
|
|
36050
|
-
|
|
36051
|
-
|
|
36052
|
-
|
|
36053
|
-
|
|
36054
|
-
|
|
36055
|
-
|
|
36056
|
-
|
|
36057
|
-
|
|
36058
|
-
|
|
36059
|
-
|
|
36060
|
-
}
|
|
36061
|
-
|
|
36062
|
-
|
|
36063
|
-
|
|
36064
|
-
|
|
36065
|
-
|
|
36066
|
-
|
|
36067
|
-
|
|
36068
|
-
|
|
36069
|
-
|
|
36070
|
-
|
|
36071
|
-
|
|
36072
|
-
|
|
36073
|
-
|
|
36074
|
-
|
|
36075
|
-
const lines = items.filter(Boolean).map((i) => `- ${i.record?.title || i.display} [${i.key}]`);
|
|
36076
|
-
return `\u5DF2\u52A0\u5165\u4FA7\u7A97 ${items.length} \u6761\uFF1A
|
|
36077
|
-
${lines.join("\n")}`;
|
|
36536
|
+
function toolDefs() {
|
|
36537
|
+
return [lookupTool(), searchTool(), getTool(), citeTool(), noteTool(), statusTool(), saveTool(), figureTool()];
|
|
36538
|
+
}
|
|
36539
|
+
function registerTools(ctx2) {
|
|
36540
|
+
let mounted = [];
|
|
36541
|
+
return {
|
|
36542
|
+
mount() {
|
|
36543
|
+
if (mounted.length) return;
|
|
36544
|
+
mounted = toolDefs().map((def) => {
|
|
36545
|
+
try {
|
|
36546
|
+
return ctx2.tools.register(def);
|
|
36547
|
+
} catch (e) {
|
|
36548
|
+
warn("tool registration failed:", def.name, e?.message);
|
|
36549
|
+
return null;
|
|
36550
|
+
}
|
|
36551
|
+
});
|
|
36552
|
+
log(`tools mounted: ${toolDefs().map((d) => d.name).join(", ")}`);
|
|
36553
|
+
},
|
|
36554
|
+
unmount() {
|
|
36555
|
+
if (!mounted.length) return;
|
|
36556
|
+
for (const dispose of mounted) {
|
|
36557
|
+
try {
|
|
36558
|
+
dispose?.();
|
|
36559
|
+
} catch (e) {
|
|
36560
|
+
warn("tool dispose failed:", e?.message);
|
|
36561
|
+
}
|
|
36078
36562
|
}
|
|
36079
|
-
|
|
36080
|
-
|
|
36081
|
-
|
|
36082
|
-
|
|
36083
|
-
|
|
36084
|
-
|
|
36085
|
-
|
|
36086
|
-
|
|
36087
|
-
|
|
36088
|
-
|
|
36089
|
-
|
|
36090
|
-
|
|
36563
|
+
mounted = [];
|
|
36564
|
+
log("tools unmounted");
|
|
36565
|
+
},
|
|
36566
|
+
isMounted: () => mounted.length > 0,
|
|
36567
|
+
dispose() {
|
|
36568
|
+
this.unmount();
|
|
36569
|
+
}
|
|
36570
|
+
};
|
|
36571
|
+
}
|
|
36572
|
+
function formatHit(h) {
|
|
36573
|
+
const bits = [h.title];
|
|
36574
|
+
if (h.authors) bits.push(h.authors);
|
|
36575
|
+
if (h.year) bits.push(String(h.year));
|
|
36576
|
+
if (h.container) bits.push(h.container);
|
|
36577
|
+
const line = bits.join(" | ") + ` [key=${h.key}]`;
|
|
36578
|
+
return h.snippet ? `${line}
|
|
36579
|
+
${h.snippet.slice(0, 160)}` : line;
|
|
36580
|
+
}
|
|
36581
|
+
var NEXT_STEP = "\n[\u4E0B\u4E00\u6B65] literature_get(key=\u2026) \u770B\u8BE6\u60C5 \xB7 literature_cite \u751F\u6210\u5F15\u7528 \xB7 literature_search \u7EE7\u7EED\u68C0\u7D22";
|
|
36582
|
+
function lookupTool() {
|
|
36583
|
+
return {
|
|
36584
|
+
name: "literature_lookup",
|
|
36585
|
+
description: "\u4ECE\u6587\u672C\u6216\u6807\u8BC6\u7B26\u4E2D\u8BC6\u522B\u5B66\u672F\u6587\u732E\uFF08DOI\u3001arXiv ID\u3001PMID\u3001ISBN\u3001\u6807\u9898\uFF09\uFF0C\u89E3\u6790\u5143\u6570\u636E\u5E76\u751F\u6210\u4FA7\u7A97\u6761\u76EE\u3002\u5F53\u4F60\u68C0\u7D22\u6216\u5F15\u7528\u6587\u732E\u5E76\u5E0C\u671B\u7528\u6237\u80FD\u5728\u4FA7\u8FB9\u680F\u9884\u89C8/\u4FDD\u5B58\u5168\u6587\u65F6\u8C03\u7528\u3002",
|
|
36586
|
+
parameters: {
|
|
36587
|
+
type: "object",
|
|
36588
|
+
properties: {
|
|
36589
|
+
text: { type: "string", description: "\u5305\u542B\u6587\u732E\u6807\u8BC6\u7B26\u6216\u5F15\u7528\u6587\u672C\u7684\u7247\u6BB5" },
|
|
36590
|
+
resolve: { type: "string", description: "\u662F\u5426\u7ACB\u5373\u8054\u7F51\u89E3\u6790\u5143\u6570\u636E\uFF0C\u9ED8\u8BA4 yes" }
|
|
36591
|
+
},
|
|
36592
|
+
required: []
|
|
36593
|
+
},
|
|
36594
|
+
output: textResult(),
|
|
36595
|
+
timeoutMs: 12e4,
|
|
36596
|
+
async execute(args) {
|
|
36597
|
+
const text = String(args?.text ?? "");
|
|
36598
|
+
if (!text.trim()) return "\u6CA1\u6709\u63D0\u4F9B\u6587\u672C\u3002";
|
|
36599
|
+
const created = await scanText(text);
|
|
36600
|
+
if (!created.length) return "\u672A\u8BC6\u522B\u5230\u65B0\u7684\u6587\u732E\u6761\u76EE\uFF08\u53EF\u80FD\u5DF2\u5B58\u5728\u4E8E\u4FA7\u7A97\uFF09\u3002";
|
|
36601
|
+
const wantResolve = String(args?.resolve ?? "yes").toLowerCase() !== "no";
|
|
36602
|
+
if (wantResolve) {
|
|
36603
|
+
await Promise.all(created.map((i) => resolveItem(i.key).catch((e) => warn("resolve failed", e.message))));
|
|
36604
|
+
}
|
|
36605
|
+
const items = await Promise.all(created.map((i) => getItem(i.key)));
|
|
36606
|
+
const lines = items.filter(Boolean).map((i) => `- ${i.record?.title || i.display} [key=${i.key}]`);
|
|
36607
|
+
return `\u5DF2\u52A0\u5165\u4FA7\u7A97 ${items.length} \u6761\uFF1A
|
|
36608
|
+
${lines.join("\n")}${NEXT_STEP}`;
|
|
36609
|
+
}
|
|
36610
|
+
};
|
|
36611
|
+
}
|
|
36612
|
+
function searchTool() {
|
|
36613
|
+
return {
|
|
36614
|
+
name: "literature_search",
|
|
36615
|
+
description: "\u5728\u7528\u6237\u7684\u6587\u732E\u5E93\u4E2D\u68C0\u7D22\u5DF2\u4FDD\u5B58\u7684\u6587\u732E\uFF08\u6807\u9898/\u4F5C\u8005/\u671F\u520A/\u6458\u8981/\u6807\u7B7E\u7684\u5173\u952E\u8BCD\u5339\u914D\uFF09\u3002\u5F53\u7528\u6237\u95EE\u300C\u6211\u4E4B\u524D\u5B58\u7684\u90A3\u7BC7\u300D\u300C\u6211\u5E93\u91CC\u6709\u6CA1\u6709\u8BB2 X \u7684\u300D\u300C\u6709\u4EC0\u4E48\u6587\u732E\u53EF\u4EE5\u7528\u300D\u65F6\u8C03\u7528\u3002\u8FD4\u56DE\u7CBE\u7B80\u6761\u76EE\uFF0C\u9700\u8981\u5B8C\u6574\u4FE1\u606F\u518D\u7528 literature_get\u3002",
|
|
36616
|
+
parameters: {
|
|
36617
|
+
type: "object",
|
|
36618
|
+
properties: {
|
|
36619
|
+
query: { type: "string", description: "\u68C0\u7D22\u8BCD\uFF1A\u4E3B\u9898\u3001\u6807\u9898\u7247\u6BB5\u3001\u4F5C\u8005\u59D3\u6C0F\u6216\u671F\u520A\u540D" },
|
|
36620
|
+
limit: { type: "number", description: "\u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA4 8\uFF0C\u6700\u5927 20" }
|
|
36621
|
+
},
|
|
36622
|
+
required: ["query"]
|
|
36623
|
+
},
|
|
36624
|
+
output: textResult(),
|
|
36625
|
+
timeoutMs: 15e3,
|
|
36626
|
+
async execute(args) {
|
|
36627
|
+
const query = String(args?.query ?? "").trim();
|
|
36628
|
+
if (!query) return "\u7F3A\u5C11\u68C0\u7D22\u8BCD\u3002";
|
|
36629
|
+
const limit = Math.max(1, Math.min(Number(args?.limit) || 8, 20));
|
|
36630
|
+
const items = await listItems();
|
|
36631
|
+
const hits = searchItems2(items, query, { limit });
|
|
36632
|
+
if (!hits.length) return `\u672A\u5728\u5E93\u4E2D\u627E\u5230\u4E0E\u300C${query}\u300D\u5339\u914D\u7684\u6761\u76EE\u3002\u53EF\u5148\u7528 literature_lookup \u6DFB\u52A0\uFF0C\u6216\u6362\u66F4\u5BBD\u6CDB\u7684\u68C0\u7D22\u8BCD\u3002`;
|
|
36633
|
+
return `\u547D\u4E2D ${hits.length} \u6761\uFF1A
|
|
36634
|
+
${hits.map((h) => `- ${formatHit(h)}`).join("\n")}${NEXT_STEP}`;
|
|
36635
|
+
}
|
|
36636
|
+
};
|
|
36637
|
+
}
|
|
36638
|
+
function getTool() {
|
|
36639
|
+
return {
|
|
36640
|
+
name: "literature_get",
|
|
36641
|
+
description: "\u6309 key \u83B7\u53D6\u6761\u76EE\u7684\u5B8C\u6574\u4FE1\u606F\uFF1A\u5143\u6570\u636E\u3001\u6458\u8981\u3001\u6279\u6CE8\u4E0E\u7B14\u8BB0\u3002\u4EC5\u5728 literature_search \u8FD4\u56DE\u8FC7\u8BE5 key \u65F6\u4F7F\u7528\u2014\u2014\u4E0D\u8981\u51ED\u731C\u6D4B\u7F16\u9020 key\u3002",
|
|
36642
|
+
parameters: {
|
|
36643
|
+
type: "object",
|
|
36644
|
+
properties: {
|
|
36645
|
+
key: { type: "string", description: "\u6761\u76EE key" },
|
|
36646
|
+
includeAnnotations: { type: "boolean", description: "\u662F\u5426\u5305\u542B\u6279\u6CE8\uFF0C\u9ED8\u8BA4 true" }
|
|
36647
|
+
},
|
|
36648
|
+
required: ["key"]
|
|
36649
|
+
},
|
|
36650
|
+
output: textResult(),
|
|
36651
|
+
timeoutMs: 15e3,
|
|
36652
|
+
async execute(args) {
|
|
36653
|
+
const key = String(args?.key ?? "");
|
|
36654
|
+
if (!key) return "\u7F3A\u5C11\u6761\u76EE key\u3002";
|
|
36655
|
+
const item = await getItem(key);
|
|
36656
|
+
if (!item) return `\u672A\u627E\u5230\u6761\u76EE ${key}\u3002\u8BF7\u5148\u7528 literature_search \u83B7\u53D6\u6B63\u786E\u7684 key\u3002`;
|
|
36657
|
+
const rec = item.record ?? {};
|
|
36658
|
+
const lines = [
|
|
36659
|
+
`\u6807\u9898\uFF1A${rec.title ?? item.title ?? item.display ?? "(\u65E0\u6807\u9898)"}`,
|
|
36660
|
+
`\u4F5C\u8005\uFF1A${(rec.authors ?? []).map((a) => `${a.lastName ?? ""} ${a.firstName ?? ""}`.trim()).filter(Boolean).join("; ") || "\u2014"}`,
|
|
36661
|
+
`\u5E74\u4EFD\uFF1A${rec.year ?? "\u2014"}`,
|
|
36662
|
+
`\u671F\u520A/\u4F1A\u8BAE\uFF1A${rec.container ?? "\u2014"}`,
|
|
36663
|
+
`DOI\uFF1A${rec.doi ?? "\u2014"}`,
|
|
36664
|
+
`\u72B6\u6001\uFF1A${item.state ?? "\u2014"}${item.pdf ? "\uFF08\u5DF2\u6709\u5168\u6587\uFF09" : "\uFF08\u65E0\u5168\u6587\uFF09"}`
|
|
36665
|
+
];
|
|
36666
|
+
if (rec.abstract) lines.push(`\u6458\u8981\uFF1A${String(rec.abstract).slice(0, 600)}`);
|
|
36667
|
+
if (String(args?.includeAnnotations ?? true) !== "false") {
|
|
36668
|
+
const anns = await getAnnotations(key);
|
|
36669
|
+
if (anns.length) {
|
|
36670
|
+
const shown = anns.slice(0, 50);
|
|
36671
|
+
lines.push(`\u6279\u6CE8\uFF08${anns.length} \u6761${anns.length > shown.length ? `\uFF0C\u5C55\u793A\u524D ${shown.length} \u6761` : ""}\uFF09\uFF1A`);
|
|
36672
|
+
for (const a of shown) lines.push(` - p.${a.pageIndex ?? "?"} ${String(a.text ?? "").slice(0, 120)}${a.note ? ` \uFF5C \u7B14\u8BB0\uFF1A${String(a.note).slice(0, 120)}` : ""}`);
|
|
36673
|
+
}
|
|
36674
|
+
}
|
|
36675
|
+
return lines.join("\n") + "\n[\u4E0B\u4E00\u6B65] literature_cite \u751F\u6210\u5F15\u7528 \xB7 literature_note \u8BB0\u5F55\u5173\u7CFB";
|
|
36676
|
+
}
|
|
36677
|
+
};
|
|
36678
|
+
}
|
|
36679
|
+
function citeTool() {
|
|
36680
|
+
return {
|
|
36681
|
+
name: "literature_cite",
|
|
36682
|
+
description: "\u751F\u6210\u89C4\u8303\u5316\u7684\u5F15\u7528\u6587\u672C\uFF08APA 7 / GB/T 7714 / MLA 9 / Chicago 17 / BibTeX\uFF09\uFF0C\u652F\u6301\u53C2\u8003\u6587\u732E\u6761\u76EE\u3001\u6587\u5185\u5F15\u7528\u4E0E\u5E26\u9875\u7801\u7684\u76F4\u63A5\u5F15\u7528\u3002\u5199\u4F5C\u4E2D\u9700\u8981\u5F15\u7528\u6587\u732E\u65F6\u76F4\u63A5\u8C03\u7528\uFF0C\u4E0D\u8981\u624B\u5DE5\u62FC\u88C5\u4F5C\u8005\u4E0E\u5E74\u4EFD\u3002",
|
|
36683
|
+
parameters: {
|
|
36684
|
+
type: "object",
|
|
36685
|
+
properties: {
|
|
36686
|
+
key: { type: "string", description: "\u6761\u76EE key" },
|
|
36687
|
+
style: { type: "string", description: "apa | gb | mla | chicago | bibtex\uFF0C\u9ED8\u8BA4 apa" },
|
|
36688
|
+
mode: { type: "string", description: "reference\uFF08\u9ED8\u8BA4\uFF09| intext | direct" },
|
|
36689
|
+
pages: { type: "string", description: "\u76F4\u63A5\u5F15\u7528\u7684\u9875\u7801\uFF0C\u5982 12 \u6216 12-15" }
|
|
36690
|
+
},
|
|
36691
|
+
required: ["key"]
|
|
36692
|
+
},
|
|
36693
|
+
output: textResult(),
|
|
36694
|
+
timeoutMs: 15e3,
|
|
36695
|
+
async execute(args) {
|
|
36696
|
+
const key = String(args?.key ?? "");
|
|
36697
|
+
if (!key) return "\u7F3A\u5C11\u6761\u76EE key\u3002";
|
|
36698
|
+
const item = await getItem(key);
|
|
36699
|
+
if (!item?.record) return `\u6761\u76EE ${key} \u7F3A\u5C11\u5143\u6570\u636E\uFF0C\u65E0\u6CD5\u751F\u6210\u5F15\u7528\u3002\u8BF7\u5148\u7528 literature_lookup \u89E3\u6790\u5143\u6570\u636E\u3002`;
|
|
36700
|
+
const { citeDetailed: citeDetailed2 } = await Promise.resolve().then(() => (init_cite(), cite_exports));
|
|
36701
|
+
const d = citeDetailed2(item.record, {
|
|
36702
|
+
style: args?.style ?? "apa",
|
|
36703
|
+
mode: args?.mode ?? "reference",
|
|
36704
|
+
pages: args?.pages
|
|
36705
|
+
});
|
|
36706
|
+
return `${d.text}
|
|
36707
|
+
\uFF08${d.style} \xB7 ${d.mode}\uFF09
|
|
36708
|
+
[\u4E0B\u4E00\u6B65] literature_verify \u6838\u9A8C\u5F15\u7528\u771F\u5B9E\u6027 \xB7 literature_note \u8BB0\u5F55\u5B83\u548C\u5F53\u524D\u5199\u4F5C\u7684\u5173\u7CFB`;
|
|
36709
|
+
}
|
|
36710
|
+
};
|
|
36711
|
+
}
|
|
36712
|
+
function noteTool() {
|
|
36713
|
+
return {
|
|
36714
|
+
name: "literature_note",
|
|
36715
|
+
description: "\u628A\u4E00\u6761\u7B14\u8BB0\u5199\u56DE\u6587\u732E\u6761\u76EE\uFF1A\u8FD9\u7BC7\u6587\u732E\u4E0E\u7528\u6237\u5F53\u524D\u5199\u4F5C/\u7814\u7A76\u7684\u5173\u7CFB\u3001\u53EF\u7528\u8BBA\u70B9\u3001\u5F85\u9A8C\u8BC1\u4E4B\u5904\u3002\u4F1A\u8FFD\u52A0\u4FDD\u5B58\uFF0C\u4E0B\u6B21\u68C0\u7D22\u8BE5\u6761\u76EE\u65F6\u80FD\u88AB\u627E\u56DE\u3002",
|
|
36716
|
+
parameters: {
|
|
36717
|
+
type: "object",
|
|
36718
|
+
properties: {
|
|
36719
|
+
key: { type: "string", description: "\u6761\u76EE key" },
|
|
36720
|
+
note: { type: "string", description: "\u8981\u8BB0\u5F55\u7684\u7B14\u8BB0\u5185\u5BB9" }
|
|
36721
|
+
},
|
|
36722
|
+
required: ["key", "note"]
|
|
36723
|
+
},
|
|
36724
|
+
output: textResult(),
|
|
36725
|
+
timeoutMs: 15e3,
|
|
36726
|
+
async execute(args) {
|
|
36727
|
+
const key = String(args?.key ?? "");
|
|
36728
|
+
const note = String(args?.note ?? "").trim();
|
|
36729
|
+
if (!key) return "\u7F3A\u5C11\u6761\u76EE key\u3002";
|
|
36730
|
+
if (!note) return "\u7B14\u8BB0\u5185\u5BB9\u4E3A\u7A7A\uFF0C\u672A\u5199\u5165\u3002";
|
|
36731
|
+
const item = await getItem(key);
|
|
36732
|
+
if (!item) return `\u672A\u627E\u5230\u6761\u76EE ${key}\u3002`;
|
|
36733
|
+
const notes = Array.isArray(item.notes) ? item.notes : [];
|
|
36734
|
+
if (notes.some((n) => (typeof n === "string" ? n : n.text) === note)) return "\u8BE5\u7B14\u8BB0\u5DF2\u5B58\u5728\uFF0C\u672A\u91CD\u590D\u5199\u5165\u3002";
|
|
36735
|
+
const entry = { text: note, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
36736
|
+
await patchItem(key, { notes: [...notes, entry] });
|
|
36737
|
+
return `\u5DF2\u8BB0\u5F55\u5230\u6761\u76EE ${key}\uFF08\u5171 ${notes.length + 1} \u6761\u7B14\u8BB0\uFF09\u3002`;
|
|
36738
|
+
}
|
|
36739
|
+
};
|
|
36740
|
+
}
|
|
36741
|
+
function statusTool() {
|
|
36742
|
+
return {
|
|
36743
|
+
name: "literature_status",
|
|
36744
|
+
description: "\u67E5\u770B\u6587\u732E\u5E93\u7684\u5F53\u524D\u72B6\u6001\uFF1A\u6761\u76EE\u603B\u6570\u3001\u5404\u72B6\u6001\u5206\u5E03\u3001\u6700\u8FD1\u6DFB\u52A0\u7684\u6761\u76EE\u3001\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u3002\u5728\u5F00\u59CB\u6587\u732E\u5DE5\u4F5C\u524D\u4E86\u89E3\u5E93\u91CC\u6709\u4EC0\u4E48\u65F6\u8C03\u7528\u3002",
|
|
36745
|
+
parameters: { type: "object", properties: {}, required: [] },
|
|
36746
|
+
output: textResult(),
|
|
36747
|
+
timeoutMs: 15e3,
|
|
36748
|
+
async execute() {
|
|
36749
|
+
const items = await listItems();
|
|
36750
|
+
const byState = {};
|
|
36751
|
+
for (const i of items) {
|
|
36752
|
+
const s = i.state ?? "unknown";
|
|
36753
|
+
byState[s] = (byState[s] ?? 0) + 1;
|
|
36754
|
+
}
|
|
36755
|
+
const recent = [...items].sort((a, b) => Number(b.createdAt ?? 0) - Number(a.createdAt ?? 0)).slice(0, 5).map((i) => `- ${i.record?.title ?? i.title ?? i.display ?? "(\u65E0\u6807\u9898)"} [key=${i.key}]`);
|
|
36756
|
+
const running = (await listTasks()).filter((t) => t.status === "running");
|
|
36757
|
+
return [
|
|
36758
|
+
`\u6761\u76EE\u603B\u6570\uFF1A${items.length}`,
|
|
36759
|
+
`\u72B6\u6001\u5206\u5E03\uFF1A${Object.entries(byState).map(([k, v]) => `${k}=${v}`).join(", ") || "\u2014"}`,
|
|
36760
|
+
running.length ? `\u8FDB\u884C\u4E2D\u4EFB\u52A1\uFF1A${running.map((t) => `${t.key}(${t.progress ?? 0}%)`).join(", ")}` : "\u8FDB\u884C\u4E2D\u4EFB\u52A1\uFF1A\u65E0",
|
|
36761
|
+
recent.length ? `\u6700\u8FD1\u6DFB\u52A0\uFF1A
|
|
36762
|
+
${recent.join("\n")}` : "\u5E93\u662F\u7A7A\u7684\u3002"
|
|
36763
|
+
].join("\n") + NEXT_STEP;
|
|
36764
|
+
}
|
|
36765
|
+
};
|
|
36766
|
+
}
|
|
36767
|
+
function figureTool() {
|
|
36768
|
+
const CHART_TYPES = /* @__PURE__ */ new Set(["bar", "line", "pie"]);
|
|
36769
|
+
return {
|
|
36770
|
+
name: "literature_figure",
|
|
36771
|
+
description: "\u6839\u636E\u8868\u683C\u6570\u636E\u7ED8\u5236\u793A\u610F\u56FE\u5E76\u63D2\u5165\u5F53\u524D\u5BF9\u8BDD\uFF08\u67F1\u72B6\u56FE/\u6298\u7EBF\u56FE/\u997C\u56FE\uFF09\u3002\u4EC5\u5728\u7528\u6237\u660E\u786E\u8981\u6C42\u300C\u753B\u4E2A\u56FE/\u53EF\u89C6\u5316/\u505A\u793A\u610F\u56FE\u300D\u65F6\u8C03\u7528\uFF1B\u4E0D\u8981\u5728\u6CA1\u6709\u6570\u636E\u4F9D\u636E\u65F6\u51ED\u7A7A\u7F16\u9020\u6570\u503C\u3002",
|
|
36772
|
+
parameters: {
|
|
36773
|
+
type: "object",
|
|
36774
|
+
properties: {
|
|
36775
|
+
title: { type: "string", description: "\u56FE\u8868\u6807\u9898\uFF08\u4E5F\u4F1A\u4F5C\u4E3A\u6D88\u606F\u6807\u9898\uFF09" },
|
|
36776
|
+
categories: { type: "array", items: { type: "string" }, description: '\u6A2A\u8F74\u7C7B\u522B\uFF0C\u5982 ["2023","2024","2025"]' },
|
|
36777
|
+
series: {
|
|
36778
|
+
type: "array",
|
|
36779
|
+
description: "\u6570\u636E\u7CFB\u5217\uFF0C\u6BCF\u9879 { name, values }\uFF0Cvalues \u4E0E categories \u7B49\u957F",
|
|
36780
|
+
items: {
|
|
36781
|
+
type: "object",
|
|
36782
|
+
properties: {
|
|
36783
|
+
name: { type: "string" },
|
|
36784
|
+
values: { type: "array", items: { type: "number" } }
|
|
36785
|
+
},
|
|
36786
|
+
required: ["name", "values"]
|
|
36787
|
+
}
|
|
36091
36788
|
},
|
|
36092
|
-
|
|
36789
|
+
chartType: { type: "string", description: "bar\uFF08\u9ED8\u8BA4\uFF09| line | pie" },
|
|
36790
|
+
caption: { type: "string", description: "\u56FE\u4E0B\u8BF4\u660E\u6587\u5B57" },
|
|
36791
|
+
key: { type: "string", description: "\u53EF\u9009\uFF1A\u6570\u636E\u6765\u6E90\u6761\u76EE key\uFF08\u4FBF\u4E8E\u6807\u6CE8\u51FA\u5904\uFF09" }
|
|
36093
36792
|
},
|
|
36094
|
-
|
|
36095
|
-
|
|
36096
|
-
|
|
36097
|
-
|
|
36098
|
-
|
|
36099
|
-
|
|
36100
|
-
|
|
36101
|
-
|
|
36102
|
-
|
|
36103
|
-
|
|
36104
|
-
|
|
36105
|
-
|
|
36793
|
+
required: ["title", "categories", "series"]
|
|
36794
|
+
},
|
|
36795
|
+
output: textResult(),
|
|
36796
|
+
timeoutMs: 12e4,
|
|
36797
|
+
async execute(args, exec) {
|
|
36798
|
+
const title = String(args?.title ?? "").trim() || "\u793A\u610F\u56FE";
|
|
36799
|
+
const categories = Array.isArray(args?.categories) ? args.categories.map(String) : [];
|
|
36800
|
+
const series = Array.isArray(args?.series) ? args.series.map((s) => ({ name: String(s?.name ?? "series"), values: (Array.isArray(s?.values) ? s.values : []).map((v) => Number(v)) })).filter((s) => s.values.length) : [];
|
|
36801
|
+
const chartType = CHART_TYPES.has(args?.chartType) ? args.chartType : "bar";
|
|
36802
|
+
if (!categories.length || !series.length) return "\u7F3A\u5C11\u6570\u636E\uFF08categories \u6216 series \u4E3A\u7A7A\uFF09\u3002\u793A\u610F\u56FE\u9700\u8981\u771F\u5B9E\u6570\u636E\uFF0C\u4E0D\u80FD\u51ED\u7A7A\u7ED8\u5236\u3002";
|
|
36803
|
+
const { figureInterpreter: figureInterpreter2 } = await Promise.resolve().then(() => (init_pyenv(), pyenv_exports));
|
|
36804
|
+
const fig = await figureInterpreter2();
|
|
36805
|
+
if (!fig || !fig.hasMatplotlib) {
|
|
36806
|
+
return "\u793A\u610F\u56FE\u5F15\u64CE\u5C1A\u672A\u5C31\u7EEA\uFF1A\u672C\u673A\u7F3A\u5C11 Python + matplotlib\u3002\u8BF7\u5728\u4FA7\u7A97\u8BBE\u7F6E\u9875\u300C\u793A\u610F\u56FE\u5F15\u64CE\u300D\u4E2D\u70B9\u51FB\u300C\u5B89\u88C5\u4F9D\u8D56\u300D\u540E\u91CD\u8BD5\uFF1B\u671F\u95F4\u53EF\u4EE5\u8BA9\u6211\u8F93\u51FA\u6570\u636E\u8868\u683C\u4EE3\u66FF\u56FE\u8868\u3002";
|
|
36807
|
+
}
|
|
36808
|
+
const { mkdtemp: _mk, writeFile: _w, readFile: _r, rm: _rm } = { mkdtemp, writeFile: writeFile5, readFile: readFile6, rm };
|
|
36809
|
+
const dir = await mkdtemp(join7(tmpdir(), "lit-fig-"));
|
|
36810
|
+
const pyFile = join7(dir, "fig.py");
|
|
36811
|
+
const pngFile = join7(dir, "fig.png");
|
|
36812
|
+
const script = [
|
|
36813
|
+
"import matplotlib",
|
|
36814
|
+
"matplotlib.use('Agg')",
|
|
36815
|
+
"import matplotlib.pyplot as plt",
|
|
36816
|
+
// CJK glyphs are missing from matplotlib's default font (DejaVu Sans),
|
|
36817
|
+
// which turns Chinese labels into tofu boxes. Pick the first installed
|
|
36818
|
+
// CJK-capable font; degrade silently on non-CJK systems.
|
|
36819
|
+
"from matplotlib import font_manager",
|
|
36820
|
+
"_available = {f.name for f in font_manager.fontManager.ttflist}",
|
|
36821
|
+
"for _name in ['Microsoft YaHei', 'SimHei', 'PingFang SC', 'Noto Sans CJK SC', 'Source Han Sans SC', 'WenQuanYi Zen Hei']:",
|
|
36822
|
+
" if _name in _available:",
|
|
36823
|
+
" plt.rcParams['font.sans-serif'] = [_name]",
|
|
36824
|
+
" break",
|
|
36825
|
+
"plt.rcParams['axes.unicode_minus'] = False",
|
|
36826
|
+
`categories = ${JSON.stringify(categories)}`,
|
|
36827
|
+
`series = ${JSON.stringify(series)}`,
|
|
36828
|
+
`chart_type = ${JSON.stringify(chartType)}`,
|
|
36829
|
+
`title = ${JSON.stringify(title)}`,
|
|
36830
|
+
"fig, ax = plt.subplots(figsize=(7, 4.2), dpi=150)",
|
|
36831
|
+
"if chart_type == 'pie':",
|
|
36832
|
+
" vals = series[0]['values']",
|
|
36833
|
+
" ax.pie(vals, labels=categories, autopct='%1.1f%%', startangle=90)",
|
|
36834
|
+
" ax.axis('equal')",
|
|
36835
|
+
"elif chart_type == 'line':",
|
|
36836
|
+
" for s in series: ax.plot(categories, s['values'], marker='o', label=s['name'])",
|
|
36837
|
+
" ax.legend()",
|
|
36838
|
+
"else:",
|
|
36839
|
+
" import numpy as np",
|
|
36840
|
+
" x = np.arange(len(categories)); w = 0.8 / max(len(series), 1)",
|
|
36841
|
+
" for i, s in enumerate(series): ax.bar(x + i * w, s['values'], w, label=s['name'])",
|
|
36842
|
+
" ax.set_xticks(x + w * (len(series) - 1) / 2); ax.set_xticklabels(categories)",
|
|
36843
|
+
" ax.legend()",
|
|
36844
|
+
"ax.set_title(title)",
|
|
36845
|
+
"plt.tight_layout()",
|
|
36846
|
+
`plt.savefig(${JSON.stringify(pngFile)})`
|
|
36847
|
+
].join("\n");
|
|
36848
|
+
await writeFile5(pyFile, script, "utf8");
|
|
36849
|
+
const { execFile: execFile2 } = await import("node:child_process");
|
|
36850
|
+
const run2 = () => new Promise((resolve6) => execFile2(fig.exe, [pyFile], { timeout: 6e4, windowsHide: true }, (err, stdout, stderr) => resolve6({ err, stdout, stderr })));
|
|
36851
|
+
const r = await run2();
|
|
36852
|
+
let png = null;
|
|
36853
|
+
try {
|
|
36854
|
+
png = await readFile6(pngFile);
|
|
36855
|
+
} catch {
|
|
36106
36856
|
}
|
|
36107
|
-
|
|
36108
|
-
|
|
36109
|
-
|
|
36110
|
-
|
|
36857
|
+
await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
36858
|
+
});
|
|
36859
|
+
if (!png) return "\u7ED8\u56FE\u5931\u8D25\uFF1A" + (r.stderr || r.stdout || "\u672A\u77E5\u9519\u8BEF").slice(0, 300);
|
|
36860
|
+
const { sendFigure: sendFigure2 } = await Promise.resolve().then(() => (init_ai(), ai_exports));
|
|
36861
|
+
const sourceNote = args?.key ? `\uFF08\u6570\u636E\u6765\u6E90\uFF1A\u6761\u76EE ${args.key}\uFF09` : "";
|
|
36862
|
+
try {
|
|
36863
|
+
await sendFigure2(ctx, { png, title, caption: `${args?.caption ?? ""}${sourceNote}`.trim(), sessionId: exec?.agent?.sessionId ?? null });
|
|
36864
|
+
return `\u793A\u610F\u56FE\u300C${title}\u300D\u5DF2\u751F\u6210\u5E76\u63D2\u5165\u5F53\u524D\u5BF9\u8BDD\u3002`;
|
|
36865
|
+
} catch (e) {
|
|
36866
|
+
if (e?.code === "no_session") return "\u793A\u610F\u56FE\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u5BF9\u8BDD\u53EF\u63D2\u5165\u3002\u8BF7\u5148\u6253\u5F00\u4E00\u4E2A\u5BF9\u8BDD\u518D\u8BA9\u6211\u753B\u56FE\u3002";
|
|
36867
|
+
return "\u56FE\u7247\u63D2\u5165\u5BF9\u8BDD\u5931\u8D25\uFF1A" + (e?.message ?? "\u672A\u77E5\u9519\u8BEF");
|
|
36868
|
+
}
|
|
36869
|
+
}
|
|
36870
|
+
};
|
|
36871
|
+
}
|
|
36872
|
+
function saveTool() {
|
|
36873
|
+
return {
|
|
36874
|
+
name: "literature_save",
|
|
36875
|
+
description: "\u628A\u4FA7\u7A97\u4E2D\u5DF2\u8BC6\u522B\u7684\u6587\u732E\u4FDD\u5B58\u5230\u672C\u5730\u6587\u732E\u5E93\u6216\u5BFC\u51FA\u76EE\u5F55\uFF08\u4F1A\u81EA\u52A8\u4E0B\u8F7D\u5168\u6587 PDF\uFF09\u3002",
|
|
36876
|
+
parameters: {
|
|
36877
|
+
type: "object",
|
|
36878
|
+
properties: {
|
|
36879
|
+
key: { type: "string", description: "\u6761\u76EE key\uFF08\u6765\u81EA literature_lookup \u6216 literature_search \u7684\u8FD4\u56DE\uFF09" },
|
|
36880
|
+
mode: { type: "string", description: "\u4FDD\u5B58\u65B9\u5F0F\uFF1Azotero \u6216 dir\uFF0C\u7F3A\u7701\u7528\u914D\u7F6E\u503C" },
|
|
36881
|
+
tags: { type: "string", description: "\u9017\u53F7\u5206\u9694\u7684\u6807\u7B7E" }
|
|
36882
|
+
},
|
|
36883
|
+
required: ["key"]
|
|
36884
|
+
},
|
|
36885
|
+
output: textResult(),
|
|
36886
|
+
timeoutMs: 3e5,
|
|
36887
|
+
async execute(args) {
|
|
36888
|
+
const key = String(args?.key ?? "");
|
|
36889
|
+
if (!key) return "\u7F3A\u5C11\u6761\u76EE key\u3002";
|
|
36890
|
+
const tags = String(args?.tags ?? "").split(",").map((t) => t.trim()).filter(Boolean);
|
|
36891
|
+
const item = await saveItem(key, { mode: args?.mode, tags });
|
|
36892
|
+
if (!item) return `\u627E\u4E0D\u5230\u6761\u76EE ${key}\u3002`;
|
|
36893
|
+
if (item.state === "saved") {
|
|
36894
|
+
return `\u5DF2\u4FDD\u5B58\uFF1A${shortLabel(item.record ?? {})}\uFF08${item.saveMode === "dir" ? item.export?.pdfPath : "\u672C\u5730\u6587\u732E\u5E93"}\uFF09
|
|
36895
|
+
[\u4E0B\u4E00\u6B65] literature_get \u67E5\u770B\u8BE6\u60C5 \xB7 literature_cite \u751F\u6210\u5F15\u7528`;
|
|
36896
|
+
}
|
|
36897
|
+
return `\u4FDD\u5B58\u5931\u8D25\uFF1A${item.error?.message ?? "\u672A\u77E5\u9519\u8BEF"}\uFF08${item.error?.code ?? "unknown"}\uFF09`;
|
|
36898
|
+
}
|
|
36899
|
+
};
|
|
36111
36900
|
}
|
|
36112
36901
|
|
|
36113
36902
|
// src/node/session-hook.js
|
|
@@ -36144,11 +36933,15 @@ function textFromSessionEvent(event) {
|
|
|
36144
36933
|
}
|
|
36145
36934
|
return "";
|
|
36146
36935
|
}
|
|
36147
|
-
function registerSessionHook(
|
|
36936
|
+
function registerSessionHook(ctx2, { activation: activation2, detectIntent: detectIntent2 } = {}) {
|
|
36148
36937
|
const disposers = [];
|
|
36149
36938
|
disposers.push(
|
|
36150
|
-
|
|
36939
|
+
ctx2.on("session/event", (session, event) => {
|
|
36151
36940
|
const text = textFromSessionEvent(event);
|
|
36941
|
+
if (activation2 && detectIntent2 && event?.type === "user/message") {
|
|
36942
|
+
const verdict = detectIntent2(textFromSessionEvent(event));
|
|
36943
|
+
if (verdict.active) activation2.activate(verdict.reason);
|
|
36944
|
+
}
|
|
36152
36945
|
if (!text || text.length < 20) return;
|
|
36153
36946
|
if (!extractIdentifiers(text).length) return;
|
|
36154
36947
|
checkConfig().then((config) => {
|
|
@@ -36170,26 +36963,184 @@ async function checkConfig() {
|
|
|
36170
36963
|
return cachedConfig;
|
|
36171
36964
|
}
|
|
36172
36965
|
|
|
36966
|
+
// src/node/activation.js
|
|
36967
|
+
var IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
36968
|
+
var STRONG = [
|
|
36969
|
+
"\u6587\u732E",
|
|
36970
|
+
"\u8BBA\u6587",
|
|
36971
|
+
"\u53C2\u8003\u6587\u732E",
|
|
36972
|
+
"\u5F15\u7528\u683C\u5F0F",
|
|
36973
|
+
"\u5F15\u6587",
|
|
36974
|
+
"\u7EFC\u8FF0",
|
|
36975
|
+
"\u5F00\u9898",
|
|
36976
|
+
"\u7EC4\u4F1A",
|
|
36977
|
+
"doi",
|
|
36978
|
+
"arxiv",
|
|
36979
|
+
"pmid",
|
|
36980
|
+
"isbn",
|
|
36981
|
+
"bibtex",
|
|
36982
|
+
"apa",
|
|
36983
|
+
"mla",
|
|
36984
|
+
"chicago",
|
|
36985
|
+
"gb/t 7714",
|
|
36986
|
+
"gbt7714",
|
|
36987
|
+
"abstract",
|
|
36988
|
+
"citation",
|
|
36989
|
+
"reference list",
|
|
36990
|
+
"related work",
|
|
36991
|
+
"literature review",
|
|
36992
|
+
"paper",
|
|
36993
|
+
"preprint",
|
|
36994
|
+
"thesis",
|
|
36995
|
+
" dissertation"
|
|
36996
|
+
];
|
|
36997
|
+
var WEAK = ["\u641C\u96C6", "\u6536\u96C6", "\u68C0\u7D22", "\u67E5\u9605", "\u6574\u7406", "\u51C6\u5907", "\u8C03\u7814", "\u67E5\u4E00\u4E0B", "\u627E\u51E0\u7BC7", "search", "collect", "gather", "find some"];
|
|
36998
|
+
var ACADEMIC_COMPANION = [
|
|
36999
|
+
"\u6587\u732E",
|
|
37000
|
+
"\u8BBA\u6587",
|
|
37001
|
+
"\u8D44\u6599",
|
|
37002
|
+
"\u7814\u7A76",
|
|
37003
|
+
"\u5B66\u672F",
|
|
37004
|
+
"\u671F\u520A",
|
|
37005
|
+
"\u4F1A\u8BAE",
|
|
37006
|
+
"\u5B9E\u9A8C",
|
|
37007
|
+
"\u65B9\u6CD5",
|
|
37008
|
+
"\u7ED3\u8BBA",
|
|
37009
|
+
"research",
|
|
37010
|
+
"study",
|
|
37011
|
+
"studies",
|
|
37012
|
+
"academic",
|
|
37013
|
+
"journal",
|
|
37014
|
+
"conference",
|
|
37015
|
+
"survey"
|
|
37016
|
+
];
|
|
37017
|
+
var NEGATIVE = [
|
|
37018
|
+
"\u62A5\u9519",
|
|
37019
|
+
"\u5D29\u6E83",
|
|
37020
|
+
"\u7F16\u8BD1",
|
|
37021
|
+
"\u6784\u5EFA",
|
|
37022
|
+
"\u90E8\u7F72",
|
|
37023
|
+
"\u5355\u5143\u6D4B\u8BD5",
|
|
37024
|
+
"commit",
|
|
37025
|
+
"merge",
|
|
37026
|
+
"\u91CD\u6784",
|
|
37027
|
+
"debug",
|
|
37028
|
+
"stack trace",
|
|
37029
|
+
"segfault",
|
|
37030
|
+
"npm ",
|
|
37031
|
+
"pnpm ",
|
|
37032
|
+
"yarn ",
|
|
37033
|
+
"git ",
|
|
37034
|
+
"build failed",
|
|
37035
|
+
"regression"
|
|
37036
|
+
];
|
|
37037
|
+
function normalize(text) {
|
|
37038
|
+
return String(text ?? "").toLowerCase();
|
|
37039
|
+
}
|
|
37040
|
+
function hitCount(text, list) {
|
|
37041
|
+
let n = 0;
|
|
37042
|
+
for (const w of list) if (text.includes(w)) n += 1;
|
|
37043
|
+
return n;
|
|
37044
|
+
}
|
|
37045
|
+
function detectIntent(text) {
|
|
37046
|
+
const t = normalize(text);
|
|
37047
|
+
if (!t || t.length < 6) return { active: false, score: 0, reason: "empty" };
|
|
37048
|
+
const strong = hitCount(t, STRONG);
|
|
37049
|
+
if (strong > 0) {
|
|
37050
|
+
const neg = hitCount(t, NEGATIVE);
|
|
37051
|
+
if (neg > 0 && neg >= strong) return { active: false, score: 0, reason: "coding-context" };
|
|
37052
|
+
return { active: true, score: 1, reason: "strong-signal" };
|
|
37053
|
+
}
|
|
37054
|
+
const weak = hitCount(t, WEAK);
|
|
37055
|
+
if (weak > 0 && hitCount(t, ACADEMIC_COMPANION) > 0) {
|
|
37056
|
+
return { active: true, score: 0.6, reason: "weak+academic" };
|
|
37057
|
+
}
|
|
37058
|
+
return { active: false, score: 0, reason: "no-signal" };
|
|
37059
|
+
}
|
|
37060
|
+
function createActivation({ idleTimeoutMs = IDLE_TIMEOUT_MS } = {}) {
|
|
37061
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
37062
|
+
let active = false;
|
|
37063
|
+
let reason = "";
|
|
37064
|
+
let timer = null;
|
|
37065
|
+
let lastActivityAt = 0;
|
|
37066
|
+
function emit2(next) {
|
|
37067
|
+
active = next;
|
|
37068
|
+
for (const fn of listeners) {
|
|
37069
|
+
try {
|
|
37070
|
+
fn({ active, reason });
|
|
37071
|
+
} catch {
|
|
37072
|
+
}
|
|
37073
|
+
}
|
|
37074
|
+
}
|
|
37075
|
+
function clearTimer() {
|
|
37076
|
+
if (timer) {
|
|
37077
|
+
clearTimeout(timer);
|
|
37078
|
+
timer = null;
|
|
37079
|
+
}
|
|
37080
|
+
}
|
|
37081
|
+
function armIdle() {
|
|
37082
|
+
clearTimer();
|
|
37083
|
+
timer = setTimeout(() => {
|
|
37084
|
+
if (!active) return;
|
|
37085
|
+
reason = "idle-timeout";
|
|
37086
|
+
emit2(false);
|
|
37087
|
+
}, idleTimeoutMs);
|
|
37088
|
+
timer.unref?.();
|
|
37089
|
+
}
|
|
37090
|
+
return {
|
|
37091
|
+
/** Mount the tools. Safe to call repeatedly — it just refreshes the idle timer. */
|
|
37092
|
+
activate(why = "manual") {
|
|
37093
|
+
lastActivityAt = Date.now();
|
|
37094
|
+
if (!active) {
|
|
37095
|
+
reason = why;
|
|
37096
|
+
emit2(true);
|
|
37097
|
+
}
|
|
37098
|
+
armIdle();
|
|
37099
|
+
},
|
|
37100
|
+
deactivate(why = "manual") {
|
|
37101
|
+
clearTimer();
|
|
37102
|
+
if (active) {
|
|
37103
|
+
reason = why;
|
|
37104
|
+
emit2(false);
|
|
37105
|
+
}
|
|
37106
|
+
},
|
|
37107
|
+
onTransition(fn) {
|
|
37108
|
+
listeners.add(fn);
|
|
37109
|
+
return () => listeners.delete(fn);
|
|
37110
|
+
},
|
|
37111
|
+
isActive: () => active,
|
|
37112
|
+
reason: () => reason,
|
|
37113
|
+
lastActivityAt: () => lastActivityAt,
|
|
37114
|
+
dispose() {
|
|
37115
|
+
clearTimer();
|
|
37116
|
+
listeners.clear();
|
|
37117
|
+
}
|
|
37118
|
+
};
|
|
37119
|
+
}
|
|
37120
|
+
|
|
36173
37121
|
// src/node/index.js
|
|
36174
37122
|
init_log();
|
|
36175
37123
|
var name = "dsh-literature-pre";
|
|
36176
37124
|
var inject = ["webServer", "tools"];
|
|
36177
|
-
function apply(
|
|
37125
|
+
function apply(ctx2, config) {
|
|
36178
37126
|
const onUncaught = (e) => error("uncaught exception:", e?.stack ?? e);
|
|
36179
37127
|
const onUnhandled = (e) => error("unhandled rejection:", e?.stack ?? e);
|
|
36180
37128
|
process.on("uncaughtException", onUncaught);
|
|
36181
37129
|
process.on("unhandledRejection", onUnhandled);
|
|
36182
37130
|
const disposers = [];
|
|
36183
|
-
|
|
37131
|
+
ctx2.effect(() => {
|
|
36184
37132
|
ensureDirs().then(() => init()).catch((e) => error("storage init failed:", e.message));
|
|
36185
37133
|
}, "dsh-literature: storage");
|
|
36186
37134
|
const ready = (async () => {
|
|
36187
37135
|
await ensureDirs();
|
|
36188
37136
|
await init();
|
|
36189
|
-
|
|
36190
|
-
|
|
37137
|
+
const activation2 = createActivation();
|
|
37138
|
+
const toolsCtl = registerTools(ctx2);
|
|
37139
|
+
disposers.push(activation2.onTransition(({ active }) => active ? toolsCtl.mount() : toolsCtl.unmount()));
|
|
37140
|
+
disposers.push(() => activation2.dispose());
|
|
37141
|
+
disposers.push(...registerRoutes(ctx2, { activation: activation2 }));
|
|
36191
37142
|
try {
|
|
36192
|
-
disposers.push(...registerSessionHook(
|
|
37143
|
+
disposers.push(...registerSessionHook(ctx2, { activation: activation2, detectIntent }));
|
|
36193
37144
|
} catch (e) {
|
|
36194
37145
|
error("session hook unavailable:", e.message);
|
|
36195
37146
|
}
|