@a9i5k4/dsh-literature 0.2.9 → 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 +1461 -470
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1774,13 +1774,46 @@ __export(cite_exports, {
|
|
|
1774
1774
|
stripItalic: () => stripItalic,
|
|
1775
1775
|
toSegments: () => toSegments
|
|
1776
1776
|
});
|
|
1777
|
-
function
|
|
1777
|
+
function apaInitials(firstName) {
|
|
1778
|
+
const s = String(firstName ?? "").trim();
|
|
1779
|
+
if (!s) return "";
|
|
1780
|
+
return s.charAt(0).toUpperCase() + ".";
|
|
1781
|
+
}
|
|
1782
|
+
function apaAuthors(record) {
|
|
1783
|
+
const list = record.authors ?? [];
|
|
1784
|
+
if (!list.length) return "";
|
|
1785
|
+
const name2 = (a) => {
|
|
1786
|
+
if (CJK.test(a.lastName ?? "") || CJK.test(a.firstName ?? "")) return `${a.lastName ?? ""}${a.firstName ?? ""}`;
|
|
1787
|
+
return [a.lastName, apaInitials(a.firstName)].filter(Boolean).join(", ");
|
|
1788
|
+
};
|
|
1789
|
+
if (list.length === 1) return name2(list[0]);
|
|
1790
|
+
if (list.length <= 20) {
|
|
1791
|
+
const names = list.map(name2);
|
|
1792
|
+
return names.slice(0, -1).join(", ") + ", & " + names[names.length - 1];
|
|
1793
|
+
}
|
|
1794
|
+
return list.slice(0, 19).map(name2).join(", ") + ", \u2026 " + name2(list[list.length - 1]);
|
|
1795
|
+
}
|
|
1796
|
+
function mlaAuthors(record) {
|
|
1778
1797
|
const list = record.authors ?? [];
|
|
1779
1798
|
if (!list.length) return "";
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
if (
|
|
1783
|
-
return
|
|
1799
|
+
const inverted = (a) => [a.lastName, a.firstName].filter(Boolean).join(", ");
|
|
1800
|
+
const upright = (a) => [a.firstName, a.lastName].filter(Boolean).join(" ");
|
|
1801
|
+
if (list.length === 1) return inverted(list[0]);
|
|
1802
|
+
if (list.length === 2) return inverted(list[0]) + ", and " + upright(list[1]);
|
|
1803
|
+
return inverted(list[0]) + ", et al";
|
|
1804
|
+
}
|
|
1805
|
+
function chicagoAuthors(record) {
|
|
1806
|
+
const list = record.authors ?? [];
|
|
1807
|
+
if (!list.length) return "";
|
|
1808
|
+
const inverted = (a) => [a.lastName, a.firstName].filter(Boolean).join(", ");
|
|
1809
|
+
const upright = (a) => [a.firstName, a.lastName].filter(Boolean).join(" ");
|
|
1810
|
+
if (list.length === 1) return inverted(list[0]);
|
|
1811
|
+
if (list.length === 2) return inverted(list[0]) + ", and " + upright(list[1]);
|
|
1812
|
+
if (list.length <= 10) {
|
|
1813
|
+
const parts = [inverted(list[0]), ...list.slice(1, -1).map(upright)];
|
|
1814
|
+
return parts.join(", ") + ", and " + upright(list[list.length - 1]);
|
|
1815
|
+
}
|
|
1816
|
+
return list.slice(0, 7).map(inverted).join(", ") + ", et al";
|
|
1784
1817
|
}
|
|
1785
1818
|
function authorsShort(record) {
|
|
1786
1819
|
const list = record.authors ?? [];
|
|
@@ -1800,8 +1833,8 @@ function doiUrl(record) {
|
|
|
1800
1833
|
return record.doi ? `https://doi.org/${record.doi}` : record.url ?? "";
|
|
1801
1834
|
}
|
|
1802
1835
|
function apa(record) {
|
|
1803
|
-
const authors2 =
|
|
1804
|
-
const who = authors2 ? `${authors2}
|
|
1836
|
+
const authors2 = apaAuthors(record);
|
|
1837
|
+
const who = authors2 ? `${authors2} ` : "";
|
|
1805
1838
|
const year = `(${yearStr(record)}). `;
|
|
1806
1839
|
const title = (record.title ?? "Untitled").trim();
|
|
1807
1840
|
if (record.itemType === "journalArticle" || record.itemType === "preprint") {
|
|
@@ -1833,10 +1866,16 @@ function apa(record) {
|
|
|
1833
1866
|
}
|
|
1834
1867
|
function gb(record) {
|
|
1835
1868
|
const list = record.authors ?? [];
|
|
1869
|
+
const cjk = (s) => /[\u4e00-\u9fff]/.test(s ?? "");
|
|
1870
|
+
const gbName = (a) => {
|
|
1871
|
+
if (cjk(a.lastName) || cjk(a.firstName)) return `${a.lastName ?? ""}${a.firstName ?? ""}`;
|
|
1872
|
+
const ini = String(a.firstName ?? "").trim();
|
|
1873
|
+
return [a.lastName, ini ? ini.charAt(0).toUpperCase() : ""].filter(Boolean).join(" ");
|
|
1874
|
+
};
|
|
1836
1875
|
let who;
|
|
1837
1876
|
if (!list.length) who = "";
|
|
1838
|
-
else if (list.length <= 3) who = list.map(
|
|
1839
|
-
else who = `${list.slice(0, 3).map(
|
|
1877
|
+
else if (list.length <= 3) who = list.map(gbName).join(", ");
|
|
1878
|
+
else who = `${list.slice(0, 3).map(gbName).join(", ")}, \u7B49`;
|
|
1840
1879
|
const whoPart = who ? `${who}. ` : "";
|
|
1841
1880
|
const title = (record.title ?? "").trim();
|
|
1842
1881
|
const year = yearStr(record);
|
|
@@ -1865,8 +1904,8 @@ function gb(record) {
|
|
|
1865
1904
|
return `${whoPart}${title}[Z]. ${year}.`.trim();
|
|
1866
1905
|
}
|
|
1867
1906
|
function mla(record) {
|
|
1868
|
-
const
|
|
1869
|
-
const who =
|
|
1907
|
+
const who0 = mlaAuthors(record);
|
|
1908
|
+
const who = who0 ? who0 + ". " : "";
|
|
1870
1909
|
const title = (record.title ?? "Untitled").trim();
|
|
1871
1910
|
if (record.itemType === "journalArticle" || record.itemType === "preprint") {
|
|
1872
1911
|
const journal = record.container ? ` *${record.container}*, ` : "";
|
|
@@ -1884,8 +1923,8 @@ function mla(record) {
|
|
|
1884
1923
|
return `${who}"${title}." ${record.publisher ?? ""} ${yearStr(record)}.`.trim();
|
|
1885
1924
|
}
|
|
1886
1925
|
function chicago(record) {
|
|
1887
|
-
const
|
|
1888
|
-
const who =
|
|
1926
|
+
const who0 = chicagoAuthors(record);
|
|
1927
|
+
const who = who0 ? who0 + ". " : "";
|
|
1889
1928
|
const title = (record.title ?? "Untitled").trim();
|
|
1890
1929
|
if (record.itemType === "journalArticle" || record.itemType === "preprint") {
|
|
1891
1930
|
const journal = record.container ? ` *${record.container}*` : "";
|
|
@@ -1990,14 +2029,15 @@ function authorsShortGb(record) {
|
|
|
1990
2029
|
if (!list.length) return "\u4F5A\u540D";
|
|
1991
2030
|
if (list.length === 1) return list[0].lastName;
|
|
1992
2031
|
if (list.length === 2) return `${list[0].lastName}\u3001${list[1].lastName}`;
|
|
1993
|
-
return `${list[0].lastName}\u7B49`;
|
|
2032
|
+
return `${list[0].lastName} \u7B49`;
|
|
1994
2033
|
}
|
|
1995
2034
|
function listStyles() {
|
|
1996
2035
|
return Object.entries(STYLES).map(([id, s]) => ({ id, label: s.label }));
|
|
1997
2036
|
}
|
|
1998
|
-
var STYLES;
|
|
2037
|
+
var CJK, STYLES;
|
|
1999
2038
|
var init_cite = __esm({
|
|
2000
2039
|
"src/node/cite.js"() {
|
|
2040
|
+
CJK = /[\u4e00-\u9fff]/;
|
|
2001
2041
|
STYLES = {
|
|
2002
2042
|
apa: { label: "APA 7th", format: apa },
|
|
2003
2043
|
gb: { label: "GB/T 7714-2015", format: gb },
|
|
@@ -2586,6 +2626,183 @@ var init_importer = __esm({
|
|
|
2586
2626
|
}
|
|
2587
2627
|
});
|
|
2588
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
|
+
|
|
2589
2806
|
// src/node/pipeline.js
|
|
2590
2807
|
var pipeline_exports = {};
|
|
2591
2808
|
__export(pipeline_exports, {
|
|
@@ -2593,6 +2810,7 @@ __export(pipeline_exports, {
|
|
|
2593
2810
|
arxivBase: () => arxivBase,
|
|
2594
2811
|
discardItem: () => discardItem,
|
|
2595
2812
|
fetchItemPdf: () => fetchItemPdf,
|
|
2813
|
+
importDroppedCourseware: () => importDroppedCourseware,
|
|
2596
2814
|
importDroppedPdf: () => importDroppedPdf,
|
|
2597
2815
|
importPdf: () => importPdf,
|
|
2598
2816
|
log: () => log,
|
|
@@ -2893,8 +3111,8 @@ async function saveItem(key, { mode, tags } = {}) {
|
|
|
2893
3111
|
if (wantMode === "dir") {
|
|
2894
3112
|
let buffer = null;
|
|
2895
3113
|
if (current.pdf?.path) {
|
|
2896
|
-
const { readFile:
|
|
2897
|
-
buffer = await
|
|
3114
|
+
const { readFile: readFile7 } = await import("node:fs/promises");
|
|
3115
|
+
buffer = await readFile7(current.pdf.path).catch(() => null);
|
|
2898
3116
|
}
|
|
2899
3117
|
result = await exportToDirectory(current.record, buffer);
|
|
2900
3118
|
const updated2 = await patchItem(key, { state: "saved", saveMode: "dir", export: result, error: null, updatedAt: Date.now() });
|
|
@@ -2904,14 +3122,14 @@ async function saveItem(key, { mode, tags } = {}) {
|
|
|
2904
3122
|
}
|
|
2905
3123
|
let pdfBuffer = null;
|
|
2906
3124
|
if (current.pdf?.path) {
|
|
2907
|
-
const { readFile:
|
|
2908
|
-
pdfBuffer = await
|
|
3125
|
+
const { readFile: readFile7 } = await import("node:fs/promises");
|
|
3126
|
+
pdfBuffer = await readFile7(current.pdf.path).catch(() => null);
|
|
2909
3127
|
}
|
|
2910
3128
|
if (!pdfBuffer) {
|
|
2911
3129
|
const fetched = await fetchItemPdf(key);
|
|
2912
3130
|
if (fetched?.pdf?.path) {
|
|
2913
|
-
const { readFile:
|
|
2914
|
-
pdfBuffer = await
|
|
3131
|
+
const { readFile: readFile7 } = await import("node:fs/promises");
|
|
3132
|
+
pdfBuffer = await readFile7(fetched.pdf.path).catch(() => null);
|
|
2915
3133
|
} else {
|
|
2916
3134
|
const err = fetched?.error ?? failure("fetch_failed", "\u65E0\u6CD5\u83B7\u53D6\u5168\u6587 PDF\uFF0C\u65E0\u6CD5\u4FDD\u5B58\u5230\u6587\u732E\u5E93");
|
|
2917
3135
|
throw Object.assign(new Error(err.message), { code: err.code ?? "fetch_failed", detail: err.detail });
|
|
@@ -3048,6 +3266,48 @@ async function importDroppedPdf(buffer, { filename = "dropped.pdf" } = {}) {
|
|
|
3048
3266
|
emitItem(saved);
|
|
3049
3267
|
return saved;
|
|
3050
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
|
+
}
|
|
3051
3311
|
var FAILURE_MESSAGES;
|
|
3052
3312
|
var init_pipeline = __esm({
|
|
3053
3313
|
"src/node/pipeline.js"() {
|
|
@@ -3096,6 +3356,118 @@ var init_session_track = __esm({
|
|
|
3096
3356
|
}
|
|
3097
3357
|
});
|
|
3098
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
|
+
|
|
3099
3471
|
// node_modules/pdfjs-dist/legacy/build/pdf.mjs
|
|
3100
3472
|
var pdf_exports = {};
|
|
3101
3473
|
__export(pdf_exports, {
|
|
@@ -3543,7 +3915,7 @@ function getColorValues(colors) {
|
|
|
3543
3915
|
}
|
|
3544
3916
|
span.remove();
|
|
3545
3917
|
}
|
|
3546
|
-
function getCurrentTransform(
|
|
3918
|
+
function getCurrentTransform(ctx2) {
|
|
3547
3919
|
const {
|
|
3548
3920
|
a,
|
|
3549
3921
|
b,
|
|
@@ -3551,10 +3923,10 @@ function getCurrentTransform(ctx) {
|
|
|
3551
3923
|
d,
|
|
3552
3924
|
e,
|
|
3553
3925
|
f
|
|
3554
|
-
} =
|
|
3926
|
+
} = ctx2.getTransform();
|
|
3555
3927
|
return [a, b, c, d, e, f];
|
|
3556
3928
|
}
|
|
3557
|
-
function getCurrentTransformInverse(
|
|
3929
|
+
function getCurrentTransformInverse(ctx2) {
|
|
3558
3930
|
const {
|
|
3559
3931
|
a,
|
|
3560
3932
|
b,
|
|
@@ -3562,7 +3934,7 @@ function getCurrentTransformInverse(ctx) {
|
|
|
3562
3934
|
d,
|
|
3563
3935
|
e,
|
|
3564
3936
|
f
|
|
3565
|
-
} =
|
|
3937
|
+
} = ctx2.getTransform().invertSelf();
|
|
3566
3938
|
return [a, b, c, d, e, f];
|
|
3567
3939
|
}
|
|
3568
3940
|
function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) {
|
|
@@ -4010,7 +4382,7 @@ function loadMeshShader() {
|
|
|
4010
4382
|
function drawMeshWithGPU(posData, colData, vertexCount, context, backgroundColor, paddedWidth, paddedHeight, borderSize) {
|
|
4011
4383
|
return _webGPU.draw(posData, colData, vertexCount, context, backgroundColor, paddedWidth, paddedHeight, borderSize);
|
|
4012
4384
|
}
|
|
4013
|
-
function applyBoundingBox(
|
|
4385
|
+
function applyBoundingBox(ctx2, bbox) {
|
|
4014
4386
|
if (!bbox) {
|
|
4015
4387
|
return;
|
|
4016
4388
|
}
|
|
@@ -4018,7 +4390,7 @@ function applyBoundingBox(ctx, bbox) {
|
|
|
4018
4390
|
const height = bbox[3] - bbox[1];
|
|
4019
4391
|
const region = new Path2D();
|
|
4020
4392
|
region.rect(bbox[0], bbox[1], width, height);
|
|
4021
|
-
|
|
4393
|
+
ctx2.clip(region);
|
|
4022
4394
|
}
|
|
4023
4395
|
function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
|
|
4024
4396
|
const coords = context.coords, colors = context.colors;
|
|
@@ -4124,31 +4496,31 @@ function getShadingPattern(IR) {
|
|
|
4124
4496
|
}
|
|
4125
4497
|
throw new Error(`Unknown IR type: ${IR[0]}`);
|
|
4126
4498
|
}
|
|
4127
|
-
function mirrorContextOperations(
|
|
4128
|
-
if (
|
|
4499
|
+
function mirrorContextOperations(ctx2, destCtx) {
|
|
4500
|
+
if (ctx2._removeMirroring) {
|
|
4129
4501
|
throw new Error("Context is already forwarding operations.");
|
|
4130
4502
|
}
|
|
4131
4503
|
const originalMethods = /* @__PURE__ */ new Map();
|
|
4132
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"]) {
|
|
4133
|
-
const original =
|
|
4505
|
+
const original = ctx2[name2];
|
|
4134
4506
|
if (typeof original !== "function" || typeof destCtx[name2] !== "function") {
|
|
4135
4507
|
continue;
|
|
4136
4508
|
}
|
|
4137
4509
|
originalMethods.set(name2, original);
|
|
4138
|
-
|
|
4510
|
+
ctx2[name2] = function(...args) {
|
|
4139
4511
|
destCtx[name2](...args);
|
|
4140
4512
|
return original.apply(this, args);
|
|
4141
4513
|
};
|
|
4142
4514
|
}
|
|
4143
|
-
|
|
4515
|
+
ctx2._removeMirroring = () => {
|
|
4144
4516
|
for (const [name2, original] of originalMethods) {
|
|
4145
|
-
|
|
4517
|
+
ctx2[name2] = original;
|
|
4146
4518
|
}
|
|
4147
|
-
delete
|
|
4519
|
+
delete ctx2._removeMirroring;
|
|
4148
4520
|
};
|
|
4149
4521
|
}
|
|
4150
|
-
function drawImageAtIntegerCoords(
|
|
4151
|
-
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);
|
|
4152
4524
|
if (b === 0 && c === 0) {
|
|
4153
4525
|
const tlX = destX * a + tx;
|
|
4154
4526
|
const rTlX = Math.round(tlX);
|
|
@@ -4158,9 +4530,9 @@ function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, de
|
|
|
4158
4530
|
const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
|
|
4159
4531
|
const brY = (destY + destH) * d + ty;
|
|
4160
4532
|
const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
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);
|
|
4164
4536
|
return [rWidth, rHeight];
|
|
4165
4537
|
}
|
|
4166
4538
|
if (a === 0 && d === 0) {
|
|
@@ -4172,17 +4544,17 @@ function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, de
|
|
|
4172
4544
|
const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
|
|
4173
4545
|
const brY = (destX + destW) * b + ty;
|
|
4174
4546
|
const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
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);
|
|
4178
4550
|
return [rHeight, rWidth];
|
|
4179
4551
|
}
|
|
4180
|
-
|
|
4552
|
+
ctx2.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
|
|
4181
4553
|
const scaleX = Math.hypot(a, b);
|
|
4182
4554
|
const scaleY = Math.hypot(c, d);
|
|
4183
4555
|
return [scaleX * destW, scaleY * destH];
|
|
4184
4556
|
}
|
|
4185
|
-
function putBinaryImageData(
|
|
4557
|
+
function putBinaryImageData(ctx2, imgData) {
|
|
4186
4558
|
const {
|
|
4187
4559
|
width,
|
|
4188
4560
|
height,
|
|
@@ -4191,7 +4563,7 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4191
4563
|
const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
|
|
4192
4564
|
const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
|
|
4193
4565
|
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
|
|
4194
|
-
const chunkImgData =
|
|
4566
|
+
const chunkImgData = ctx2.createImageData(width, FULL_CHUNK_HEIGHT);
|
|
4195
4567
|
let srcPos = 0;
|
|
4196
4568
|
const src = imgData.data;
|
|
4197
4569
|
const dest = chunkImgData.data;
|
|
@@ -4207,7 +4579,7 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4207
4579
|
width,
|
|
4208
4580
|
height: i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight
|
|
4209
4581
|
}));
|
|
4210
|
-
|
|
4582
|
+
ctx2.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
|
|
4211
4583
|
}
|
|
4212
4584
|
} else if (kind === ImageKind.RGBA_32BPP) {
|
|
4213
4585
|
let j = 0;
|
|
@@ -4215,13 +4587,13 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4215
4587
|
for (i = 0; i < fullChunks; i++) {
|
|
4216
4588
|
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
|
|
4217
4589
|
srcPos += elemsInThisChunk;
|
|
4218
|
-
|
|
4590
|
+
ctx2.putImageData(chunkImgData, 0, j);
|
|
4219
4591
|
j += FULL_CHUNK_HEIGHT;
|
|
4220
4592
|
}
|
|
4221
4593
|
if (i < totalChunks) {
|
|
4222
4594
|
elemsInThisChunk = width * partialChunkHeight * 4;
|
|
4223
4595
|
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
|
|
4224
|
-
|
|
4596
|
+
ctx2.putImageData(chunkImgData, 0, j);
|
|
4225
4597
|
}
|
|
4226
4598
|
} else if (kind === ImageKind.RGB_24BPP) {
|
|
4227
4599
|
for (i = 0; i < totalChunks; i++) {
|
|
@@ -4234,15 +4606,15 @@ function putBinaryImageData(ctx, imgData) {
|
|
|
4234
4606
|
width,
|
|
4235
4607
|
height: i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight
|
|
4236
4608
|
}));
|
|
4237
|
-
|
|
4609
|
+
ctx2.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
|
|
4238
4610
|
}
|
|
4239
4611
|
} else {
|
|
4240
4612
|
throw new Error(`bad image kind: ${kind}`);
|
|
4241
4613
|
}
|
|
4242
4614
|
}
|
|
4243
|
-
function putBinaryImageMask(
|
|
4615
|
+
function putBinaryImageMask(ctx2, imgData) {
|
|
4244
4616
|
if (imgData.bitmap) {
|
|
4245
|
-
|
|
4617
|
+
ctx2.drawImage(imgData.bitmap, 0, 0);
|
|
4246
4618
|
return;
|
|
4247
4619
|
}
|
|
4248
4620
|
const {
|
|
@@ -4252,7 +4624,7 @@ function putBinaryImageMask(ctx, imgData) {
|
|
|
4252
4624
|
const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
|
|
4253
4625
|
const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
|
|
4254
4626
|
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
|
|
4255
|
-
const chunkImgData =
|
|
4627
|
+
const chunkImgData = ctx2.createImageData(width, FULL_CHUNK_HEIGHT);
|
|
4256
4628
|
let srcPos = 0;
|
|
4257
4629
|
const src = imgData.data;
|
|
4258
4630
|
const dest = chunkImgData.data;
|
|
@@ -4267,7 +4639,7 @@ function putBinaryImageMask(ctx, imgData) {
|
|
|
4267
4639
|
height: i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight,
|
|
4268
4640
|
nonBlackColor: 0
|
|
4269
4641
|
}));
|
|
4270
|
-
|
|
4642
|
+
ctx2.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
|
|
4271
4643
|
}
|
|
4272
4644
|
}
|
|
4273
4645
|
function copyCtxState(sourceCtx, destCtx) {
|
|
@@ -4282,25 +4654,25 @@ function copyCtxState(sourceCtx, destCtx) {
|
|
|
4282
4654
|
destCtx.lineDashOffset = sourceCtx.lineDashOffset;
|
|
4283
4655
|
}
|
|
4284
4656
|
}
|
|
4285
|
-
function resetCtxToDefault(
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
if (
|
|
4296
|
-
|
|
4297
|
-
|
|
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;
|
|
4298
4670
|
}
|
|
4299
4671
|
const {
|
|
4300
4672
|
filter
|
|
4301
|
-
} =
|
|
4673
|
+
} = ctx2;
|
|
4302
4674
|
if (filter !== "none" && filter !== "") {
|
|
4303
|
-
|
|
4675
|
+
ctx2.filter = "none";
|
|
4304
4676
|
}
|
|
4305
4677
|
}
|
|
4306
4678
|
function getImageSmoothingEnabled(transform, interpolate) {
|
|
@@ -5950,10 +6322,10 @@ var init_pdf2 = __esm({
|
|
|
5950
6322
|
var isCallable = __webpack_require__2(4901);
|
|
5951
6323
|
var replacement = /#|\.prototype\./;
|
|
5952
6324
|
var isForced = function(feature, detection) {
|
|
5953
|
-
var value = data[
|
|
6325
|
+
var value = data[normalize2(feature)];
|
|
5954
6326
|
return value === POLYFILL ? true : value === NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection;
|
|
5955
6327
|
};
|
|
5956
|
-
var
|
|
6328
|
+
var normalize2 = isForced.normalize = function(string) {
|
|
5957
6329
|
return String(string).replace(replacement, ".").toLowerCase();
|
|
5958
6330
|
};
|
|
5959
6331
|
var data = isForced.data = {};
|
|
@@ -6323,7 +6695,7 @@ var init_pdf2 = __esm({
|
|
|
6323
6695
|
var defineProperty = Object.defineProperty;
|
|
6324
6696
|
var stringSlice = uncurryThis("".slice);
|
|
6325
6697
|
var replace = uncurryThis("".replace);
|
|
6326
|
-
var
|
|
6698
|
+
var join9 = uncurryThis([].join);
|
|
6327
6699
|
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
|
|
6328
6700
|
return defineProperty(function() {
|
|
6329
6701
|
}, "length", { value: 8 }).length !== 8;
|
|
@@ -6350,7 +6722,7 @@ var init_pdf2 = __esm({
|
|
|
6350
6722
|
}
|
|
6351
6723
|
var state2 = enforceInternalState(value);
|
|
6352
6724
|
if (!hasOwn(state2, "source")) {
|
|
6353
|
-
state2.source =
|
|
6725
|
+
state2.source = join9(TEMPLATE, typeof name2 == "string" ? name2 : "");
|
|
6354
6726
|
}
|
|
6355
6727
|
return value;
|
|
6356
6728
|
};
|
|
@@ -8873,7 +9245,7 @@ var init_pdf2 = __esm({
|
|
|
8873
9245
|
var charAt = uncurryThis("".charAt);
|
|
8874
9246
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
8875
9247
|
var $Array = globalThis2.Array;
|
|
8876
|
-
var
|
|
9248
|
+
var join9 = uncurryThis([].join);
|
|
8877
9249
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
|
|
8878
9250
|
try {
|
|
8879
9251
|
var target = new Uint8Array2();
|
|
@@ -8919,7 +9291,7 @@ var init_pdf2 = __esm({
|
|
|
8919
9291
|
result[written++] = "=";
|
|
8920
9292
|
}
|
|
8921
9293
|
}
|
|
8922
|
-
return
|
|
9294
|
+
return join9(result, "");
|
|
8923
9295
|
}
|
|
8924
9296
|
});
|
|
8925
9297
|
},
|
|
@@ -8931,7 +9303,7 @@ var init_pdf2 = __esm({
|
|
|
8931
9303
|
var anUint8Array = __webpack_require__2(4154);
|
|
8932
9304
|
var notDetached = __webpack_require__2(5169);
|
|
8933
9305
|
var numberToString = uncurryThis(1.1.toString);
|
|
8934
|
-
var
|
|
9306
|
+
var join9 = uncurryThis([].join);
|
|
8935
9307
|
var $Array = Array;
|
|
8936
9308
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
8937
9309
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
|
|
@@ -8951,7 +9323,7 @@ var init_pdf2 = __esm({
|
|
|
8951
9323
|
var hex = numberToString(this[i], 16);
|
|
8952
9324
|
result[i] = hex.length === 1 ? "0" + hex : hex;
|
|
8953
9325
|
}
|
|
8954
|
-
return
|
|
9326
|
+
return join9(result, "");
|
|
8955
9327
|
}
|
|
8956
9328
|
});
|
|
8957
9329
|
},
|
|
@@ -9430,13 +9802,13 @@ var init_pdf2 = __esm({
|
|
|
9430
9802
|
});
|
|
9431
9803
|
}
|
|
9432
9804
|
static get isCanvasFilterSupported() {
|
|
9433
|
-
let
|
|
9805
|
+
let ctx2;
|
|
9434
9806
|
if (this.isOffscreenCanvasSupported) {
|
|
9435
|
-
|
|
9807
|
+
ctx2 = new OffscreenCanvas(1, 1).getContext("2d");
|
|
9436
9808
|
} else if (typeof document !== "undefined") {
|
|
9437
|
-
|
|
9809
|
+
ctx2 = document.createElement("canvas").getContext("2d");
|
|
9438
9810
|
}
|
|
9439
|
-
return shadow(this, "isCanvasFilterSupported",
|
|
9811
|
+
return shadow(this, "isCanvasFilterSupported", ctx2?.filter !== void 0);
|
|
9440
9812
|
}
|
|
9441
9813
|
static get isAlphaColorInputSupported() {
|
|
9442
9814
|
if (typeof document === "undefined") {
|
|
@@ -10583,14 +10955,14 @@ var init_pdf2 = __esm({
|
|
|
10583
10955
|
static get _isSVGFittingCanvas() {
|
|
10584
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>`;
|
|
10585
10957
|
const canvas = new OffscreenCanvas(1, 3);
|
|
10586
|
-
const
|
|
10958
|
+
const ctx2 = canvas.getContext("2d", {
|
|
10587
10959
|
willReadFrequently: true
|
|
10588
10960
|
});
|
|
10589
10961
|
const image = new Image();
|
|
10590
10962
|
image.src = svg;
|
|
10591
10963
|
const promise = image.decode().then(() => {
|
|
10592
|
-
|
|
10593
|
-
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;
|
|
10594
10966
|
});
|
|
10595
10967
|
return shadow(this, "_isSVGFittingCanvas", promise);
|
|
10596
10968
|
}
|
|
@@ -10698,8 +11070,8 @@ var init_pdf2 = __esm({
|
|
|
10698
11070
|
return data;
|
|
10699
11071
|
}
|
|
10700
11072
|
const offscreen = new OffscreenCanvas(canvas.width, canvas.height);
|
|
10701
|
-
const
|
|
10702
|
-
|
|
11073
|
+
const ctx2 = offscreen.getContext("2d");
|
|
11074
|
+
ctx2.drawImage(canvas, 0, 0);
|
|
10703
11075
|
data = {
|
|
10704
11076
|
bitmap: offscreen.transferToImageBitmap(),
|
|
10705
11077
|
id: `image_${this.#baseId}_${this.#id++}`,
|
|
@@ -10732,8 +11104,8 @@ var init_pdf2 = __esm({
|
|
|
10732
11104
|
} = data;
|
|
10733
11105
|
if (!data.url && !data.file) {
|
|
10734
11106
|
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
10735
|
-
const
|
|
10736
|
-
|
|
11107
|
+
const ctx2 = canvas.getContext("bitmaprenderer");
|
|
11108
|
+
ctx2.transferFromImageBitmap(bitmap);
|
|
10737
11109
|
data.blobPromise = canvas.convertToBlob();
|
|
10738
11110
|
}
|
|
10739
11111
|
bitmap.close?.();
|
|
@@ -15630,8 +16002,8 @@ var init_pdf2 = __esm({
|
|
|
15630
16002
|
}
|
|
15631
16003
|
return this;
|
|
15632
16004
|
}
|
|
15633
|
-
pushBaseTransform(
|
|
15634
|
-
this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1),
|
|
16005
|
+
pushBaseTransform(ctx2) {
|
|
16006
|
+
this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx2.getTransform()));
|
|
15635
16007
|
return this;
|
|
15636
16008
|
}
|
|
15637
16009
|
popBaseTransform() {
|
|
@@ -15647,8 +16019,8 @@ var init_pdf2 = __esm({
|
|
|
15647
16019
|
}
|
|
15648
16020
|
return this;
|
|
15649
16021
|
}
|
|
15650
|
-
recordClipBox(idx,
|
|
15651
|
-
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());
|
|
15652
16024
|
const clipBox = BBOX_INIT.slice();
|
|
15653
16025
|
Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, clipBox);
|
|
15654
16026
|
const intersection = Util.intersect(this.#clipBox, clipBox);
|
|
@@ -15663,12 +16035,12 @@ var init_pdf2 = __esm({
|
|
|
15663
16035
|
}
|
|
15664
16036
|
return this;
|
|
15665
16037
|
}
|
|
15666
|
-
recordBBox(idx,
|
|
16038
|
+
recordBBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
15667
16039
|
const clipBox = this.#clipBox;
|
|
15668
16040
|
if (clipBox[0] === Infinity) {
|
|
15669
16041
|
return this;
|
|
15670
16042
|
}
|
|
15671
|
-
const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1),
|
|
16043
|
+
const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx2.getTransform());
|
|
15672
16044
|
if (clipBox[0] === -Infinity) {
|
|
15673
16045
|
Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, this.#pendingBBox);
|
|
15674
16046
|
return this;
|
|
@@ -15751,7 +16123,7 @@ var init_pdf2 = __esm({
|
|
|
15751
16123
|
inheritPendingDependenciesAsFutureForcedDependencies() {
|
|
15752
16124
|
return this;
|
|
15753
16125
|
}
|
|
15754
|
-
recordCharacterBBox(idx,
|
|
16126
|
+
recordCharacterBBox(idx, ctx2, font, scale = 1, x = 0, y = 0, getMeasure) {
|
|
15755
16127
|
return this;
|
|
15756
16128
|
}
|
|
15757
16129
|
getSimpleIndex(dependencyName) {
|
|
@@ -15850,8 +16222,8 @@ var init_pdf2 = __esm({
|
|
|
15850
16222
|
this.#bboxTracker.endMarkedContent(opIdx, this.#recordDebugMetadataDepenencyAfterRestore);
|
|
15851
16223
|
return this;
|
|
15852
16224
|
}
|
|
15853
|
-
pushBaseTransform(
|
|
15854
|
-
this.#bboxTracker.pushBaseTransform(
|
|
16225
|
+
pushBaseTransform(ctx2) {
|
|
16226
|
+
this.#bboxTracker.pushBaseTransform(ctx2);
|
|
15855
16227
|
return this;
|
|
15856
16228
|
}
|
|
15857
16229
|
popBaseTransform() {
|
|
@@ -15899,15 +16271,15 @@ var init_pdf2 = __esm({
|
|
|
15899
16271
|
this.#bboxTracker.resetBBox(idx);
|
|
15900
16272
|
return this;
|
|
15901
16273
|
}
|
|
15902
|
-
recordClipBox(idx,
|
|
15903
|
-
this.#bboxTracker.recordClipBox(idx,
|
|
16274
|
+
recordClipBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16275
|
+
this.#bboxTracker.recordClipBox(idx, ctx2, minX, maxX, minY, maxY);
|
|
15904
16276
|
return this;
|
|
15905
16277
|
}
|
|
15906
|
-
recordBBox(idx,
|
|
15907
|
-
this.#bboxTracker.recordBBox(idx,
|
|
16278
|
+
recordBBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16279
|
+
this.#bboxTracker.recordBBox(idx, ctx2, minX, maxX, minY, maxY);
|
|
15908
16280
|
return this;
|
|
15909
16281
|
}
|
|
15910
|
-
recordCharacterBBox(idx,
|
|
16282
|
+
recordCharacterBBox(idx, ctx2, font, scale = 1, x = 0, y = 0, getMeasure) {
|
|
15911
16283
|
const fontBBox = font.bbox;
|
|
15912
16284
|
let isBBoxTrustworthy;
|
|
15913
16285
|
let computedBBox;
|
|
@@ -15920,7 +16292,7 @@ var init_pdf2 = __esm({
|
|
|
15920
16292
|
scaleCharBBox(scale, -scale, x, y, computedBBox);
|
|
15921
16293
|
}
|
|
15922
16294
|
if (isBBoxTrustworthy) {
|
|
15923
|
-
return this.recordBBox(idx,
|
|
16295
|
+
return this.recordBBox(idx, ctx2, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]);
|
|
15924
16296
|
}
|
|
15925
16297
|
}
|
|
15926
16298
|
}
|
|
@@ -15932,10 +16304,10 @@ var init_pdf2 = __esm({
|
|
|
15932
16304
|
isBBoxTrustworthy = computedBBox[0] <= x - measure.actualBoundingBoxLeft && computedBBox[2] >= x + measure.actualBoundingBoxRight && computedBBox[1] <= y - measure.actualBoundingBoxAscent && computedBBox[3] >= y + measure.actualBoundingBoxDescent;
|
|
15933
16305
|
this.#fontBBoxTrustworthy.set(font, isBBoxTrustworthy);
|
|
15934
16306
|
if (isBBoxTrustworthy) {
|
|
15935
|
-
return this.recordBBox(idx,
|
|
16307
|
+
return this.recordBBox(idx, ctx2, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]);
|
|
15936
16308
|
}
|
|
15937
16309
|
}
|
|
15938
|
-
return this.recordBBox(idx,
|
|
16310
|
+
return this.recordBBox(idx, ctx2, x - measure.actualBoundingBoxLeft, x + measure.actualBoundingBoxRight, y - measure.actualBoundingBoxAscent, y + measure.actualBoundingBoxDescent);
|
|
15939
16311
|
}
|
|
15940
16312
|
recordFullPageBBox(idx) {
|
|
15941
16313
|
this.#bboxTracker.recordFullPageBBox(idx);
|
|
@@ -16057,8 +16429,8 @@ var init_pdf2 = __esm({
|
|
|
16057
16429
|
endMarkedContent(opIdx) {
|
|
16058
16430
|
return this;
|
|
16059
16431
|
}
|
|
16060
|
-
pushBaseTransform(
|
|
16061
|
-
this.#dependencyTracker.pushBaseTransform(
|
|
16432
|
+
pushBaseTransform(ctx2) {
|
|
16433
|
+
this.#dependencyTracker.pushBaseTransform(ctx2);
|
|
16062
16434
|
return this;
|
|
16063
16435
|
}
|
|
16064
16436
|
popBaseTransform() {
|
|
@@ -16102,21 +16474,21 @@ var init_pdf2 = __esm({
|
|
|
16102
16474
|
}
|
|
16103
16475
|
return this;
|
|
16104
16476
|
}
|
|
16105
|
-
recordClipBox(idx,
|
|
16477
|
+
recordClipBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16106
16478
|
if (!this.#ignoreBBoxes) {
|
|
16107
|
-
this.#dependencyTracker.recordClipBox(this.#opIdx,
|
|
16479
|
+
this.#dependencyTracker.recordClipBox(this.#opIdx, ctx2, minX, maxX, minY, maxY);
|
|
16108
16480
|
}
|
|
16109
16481
|
return this;
|
|
16110
16482
|
}
|
|
16111
|
-
recordBBox(idx,
|
|
16483
|
+
recordBBox(idx, ctx2, minX, maxX, minY, maxY) {
|
|
16112
16484
|
if (!this.#ignoreBBoxes) {
|
|
16113
|
-
this.#dependencyTracker.recordBBox(this.#opIdx,
|
|
16485
|
+
this.#dependencyTracker.recordBBox(this.#opIdx, ctx2, minX, maxX, minY, maxY);
|
|
16114
16486
|
}
|
|
16115
16487
|
return this;
|
|
16116
16488
|
}
|
|
16117
|
-
recordCharacterBBox(idx,
|
|
16489
|
+
recordCharacterBBox(idx, ctx2, font, scale, x, y, getMeasure) {
|
|
16118
16490
|
if (!this.#ignoreBBoxes) {
|
|
16119
|
-
this.#dependencyTracker.recordCharacterBBox(this.#opIdx,
|
|
16491
|
+
this.#dependencyTracker.recordCharacterBBox(this.#opIdx, ctx2, font, scale, x, y, getMeasure);
|
|
16120
16492
|
}
|
|
16121
16493
|
return this;
|
|
16122
16494
|
}
|
|
@@ -16178,14 +16550,14 @@ var init_pdf2 = __esm({
|
|
|
16178
16550
|
this.#canvasWidth = canvas.width;
|
|
16179
16551
|
this.#canvasHeight = canvas.height;
|
|
16180
16552
|
}
|
|
16181
|
-
record(
|
|
16553
|
+
record(ctx2, width, height, clipBox) {
|
|
16182
16554
|
if (this.#count === this.#capacity) {
|
|
16183
16555
|
this.#capacity *= 2;
|
|
16184
16556
|
const newCoords = new _CanvasImagesTracker.#CoordsArray(this.#capacity * 6);
|
|
16185
16557
|
newCoords.set(this.#coords);
|
|
16186
16558
|
this.#coords = newCoords;
|
|
16187
16559
|
}
|
|
16188
|
-
const transform = getCurrentTransform(
|
|
16560
|
+
const transform = getCurrentTransform(ctx2);
|
|
16189
16561
|
let coords;
|
|
16190
16562
|
if (clipBox[0] !== Infinity) {
|
|
16191
16563
|
const bbox = BBOX_INIT.slice();
|
|
@@ -16411,7 +16783,7 @@ var init_pdf2 = __esm({
|
|
|
16411
16783
|
const canvas = this._document.createElement("canvas");
|
|
16412
16784
|
canvas.width = 1;
|
|
16413
16785
|
canvas.height = 1;
|
|
16414
|
-
const
|
|
16786
|
+
const ctx2 = canvas.getContext("2d");
|
|
16415
16787
|
let called = 0;
|
|
16416
16788
|
function isFontReady(name2, callback) {
|
|
16417
16789
|
if (++called > 30) {
|
|
@@ -16419,9 +16791,9 @@ var init_pdf2 = __esm({
|
|
|
16419
16791
|
callback();
|
|
16420
16792
|
return;
|
|
16421
16793
|
}
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
const imageData =
|
|
16794
|
+
ctx2.font = "30px " + name2;
|
|
16795
|
+
ctx2.fillText(".", 0, 20);
|
|
16796
|
+
const imageData = ctx2.getImageData(0, 0, 1, 1);
|
|
16425
16797
|
if (imageData.data[3] > 0) {
|
|
16426
16798
|
callback();
|
|
16427
16799
|
return;
|
|
@@ -18160,7 +18532,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18160
18532
|
const dist = Math.hypot(this._p0[0] - this._p1[0], this._p0[1] - this._p1[1]);
|
|
18161
18533
|
return dist + this._r1 > this._r0 && dist + this._r0 > this._r1;
|
|
18162
18534
|
}
|
|
18163
|
-
_createGradient(
|
|
18535
|
+
_createGradient(ctx2, transform = null) {
|
|
18164
18536
|
let grad;
|
|
18165
18537
|
let firstPoint = this._p0;
|
|
18166
18538
|
let secondPoint = this._p1;
|
|
@@ -18171,7 +18543,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18171
18543
|
Util.applyTransform(secondPoint, transform);
|
|
18172
18544
|
}
|
|
18173
18545
|
if (this._type === "axial") {
|
|
18174
|
-
grad =
|
|
18546
|
+
grad = ctx2.createLinearGradient(firstPoint[0], firstPoint[1], secondPoint[0], secondPoint[1]);
|
|
18175
18547
|
} else if (this._type === "radial") {
|
|
18176
18548
|
let r0 = this._r0;
|
|
18177
18549
|
let r1 = this._r1;
|
|
@@ -18181,14 +18553,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18181
18553
|
r0 *= scale[0];
|
|
18182
18554
|
r1 *= scale[0];
|
|
18183
18555
|
}
|
|
18184
|
-
grad =
|
|
18556
|
+
grad = ctx2.createRadialGradient(firstPoint[0], firstPoint[1], r0, secondPoint[0], secondPoint[1], r1);
|
|
18185
18557
|
}
|
|
18186
18558
|
for (const colorStop of this._colorStops) {
|
|
18187
18559
|
grad.addColorStop(colorStop[0], colorStop[1]);
|
|
18188
18560
|
}
|
|
18189
18561
|
return grad;
|
|
18190
18562
|
}
|
|
18191
|
-
_createReversedGradient(
|
|
18563
|
+
_createReversedGradient(ctx2, transform = null) {
|
|
18192
18564
|
let firstPoint = this._p1;
|
|
18193
18565
|
let secondPoint = this._p0;
|
|
18194
18566
|
if (transform) {
|
|
@@ -18205,14 +18577,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18205
18577
|
r0 *= scale[0];
|
|
18206
18578
|
r1 *= scale[0];
|
|
18207
18579
|
}
|
|
18208
|
-
const grad =
|
|
18580
|
+
const grad = ctx2.createRadialGradient(firstPoint[0], firstPoint[1], r0, secondPoint[0], secondPoint[1], r1);
|
|
18209
18581
|
const reversedStops = this._colorStops.map(([t, c]) => [1 - t, c]).reverse();
|
|
18210
18582
|
for (const [t, c] of reversedStops) {
|
|
18211
18583
|
grad.addColorStop(t, c);
|
|
18212
18584
|
}
|
|
18213
18585
|
return grad;
|
|
18214
18586
|
}
|
|
18215
|
-
getPattern(
|
|
18587
|
+
getPattern(ctx2, owner, inverse, pathType) {
|
|
18216
18588
|
let pattern;
|
|
18217
18589
|
if (pathType === PathType.STROKE || pathType === PathType.FILL) {
|
|
18218
18590
|
if (this.isOriginBased()) {
|
|
@@ -18227,14 +18599,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18227
18599
|
if (Math.abs(ps) < precision) {
|
|
18228
18600
|
if (this.isRadial()) {
|
|
18229
18601
|
if (Math.abs(n1 - n2) < precision) {
|
|
18230
|
-
return this._createGradient(
|
|
18602
|
+
return this._createGradient(ctx2, transf);
|
|
18231
18603
|
}
|
|
18232
18604
|
} else {
|
|
18233
|
-
return this._createGradient(
|
|
18605
|
+
return this._createGradient(ctx2, transf);
|
|
18234
18606
|
}
|
|
18235
18607
|
}
|
|
18236
18608
|
}
|
|
18237
|
-
const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(
|
|
18609
|
+
const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(ctx2)) || [0, 0, 0, 0];
|
|
18238
18610
|
const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1;
|
|
18239
18611
|
const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1;
|
|
18240
18612
|
const tmpCanvas = owner.canvasFactory.create(width, height);
|
|
@@ -18255,20 +18627,20 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18255
18627
|
}
|
|
18256
18628
|
tmpCtx.fillStyle = this._createGradient(tmpCtx);
|
|
18257
18629
|
tmpCtx.fill();
|
|
18258
|
-
pattern =
|
|
18630
|
+
pattern = ctx2.createPattern(tmpCanvas.canvas, "no-repeat");
|
|
18259
18631
|
owner.canvasFactory.destroy(tmpCanvas);
|
|
18260
18632
|
const domMatrix = new DOMMatrix(inverse);
|
|
18261
18633
|
pattern.setTransform(domMatrix);
|
|
18262
18634
|
} else {
|
|
18263
18635
|
if (this.areConic()) {
|
|
18264
|
-
|
|
18265
|
-
applyBoundingBox(
|
|
18266
|
-
|
|
18267
|
-
|
|
18268
|
-
|
|
18636
|
+
ctx2.save();
|
|
18637
|
+
applyBoundingBox(ctx2, this._bbox);
|
|
18638
|
+
ctx2.fillStyle = this._createReversedGradient(ctx2);
|
|
18639
|
+
ctx2.fillRect(-1e10, -1e10, 2e10, 2e10);
|
|
18640
|
+
ctx2.restore();
|
|
18269
18641
|
}
|
|
18270
|
-
applyBoundingBox(
|
|
18271
|
-
pattern = this._createGradient(
|
|
18642
|
+
applyBoundingBox(ctx2, this._bbox);
|
|
18643
|
+
pattern = this._createGradient(ctx2);
|
|
18272
18644
|
}
|
|
18273
18645
|
return pattern;
|
|
18274
18646
|
}
|
|
@@ -18336,11 +18708,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18336
18708
|
isModifyingCurrentTransform() {
|
|
18337
18709
|
return true;
|
|
18338
18710
|
}
|
|
18339
|
-
getPattern(
|
|
18340
|
-
applyBoundingBox(
|
|
18711
|
+
getPattern(ctx2, owner, inverse, pathType) {
|
|
18712
|
+
applyBoundingBox(ctx2, this._bbox);
|
|
18341
18713
|
const scale = new Float32Array(2);
|
|
18342
18714
|
if (pathType === PathType.SHADING) {
|
|
18343
|
-
Util.singularValueDecompose2dScale(getCurrentTransform(
|
|
18715
|
+
Util.singularValueDecompose2dScale(getCurrentTransform(ctx2), scale);
|
|
18344
18716
|
} else if (this.matrix) {
|
|
18345
18717
|
Util.singularValueDecompose2dScale(this.matrix, scale);
|
|
18346
18718
|
const [matrixScaleX, matrixScaleY] = scale;
|
|
@@ -18352,14 +18724,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18352
18724
|
}
|
|
18353
18725
|
const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.canvasFactory);
|
|
18354
18726
|
if (pathType !== PathType.SHADING) {
|
|
18355
|
-
|
|
18727
|
+
ctx2.setTransform(...owner.baseTransform);
|
|
18356
18728
|
if (this.matrix) {
|
|
18357
|
-
|
|
18729
|
+
ctx2.transform(...this.matrix);
|
|
18358
18730
|
}
|
|
18359
18731
|
}
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
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");
|
|
18363
18735
|
owner.canvasFactory.destroy(temporaryPatternCanvas);
|
|
18364
18736
|
return pattern;
|
|
18365
18737
|
}
|
|
@@ -18375,7 +18747,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18375
18747
|
};
|
|
18376
18748
|
TilingPattern = class _TilingPattern {
|
|
18377
18749
|
static MAX_PATTERN_SIZE = 3e3;
|
|
18378
|
-
constructor(IR,
|
|
18750
|
+
constructor(IR, ctx2, canvasGraphicsFactory, baseTransform) {
|
|
18379
18751
|
this.color = IR[1];
|
|
18380
18752
|
this.operatorList = IR[2];
|
|
18381
18753
|
this.matrix = IR[3];
|
|
@@ -18385,7 +18757,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18385
18757
|
this.paintType = IR[7];
|
|
18386
18758
|
this.tilingType = IR[8];
|
|
18387
18759
|
this.needsIsolation = IR[9] ?? true;
|
|
18388
|
-
this.ctx =
|
|
18760
|
+
this.ctx = ctx2;
|
|
18389
18761
|
this.canvasGraphicsFactory = canvasGraphicsFactory;
|
|
18390
18762
|
this.baseTransform = baseTransform;
|
|
18391
18763
|
this.patternBaseMatrix = this.matrix ? Util.transform(baseTransform, this.matrix) : baseTransform;
|
|
@@ -18587,13 +18959,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18587
18959
|
isModifyingCurrentTransform() {
|
|
18588
18960
|
return false;
|
|
18589
18961
|
}
|
|
18590
|
-
getPattern(
|
|
18962
|
+
getPattern(ctx2, owner, inverse, pathType, opIdx) {
|
|
18591
18963
|
const matrix = pathType !== PathType.SHADING ? Util.transform(inverse, this.patternBaseMatrix) : inverse;
|
|
18592
18964
|
const temporaryPatternCanvas = this.createPatternCanvas(owner, opIdx);
|
|
18593
18965
|
let domMatrix = new DOMMatrix(matrix);
|
|
18594
18966
|
domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
|
|
18595
18967
|
domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY);
|
|
18596
|
-
const pattern =
|
|
18968
|
+
const pattern = ctx2.createPattern(temporaryPatternCanvas.canvas, "repeat");
|
|
18597
18969
|
owner.canvasFactory.destroy(temporaryPatternCanvas.canvasEntry);
|
|
18598
18970
|
pattern.setTransform(domMatrix);
|
|
18599
18971
|
return pattern;
|
|
@@ -18870,13 +19242,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18870
19242
|
this.#knockoutElementDepth = 0;
|
|
18871
19243
|
this.#knockoutGroupLevel = 0;
|
|
18872
19244
|
this.cachedPatterns.clear();
|
|
18873
|
-
for (const
|
|
18874
|
-
for (const canvas of
|
|
19245
|
+
for (const cache3 of this._cachedBitmapsMap.values()) {
|
|
19246
|
+
for (const canvas of cache3.values()) {
|
|
18875
19247
|
if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) {
|
|
18876
19248
|
canvas.width = canvas.height = 0;
|
|
18877
19249
|
}
|
|
18878
19250
|
}
|
|
18879
|
-
|
|
19251
|
+
cache3.clear();
|
|
18880
19252
|
}
|
|
18881
19253
|
this._cachedBitmapsMap.clear();
|
|
18882
19254
|
this.#drawFilter();
|
|
@@ -18962,20 +19334,20 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
18962
19334
|
};
|
|
18963
19335
|
}
|
|
18964
19336
|
_createMaskCanvas(opIdx, img) {
|
|
18965
|
-
const
|
|
19337
|
+
const ctx2 = this.ctx;
|
|
18966
19338
|
const {
|
|
18967
19339
|
width,
|
|
18968
19340
|
height
|
|
18969
19341
|
} = img;
|
|
18970
19342
|
const fillColor = this.current.fillColor;
|
|
18971
19343
|
const isPatternFill = this.current.patternFill;
|
|
18972
|
-
const currentTransform = getCurrentTransform(
|
|
18973
|
-
let
|
|
19344
|
+
const currentTransform = getCurrentTransform(ctx2);
|
|
19345
|
+
let cache3, cacheKey, scaled, maskCanvas;
|
|
18974
19346
|
if ((img.bitmap || img.data) && img.count > 1) {
|
|
18975
19347
|
const mainKey = img.bitmap || img.data.buffer;
|
|
18976
19348
|
cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]);
|
|
18977
|
-
|
|
18978
|
-
const cachedImage =
|
|
19349
|
+
cache3 = this._cachedBitmapsMap.getOrInsertComputed(mainKey, makeMap);
|
|
19350
|
+
const cachedImage = cache3.get(cacheKey);
|
|
18979
19351
|
if (cachedImage && !isPatternFill) {
|
|
18980
19352
|
const offsetX2 = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]);
|
|
18981
19353
|
const offsetY2 = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]);
|
|
@@ -19014,8 +19386,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19014
19386
|
this.canvasFactory.destroy(maskCanvas);
|
|
19015
19387
|
maskCanvas = null;
|
|
19016
19388
|
}
|
|
19017
|
-
if (
|
|
19018
|
-
|
|
19389
|
+
if (cache3 && isPatternFill) {
|
|
19390
|
+
cache3.set(cacheKey, scaled);
|
|
19019
19391
|
scaledEntry = null;
|
|
19020
19392
|
maskCanvas = null;
|
|
19021
19393
|
}
|
|
@@ -19030,15 +19402,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19030
19402
|
}
|
|
19031
19403
|
fillCtx.globalCompositeOperation = "source-in";
|
|
19032
19404
|
const inverse = Util.transform(getCurrentTransformInverse(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]);
|
|
19033
|
-
fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(
|
|
19405
|
+
fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx2, this, inverse, PathType.FILL, opIdx) : fillColor;
|
|
19034
19406
|
fillCtx.fillRect(0, 0, width, height);
|
|
19035
|
-
if (
|
|
19036
|
-
|
|
19407
|
+
if (cache3 && !isPatternFill) {
|
|
19408
|
+
cache3.set(cacheKey, fillCanvas.canvas);
|
|
19037
19409
|
}
|
|
19038
19410
|
this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill);
|
|
19039
19411
|
return {
|
|
19040
19412
|
canvas: fillCanvas.canvas,
|
|
19041
|
-
canvasEntry:
|
|
19413
|
+
canvasEntry: cache3 && !isPatternFill ? null : fillCanvas,
|
|
19042
19414
|
offsetX: Math.round(offsetX),
|
|
19043
19415
|
offsetY: Math.round(offsetY)
|
|
19044
19416
|
};
|
|
@@ -19065,10 +19437,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19065
19437
|
}
|
|
19066
19438
|
setDash(opIdx, dashArray, dashPhase) {
|
|
19067
19439
|
this.dependencyTracker?.recordSimpleData("dash", opIdx);
|
|
19068
|
-
const
|
|
19069
|
-
if (
|
|
19070
|
-
|
|
19071
|
-
|
|
19440
|
+
const ctx2 = this.ctx;
|
|
19441
|
+
if (ctx2.setLineDash !== void 0) {
|
|
19442
|
+
ctx2.setLineDash(dashArray);
|
|
19443
|
+
ctx2.lineDashOffset = dashPhase;
|
|
19072
19444
|
}
|
|
19073
19445
|
}
|
|
19074
19446
|
setRenderingIntent(opIdx, intent) {
|
|
@@ -19267,10 +19639,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19267
19639
|
const scratchCanvas = this.canvasFactory.create(drawnWidth, drawnHeight);
|
|
19268
19640
|
this.smaskScratchCanvas = scratchCanvas;
|
|
19269
19641
|
this.suspendedCtx = this.ctx;
|
|
19270
|
-
const
|
|
19271
|
-
|
|
19272
|
-
copyCtxState(this.suspendedCtx,
|
|
19273
|
-
mirrorContextOperations(
|
|
19642
|
+
const ctx2 = this.ctx = scratchCanvas.context;
|
|
19643
|
+
ctx2.setTransform(this.suspendedCtx.getTransform());
|
|
19644
|
+
copyCtxState(this.suspendedCtx, ctx2);
|
|
19645
|
+
mirrorContextOperations(ctx2, this.suspendedCtx);
|
|
19274
19646
|
this._ensurePreparedSMask(this.current.activeSMask);
|
|
19275
19647
|
this.setGState(opIdx, [["BM", "source-over"]]);
|
|
19276
19648
|
}
|
|
@@ -19339,11 +19711,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19339
19711
|
}
|
|
19340
19712
|
return entry;
|
|
19341
19713
|
}
|
|
19342
|
-
const
|
|
19343
|
-
|
|
19344
|
-
|
|
19345
|
-
|
|
19346
|
-
|
|
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();
|
|
19347
19719
|
return entry;
|
|
19348
19720
|
}
|
|
19349
19721
|
#compositeKnockoutSurface(destCtx, surfaceCanvas, options = {}) {
|
|
@@ -19483,7 +19855,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19483
19855
|
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
|
19484
19856
|
this.ctx.restore();
|
|
19485
19857
|
}
|
|
19486
|
-
composeSMask(
|
|
19858
|
+
composeSMask(ctx2, smask, layerCtx, layerBox) {
|
|
19487
19859
|
const layerOffsetX = layerBox[0];
|
|
19488
19860
|
const layerOffsetY = layerBox[1];
|
|
19489
19861
|
const layerWidth = layerBox[2] - layerOffsetX;
|
|
@@ -19526,15 +19898,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19526
19898
|
} else {
|
|
19527
19899
|
this.genericComposeSMask(smask, layerCtx, layerWidth, layerHeight, layerOffsetX, layerOffsetY);
|
|
19528
19900
|
}
|
|
19529
|
-
if (!
|
|
19901
|
+
if (!ctx2) {
|
|
19530
19902
|
return;
|
|
19531
19903
|
}
|
|
19532
|
-
|
|
19533
|
-
|
|
19534
|
-
|
|
19535
|
-
|
|
19536
|
-
|
|
19537
|
-
|
|
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();
|
|
19538
19910
|
}
|
|
19539
19911
|
_applySMaskOOBAlpha(layerCtx, layerOffsetX, layerOffsetY, layerWidth, layerHeight, maskX0, maskY0, maskX1, maskY1, alpha) {
|
|
19540
19912
|
const hasInnerCutout = maskX0 < maskX1 && maskY0 < maskY1;
|
|
@@ -19641,21 +20013,21 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19641
20013
|
}
|
|
19642
20014
|
stroke(opIdx, path, consumePath = true) {
|
|
19643
20015
|
const started = consumePath && this.#beginKnockoutElement(this.current.strokeAlpha);
|
|
19644
|
-
const
|
|
20016
|
+
const ctx2 = this.ctx;
|
|
19645
20017
|
const strokeColor = this.current.strokeColor;
|
|
19646
|
-
|
|
20018
|
+
ctx2.globalAlpha = this.current.strokeAlpha;
|
|
19647
20019
|
if (this.contentVisible) {
|
|
19648
20020
|
if (typeof strokeColor === "object" && strokeColor?.getPattern) {
|
|
19649
|
-
const baseTransform = strokeColor.isModifyingCurrentTransform() ?
|
|
19650
|
-
|
|
19651
|
-
|
|
20021
|
+
const baseTransform = strokeColor.isModifyingCurrentTransform() ? ctx2.getTransform() : null;
|
|
20022
|
+
ctx2.save();
|
|
20023
|
+
ctx2.strokeStyle = strokeColor.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.STROKE, opIdx);
|
|
19652
20024
|
if (baseTransform) {
|
|
19653
20025
|
const newPath = new Path2D();
|
|
19654
|
-
newPath.addPath(path,
|
|
20026
|
+
newPath.addPath(path, ctx2.getTransform().invertSelf().multiplySelf(baseTransform));
|
|
19655
20027
|
path = newPath;
|
|
19656
20028
|
}
|
|
19657
20029
|
this.rescaleAndStroke(path, false);
|
|
19658
|
-
|
|
20030
|
+
ctx2.restore();
|
|
19659
20031
|
} else {
|
|
19660
20032
|
this.rescaleAndStroke(path, true);
|
|
19661
20033
|
}
|
|
@@ -19664,7 +20036,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19664
20036
|
if (consumePath) {
|
|
19665
20037
|
this.consumePath(opIdx, path, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx)));
|
|
19666
20038
|
}
|
|
19667
|
-
|
|
20039
|
+
ctx2.globalAlpha = this.current.fillAlpha;
|
|
19668
20040
|
this.#endKnockoutElement(started);
|
|
19669
20041
|
}
|
|
19670
20042
|
closeStroke(opIdx, path) {
|
|
@@ -19672,7 +20044,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19672
20044
|
}
|
|
19673
20045
|
fill(opIdx, path, consumePath = true) {
|
|
19674
20046
|
const started = consumePath && this.#beginKnockoutElement(this.current.fillAlpha);
|
|
19675
|
-
const
|
|
20047
|
+
const ctx2 = this.ctx;
|
|
19676
20048
|
const fillColor = this.current.fillColor;
|
|
19677
20049
|
const isPatternFill = this.current.patternFill;
|
|
19678
20050
|
let needRestore = false;
|
|
@@ -19691,27 +20063,27 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19691
20063
|
this.#endKnockoutElement(started);
|
|
19692
20064
|
return;
|
|
19693
20065
|
}
|
|
19694
|
-
const baseTransform = fillColor.isModifyingCurrentTransform() ?
|
|
20066
|
+
const baseTransform = fillColor.isModifyingCurrentTransform() ? ctx2.getTransform() : null;
|
|
19695
20067
|
this.dependencyTracker?.save(opIdx);
|
|
19696
|
-
|
|
19697
|
-
|
|
20068
|
+
ctx2.save();
|
|
20069
|
+
ctx2.fillStyle = fillColor.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.FILL, opIdx);
|
|
19698
20070
|
if (baseTransform) {
|
|
19699
20071
|
const newPath = new Path2D();
|
|
19700
|
-
newPath.addPath(path,
|
|
20072
|
+
newPath.addPath(path, ctx2.getTransform().invertSelf().multiplySelf(baseTransform));
|
|
19701
20073
|
path = newPath;
|
|
19702
20074
|
}
|
|
19703
20075
|
needRestore = true;
|
|
19704
20076
|
}
|
|
19705
20077
|
if (this.contentVisible && intersect !== null) {
|
|
19706
20078
|
if (this.pendingEOFill) {
|
|
19707
|
-
|
|
20079
|
+
ctx2.fill(path, "evenodd");
|
|
19708
20080
|
this.pendingEOFill = false;
|
|
19709
20081
|
} else {
|
|
19710
|
-
|
|
20082
|
+
ctx2.fill(path);
|
|
19711
20083
|
}
|
|
19712
20084
|
}
|
|
19713
20085
|
if (needRestore) {
|
|
19714
|
-
|
|
20086
|
+
ctx2.restore();
|
|
19715
20087
|
this.dependencyTracker?.restore(opIdx);
|
|
19716
20088
|
}
|
|
19717
20089
|
if (consumePath) {
|
|
@@ -19767,7 +20139,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19767
20139
|
}
|
|
19768
20140
|
endText(opIdx) {
|
|
19769
20141
|
const paths = this.pendingTextPaths;
|
|
19770
|
-
const
|
|
20142
|
+
const ctx2 = this.ctx;
|
|
19771
20143
|
if (this.dependencyTracker) {
|
|
19772
20144
|
const {
|
|
19773
20145
|
dependencyTracker
|
|
@@ -19779,7 +20151,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19779
20151
|
}
|
|
19780
20152
|
if (paths !== void 0) {
|
|
19781
20153
|
const newPath = new Path2D();
|
|
19782
|
-
const invTransf =
|
|
20154
|
+
const invTransf = ctx2.getTransform().invertSelf();
|
|
19783
20155
|
for (const {
|
|
19784
20156
|
transform,
|
|
19785
20157
|
x,
|
|
@@ -19792,7 +20164,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19792
20164
|
}
|
|
19793
20165
|
newPath.addPath(path, new DOMMatrix(transform).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize));
|
|
19794
20166
|
}
|
|
19795
|
-
|
|
20167
|
+
ctx2.clip(newPath);
|
|
19796
20168
|
}
|
|
19797
20169
|
delete this.pendingTextPaths;
|
|
19798
20170
|
}
|
|
@@ -19884,7 +20256,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19884
20256
|
return newPath;
|
|
19885
20257
|
}
|
|
19886
20258
|
paintChar(opIdx, character, x, y, patternFillTransform, patternStrokeTransform) {
|
|
19887
|
-
const
|
|
20259
|
+
const ctx2 = this.ctx;
|
|
19888
20260
|
const current = this.current;
|
|
19889
20261
|
const font = current.font;
|
|
19890
20262
|
const textRenderingMode = current.textRenderingMode;
|
|
@@ -19898,25 +20270,25 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19898
20270
|
path = font.getPathGenerator(this.commonObjs, character);
|
|
19899
20271
|
}
|
|
19900
20272
|
if (path && (font.disableFontFace || patternFill || patternStroke)) {
|
|
19901
|
-
|
|
19902
|
-
|
|
19903
|
-
|
|
19904
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20273
|
+
ctx2.save();
|
|
20274
|
+
ctx2.translate(x, y);
|
|
20275
|
+
ctx2.scale(fontSize, -fontSize);
|
|
20276
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font);
|
|
19905
20277
|
let currentTransform;
|
|
19906
20278
|
if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19907
20279
|
if (patternFillTransform) {
|
|
19908
|
-
currentTransform =
|
|
19909
|
-
|
|
20280
|
+
currentTransform = ctx2.getTransform();
|
|
20281
|
+
ctx2.setTransform(...patternFillTransform);
|
|
19910
20282
|
const scaledPath = this.#getScaledPath(path, currentTransform, patternFillTransform);
|
|
19911
|
-
|
|
20283
|
+
ctx2.fill(scaledPath);
|
|
19912
20284
|
} else {
|
|
19913
|
-
|
|
20285
|
+
ctx2.fill(path);
|
|
19914
20286
|
}
|
|
19915
20287
|
}
|
|
19916
20288
|
if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19917
20289
|
if (patternStrokeTransform) {
|
|
19918
|
-
currentTransform ||=
|
|
19919
|
-
|
|
20290
|
+
currentTransform ||= ctx2.getTransform();
|
|
20291
|
+
ctx2.setTransform(...patternStrokeTransform);
|
|
19920
20292
|
const {
|
|
19921
20293
|
a,
|
|
19922
20294
|
b,
|
|
@@ -19926,44 +20298,44 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19926
20298
|
const invPatternTransform = Util.inverseTransform(patternStrokeTransform);
|
|
19927
20299
|
const transf = Util.transform([a, b, c, d, 0, 0], invPatternTransform);
|
|
19928
20300
|
Util.singularValueDecompose2dScale(transf, XY);
|
|
19929
|
-
|
|
19930
|
-
|
|
20301
|
+
ctx2.lineWidth *= Math.max(XY[0], XY[1]) / fontSize;
|
|
20302
|
+
ctx2.stroke(this.#getScaledPath(path, currentTransform, patternStrokeTransform));
|
|
19931
20303
|
} else {
|
|
19932
|
-
|
|
19933
|
-
|
|
20304
|
+
ctx2.lineWidth /= fontSize;
|
|
20305
|
+
ctx2.stroke(path);
|
|
19934
20306
|
}
|
|
19935
20307
|
}
|
|
19936
|
-
|
|
20308
|
+
ctx2.restore();
|
|
19937
20309
|
} else {
|
|
19938
20310
|
if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19939
|
-
|
|
19940
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20311
|
+
ctx2.fillText(character, x, y);
|
|
20312
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font, fontSize, x, y, () => ctx2.measureText(character));
|
|
19941
20313
|
}
|
|
19942
20314
|
if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
19943
20315
|
if (this.dependencyTracker) {
|
|
19944
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20316
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font, fontSize, x, y, () => ctx2.measureText(character)).recordDependencies(opIdx, Dependencies.stroke);
|
|
19945
20317
|
}
|
|
19946
|
-
|
|
20318
|
+
ctx2.strokeText(character, x, y);
|
|
19947
20319
|
}
|
|
19948
20320
|
}
|
|
19949
20321
|
if (isAddToPathSet) {
|
|
19950
20322
|
const paths = this.pendingTextPaths ||= [];
|
|
19951
20323
|
paths.push({
|
|
19952
|
-
transform: getCurrentTransform(
|
|
20324
|
+
transform: getCurrentTransform(ctx2),
|
|
19953
20325
|
x,
|
|
19954
20326
|
y,
|
|
19955
20327
|
fontSize,
|
|
19956
20328
|
path
|
|
19957
20329
|
});
|
|
19958
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20330
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, font, fontSize, x, y);
|
|
19959
20331
|
}
|
|
19960
20332
|
}
|
|
19961
20333
|
get isFontSubpixelAAEnabled() {
|
|
19962
20334
|
const tmpCanvas = this.canvasFactory.create(10, 10);
|
|
19963
|
-
const
|
|
19964
|
-
|
|
19965
|
-
|
|
19966
|
-
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;
|
|
19967
20339
|
this.canvasFactory.destroy(tmpCanvas);
|
|
19968
20340
|
let enabled = false;
|
|
19969
20341
|
for (let i = 3; i < data.length; i += 4) {
|
|
@@ -19996,7 +20368,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
19996
20368
|
return;
|
|
19997
20369
|
}
|
|
19998
20370
|
const started = this.#beginKnockoutElement(current.fillAlpha);
|
|
19999
|
-
const
|
|
20371
|
+
const ctx2 = this.ctx;
|
|
20000
20372
|
const fontSizeScale = current.fontSizeScale;
|
|
20001
20373
|
const charSpacing = current.charSpacing;
|
|
20002
20374
|
const wordSpacing = current.wordSpacing;
|
|
@@ -20008,15 +20380,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20008
20380
|
const defaultVMetrics = font.defaultVMetrics;
|
|
20009
20381
|
const widthAdvanceScale = fontSize * current.fontMatrix[0];
|
|
20010
20382
|
const simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
|
|
20011
|
-
|
|
20383
|
+
ctx2.save();
|
|
20012
20384
|
if (current.textMatrix) {
|
|
20013
|
-
|
|
20385
|
+
ctx2.transform(...current.textMatrix);
|
|
20014
20386
|
}
|
|
20015
|
-
|
|
20387
|
+
ctx2.translate(current.x, current.y + current.textRise);
|
|
20016
20388
|
if (fontDirection > 0) {
|
|
20017
|
-
|
|
20389
|
+
ctx2.scale(textHScale, -1);
|
|
20018
20390
|
} else {
|
|
20019
|
-
|
|
20391
|
+
ctx2.scale(textHScale, 1);
|
|
20020
20392
|
}
|
|
20021
20393
|
let patternFillTransform, patternStrokeTransform;
|
|
20022
20394
|
const fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
|
|
@@ -20032,23 +20404,23 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20032
20404
|
lineWidth /= scale;
|
|
20033
20405
|
}
|
|
20034
20406
|
if (fontSizeScale !== 1) {
|
|
20035
|
-
|
|
20407
|
+
ctx2.scale(fontSizeScale, fontSizeScale);
|
|
20036
20408
|
lineWidth /= fontSizeScale;
|
|
20037
20409
|
}
|
|
20038
|
-
|
|
20410
|
+
ctx2.lineWidth = lineWidth;
|
|
20039
20411
|
if (needsFill && current.patternFill) {
|
|
20040
|
-
|
|
20041
|
-
const pattern = current.fillColor.getPattern(
|
|
20042
|
-
patternFillTransform = getCurrentTransform(
|
|
20043
|
-
|
|
20044
|
-
|
|
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;
|
|
20045
20417
|
}
|
|
20046
20418
|
if (needsStroke && current.patternStroke) {
|
|
20047
|
-
|
|
20048
|
-
const pattern = current.strokeColor.getPattern(
|
|
20049
|
-
patternStrokeTransform = getCurrentTransform(
|
|
20050
|
-
|
|
20051
|
-
|
|
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;
|
|
20052
20424
|
}
|
|
20053
20425
|
if (font.isInvalidPDFjsFont) {
|
|
20054
20426
|
const chars = [];
|
|
@@ -20058,13 +20430,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20058
20430
|
width += glyph.width;
|
|
20059
20431
|
}
|
|
20060
20432
|
const joinedChars = chars.join("");
|
|
20061
|
-
|
|
20433
|
+
ctx2.fillText(joinedChars, 0, 0);
|
|
20062
20434
|
if (this.dependencyTracker !== null) {
|
|
20063
|
-
const measure =
|
|
20435
|
+
const measure = ctx2.measureText(joinedChars);
|
|
20064
20436
|
this.dependencyTracker.recordBBox(opIdx, this.ctx, -measure.actualBoundingBoxLeft, measure.actualBoundingBoxRight, -measure.actualBoundingBoxAscent, measure.actualBoundingBoxDescent).recordShowTextOperation(opIdx);
|
|
20065
20437
|
}
|
|
20066
20438
|
current.x += width * widthAdvanceScale * textHScale;
|
|
20067
|
-
|
|
20439
|
+
ctx2.restore();
|
|
20068
20440
|
this.compose();
|
|
20069
20441
|
this.#endKnockoutElement(started);
|
|
20070
20442
|
return;
|
|
@@ -20095,13 +20467,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20095
20467
|
}
|
|
20096
20468
|
let measure;
|
|
20097
20469
|
if (font.remeasure && width > 0) {
|
|
20098
|
-
measure =
|
|
20470
|
+
measure = ctx2.measureText(character);
|
|
20099
20471
|
const measuredWidth = measure.width * 1e3 / fontSize * fontSizeScale;
|
|
20100
20472
|
if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
|
|
20101
20473
|
const characterScaleX = width / measuredWidth;
|
|
20102
20474
|
restoreNeeded = true;
|
|
20103
|
-
|
|
20104
|
-
|
|
20475
|
+
ctx2.save();
|
|
20476
|
+
ctx2.scale(characterScaleX, 1);
|
|
20105
20477
|
scaledX /= characterScaleX;
|
|
20106
20478
|
} else if (width !== measuredWidth) {
|
|
20107
20479
|
scaledX += (width - measuredWidth) / 2e3 * fontSize / fontSizeScale;
|
|
@@ -20109,10 +20481,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20109
20481
|
}
|
|
20110
20482
|
if (this.contentVisible && (glyph.isInFont || font.missingFile)) {
|
|
20111
20483
|
if (simpleFillText && !accent) {
|
|
20112
|
-
|
|
20113
|
-
this.dependencyTracker?.recordCharacterBBox(opIdx,
|
|
20484
|
+
ctx2.fillText(character, scaledX, scaledY);
|
|
20485
|
+
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx2, measure ? {
|
|
20114
20486
|
bbox: null
|
|
20115
|
-
} : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ??
|
|
20487
|
+
} : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ?? ctx2.measureText(character));
|
|
20116
20488
|
} else {
|
|
20117
20489
|
this.paintChar(opIdx, character, scaledX, scaledY, patternFillTransform, patternStrokeTransform);
|
|
20118
20490
|
if (accent) {
|
|
@@ -20125,7 +20497,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20125
20497
|
const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection;
|
|
20126
20498
|
x += charWidth;
|
|
20127
20499
|
if (restoreNeeded) {
|
|
20128
|
-
|
|
20500
|
+
ctx2.restore();
|
|
20129
20501
|
}
|
|
20130
20502
|
}
|
|
20131
20503
|
if (vertical) {
|
|
@@ -20133,13 +20505,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20133
20505
|
} else {
|
|
20134
20506
|
current.x += x * textHScale;
|
|
20135
20507
|
}
|
|
20136
|
-
|
|
20508
|
+
ctx2.restore();
|
|
20137
20509
|
this.compose();
|
|
20138
20510
|
this.dependencyTracker?.recordShowTextOperation(opIdx);
|
|
20139
20511
|
this.#endKnockoutElement(started);
|
|
20140
20512
|
}
|
|
20141
20513
|
showType3Text(opIdx, glyphs) {
|
|
20142
|
-
const
|
|
20514
|
+
const ctx2 = this.ctx;
|
|
20143
20515
|
const current = this.current;
|
|
20144
20516
|
const font = current.font;
|
|
20145
20517
|
const fontSize = current.fontSize;
|
|
@@ -20157,12 +20529,12 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20157
20529
|
}
|
|
20158
20530
|
this._cachedScaleForStroking[0] = -1;
|
|
20159
20531
|
this._cachedGetSinglePixelWidth = null;
|
|
20160
|
-
|
|
20532
|
+
ctx2.save();
|
|
20161
20533
|
if (current.textMatrix) {
|
|
20162
|
-
|
|
20534
|
+
ctx2.transform(...current.textMatrix);
|
|
20163
20535
|
}
|
|
20164
|
-
|
|
20165
|
-
|
|
20536
|
+
ctx2.translate(current.x, current.y + current.textRise);
|
|
20537
|
+
ctx2.scale(textHScale, fontDirection);
|
|
20166
20538
|
const dependencyTracker = this.dependencyTracker;
|
|
20167
20539
|
this.dependencyTracker = dependencyTracker ? new CanvasNestedDependencyTracker(dependencyTracker, opIdx) : null;
|
|
20168
20540
|
for (i = 0; i < glyphsLength; ++i) {
|
|
@@ -20181,20 +20553,20 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20181
20553
|
this.save();
|
|
20182
20554
|
if (operatorList.fnArray[0] === OPS.setCharWidth) {
|
|
20183
20555
|
current.fillAlpha = current.strokeAlpha = 1;
|
|
20184
|
-
|
|
20556
|
+
ctx2.globalAlpha = 1;
|
|
20185
20557
|
}
|
|
20186
|
-
|
|
20187
|
-
|
|
20558
|
+
ctx2.scale(fontSize, fontSize);
|
|
20559
|
+
ctx2.transform(...fontMatrix);
|
|
20188
20560
|
this.executeOperatorList(operatorList);
|
|
20189
20561
|
this.restore();
|
|
20190
20562
|
}
|
|
20191
20563
|
const p = [glyph.width, 0];
|
|
20192
20564
|
Util.applyTransform(p, fontMatrix);
|
|
20193
20565
|
width = p[0] * fontSize + spacing;
|
|
20194
|
-
|
|
20566
|
+
ctx2.translate(width, 0);
|
|
20195
20567
|
current.x += width * textHScale;
|
|
20196
20568
|
}
|
|
20197
|
-
|
|
20569
|
+
ctx2.restore();
|
|
20198
20570
|
if (dependencyTracker) {
|
|
20199
20571
|
this.dependencyTracker = dependencyTracker;
|
|
20200
20572
|
}
|
|
@@ -20213,7 +20585,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20213
20585
|
if (IR[0] === "TilingPattern") {
|
|
20214
20586
|
const baseTransform = this.baseTransform || getCurrentTransform(this.ctx);
|
|
20215
20587
|
const canvasGraphicsFactory = {
|
|
20216
|
-
createCanvasGraphics: (
|
|
20588
|
+
createCanvasGraphics: (ctx2, renderingOpIdx) => new _CanvasGraphics(ctx2, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {
|
|
20217
20589
|
optionalContentConfig: this.optionalContentConfig,
|
|
20218
20590
|
markedContentStack: this.markedContentStack
|
|
20219
20591
|
}, void 0, void 0, this.dependencyTracker ? new CanvasNestedDependencyTracker(this.dependencyTracker, renderingOpIdx, true) : null)
|
|
@@ -20269,16 +20641,16 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20269
20641
|
return;
|
|
20270
20642
|
}
|
|
20271
20643
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20272
|
-
const
|
|
20644
|
+
const ctx2 = this.ctx;
|
|
20273
20645
|
this.save(opIdx);
|
|
20274
20646
|
const pattern = this._getPattern(opIdx, objId);
|
|
20275
|
-
|
|
20276
|
-
const inv = getCurrentTransformInverse(
|
|
20647
|
+
ctx2.fillStyle = pattern.getPattern(ctx2, this, getCurrentTransformInverse(ctx2), PathType.SHADING, opIdx);
|
|
20648
|
+
const inv = getCurrentTransformInverse(ctx2);
|
|
20277
20649
|
if (inv) {
|
|
20278
20650
|
const {
|
|
20279
20651
|
width,
|
|
20280
20652
|
height
|
|
20281
|
-
} =
|
|
20653
|
+
} = ctx2.canvas;
|
|
20282
20654
|
const minMax = F32_BBOX_INIT.slice();
|
|
20283
20655
|
Util.axialAlignedBoundingBox([0, 0, width, height], inv, minMax);
|
|
20284
20656
|
const [x0, y0, x1, y1] = minMax;
|
|
@@ -20450,19 +20822,19 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20450
20822
|
}
|
|
20451
20823
|
this.groupLevel--;
|
|
20452
20824
|
const groupCtx = this.ctx;
|
|
20453
|
-
const
|
|
20825
|
+
const ctx2 = this.groupStack.pop();
|
|
20454
20826
|
const groupMeta = this.#groupStackMeta.pop();
|
|
20455
20827
|
if (groupMeta) {
|
|
20456
20828
|
this.#knockoutGroupLevel = groupMeta.savedKnockoutLevel;
|
|
20457
20829
|
}
|
|
20458
|
-
if (
|
|
20830
|
+
if (ctx2 === null) {
|
|
20459
20831
|
this.restore(opIdx);
|
|
20460
20832
|
return;
|
|
20461
20833
|
}
|
|
20462
20834
|
if (group.isGray) {
|
|
20463
20835
|
this.#convertGroupToGray(groupCtx);
|
|
20464
20836
|
}
|
|
20465
|
-
this.ctx =
|
|
20837
|
+
this.ctx = ctx2;
|
|
20466
20838
|
this.ctx.imageSmoothingEnabled = false;
|
|
20467
20839
|
this.dependencyTracker?.popBaseTransform();
|
|
20468
20840
|
if (group.smask) {
|
|
@@ -20492,7 +20864,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20492
20864
|
} = groupCtx.canvas;
|
|
20493
20865
|
const colorEntry = this.canvasFactory.create(width, height);
|
|
20494
20866
|
const colorCtx = colorEntry.context;
|
|
20495
|
-
colorCtx.drawImage(
|
|
20867
|
+
colorCtx.drawImage(ctx2.canvas, groupMeta.offsetX, groupMeta.offsetY, width, height, 0, 0, width, height);
|
|
20496
20868
|
colorCtx.globalCompositeOperation = "source-over";
|
|
20497
20869
|
colorCtx.drawImage(groupCtx.canvas, 0, 0);
|
|
20498
20870
|
const shapeMaskEntry = this.#createKnockoutMaskCanvas(groupCtx.canvas);
|
|
@@ -20666,14 +21038,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20666
21038
|
img = this.getObject(opIdx, img.data, img);
|
|
20667
21039
|
img.count = count;
|
|
20668
21040
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20669
|
-
const
|
|
21041
|
+
const ctx2 = this.ctx;
|
|
20670
21042
|
const mask = this._createMaskCanvas(opIdx, img);
|
|
20671
21043
|
const maskCanvas = mask.canvas;
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
21044
|
+
ctx2.save();
|
|
21045
|
+
ctx2.setTransform(1, 0, 0, 1, 0, 0);
|
|
21046
|
+
ctx2.drawImage(maskCanvas, mask.offsetX, mask.offsetY);
|
|
20675
21047
|
this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, mask.offsetX, mask.offsetX + maskCanvas.width, mask.offsetY, mask.offsetY + maskCanvas.height).recordOperation(opIdx);
|
|
20676
|
-
|
|
21048
|
+
ctx2.restore();
|
|
20677
21049
|
if (mask.canvasEntry) {
|
|
20678
21050
|
this.canvasFactory.destroy(mask.canvasEntry);
|
|
20679
21051
|
}
|
|
@@ -20686,19 +21058,19 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20686
21058
|
}
|
|
20687
21059
|
img = this.getObject(opIdx, img.data, img);
|
|
20688
21060
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20689
|
-
const
|
|
20690
|
-
|
|
20691
|
-
const currentTransform = getCurrentTransform(
|
|
20692
|
-
|
|
21061
|
+
const ctx2 = this.ctx;
|
|
21062
|
+
ctx2.save();
|
|
21063
|
+
const currentTransform = getCurrentTransform(ctx2);
|
|
21064
|
+
ctx2.transform(scaleX, skewX, skewY, scaleY, 0, 0);
|
|
20693
21065
|
const mask = this._createMaskCanvas(opIdx, img);
|
|
20694
|
-
|
|
21066
|
+
ctx2.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]);
|
|
20695
21067
|
this.dependencyTracker?.resetBBox(opIdx);
|
|
20696
21068
|
for (let i = 0, ii = positions.length; i < ii; i += 2) {
|
|
20697
21069
|
const trans = Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]);
|
|
20698
|
-
|
|
21070
|
+
ctx2.drawImage(mask.canvas, trans[4], trans[5]);
|
|
20699
21071
|
this.dependencyTracker?.recordBBox(opIdx, this.ctx, trans[4], trans[4] + mask.canvas.width, trans[5], trans[5] + mask.canvas.height);
|
|
20700
21072
|
}
|
|
20701
|
-
|
|
21073
|
+
ctx2.restore();
|
|
20702
21074
|
if (mask.canvasEntry) {
|
|
20703
21075
|
this.canvasFactory.destroy(mask.canvasEntry);
|
|
20704
21076
|
}
|
|
@@ -20711,7 +21083,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20711
21083
|
return;
|
|
20712
21084
|
}
|
|
20713
21085
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20714
|
-
const
|
|
21086
|
+
const ctx2 = this.ctx;
|
|
20715
21087
|
const fillColor = this.current.fillColor;
|
|
20716
21088
|
const isPatternFill = this.current.patternFill;
|
|
20717
21089
|
this.dependencyTracker?.resetBBox(opIdx).recordDependencies(opIdx, Dependencies.transformAndFill);
|
|
@@ -20728,16 +21100,16 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20728
21100
|
const img = this.getObject(opIdx, data, image);
|
|
20729
21101
|
putBinaryImageMask(maskCtx, img);
|
|
20730
21102
|
maskCtx.globalCompositeOperation = "source-in";
|
|
20731
|
-
maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(
|
|
21103
|
+
maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(ctx2), PathType.FILL, opIdx) : fillColor;
|
|
20732
21104
|
maskCtx.fillRect(0, 0, width, height);
|
|
20733
21105
|
maskCtx.restore();
|
|
20734
|
-
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
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);
|
|
20738
21110
|
this.canvasFactory.destroy(maskCanvas);
|
|
20739
|
-
this.dependencyTracker?.recordBBox(opIdx,
|
|
20740
|
-
|
|
21111
|
+
this.dependencyTracker?.recordBBox(opIdx, ctx2, 0, width, 0, height);
|
|
21112
|
+
ctx2.restore();
|
|
20741
21113
|
}
|
|
20742
21114
|
this.compose();
|
|
20743
21115
|
this.dependencyTracker?.recordOperation(opIdx);
|
|
@@ -20777,13 +21149,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20777
21149
|
}
|
|
20778
21150
|
this.paintInlineImageXObjectGroup(opIdx, imgData, map);
|
|
20779
21151
|
}
|
|
20780
|
-
applyTransferMapsToCanvas(
|
|
21152
|
+
applyTransferMapsToCanvas(ctx2) {
|
|
20781
21153
|
if (this.current.transferMaps !== "none") {
|
|
20782
|
-
|
|
20783
|
-
|
|
20784
|
-
|
|
21154
|
+
ctx2.filter = this.current.transferMaps;
|
|
21155
|
+
ctx2.drawImage(ctx2.canvas, 0, 0);
|
|
21156
|
+
ctx2.filter = "none";
|
|
20785
21157
|
}
|
|
20786
|
-
return
|
|
21158
|
+
return ctx2.canvas;
|
|
20787
21159
|
}
|
|
20788
21160
|
applyTransferMapsToBitmap(imgData) {
|
|
20789
21161
|
if (this.current.transferMaps === "none") {
|
|
@@ -20814,15 +21186,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20814
21186
|
const width = imgData.width;
|
|
20815
21187
|
const height = imgData.height;
|
|
20816
21188
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20817
|
-
const
|
|
21189
|
+
const ctx2 = this.ctx;
|
|
20818
21190
|
this.save(opIdx);
|
|
20819
21191
|
const {
|
|
20820
21192
|
filter
|
|
20821
|
-
} =
|
|
21193
|
+
} = ctx2;
|
|
20822
21194
|
if (filter !== "none" && filter !== "") {
|
|
20823
|
-
|
|
21195
|
+
ctx2.filter = "none";
|
|
20824
21196
|
}
|
|
20825
|
-
|
|
21197
|
+
ctx2.scale(1 / width, -1 / height);
|
|
20826
21198
|
let imgToPaint;
|
|
20827
21199
|
let inlineImgCanvas = null;
|
|
20828
21200
|
if (imgData.bitmap) {
|
|
@@ -20835,13 +21207,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20835
21207
|
imgToPaint = this.applyTransferMapsToCanvas(tmpCanvas.context);
|
|
20836
21208
|
inlineImgCanvas = tmpCanvas;
|
|
20837
21209
|
}
|
|
20838
|
-
const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(
|
|
20839
|
-
|
|
21210
|
+
const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(ctx2));
|
|
21211
|
+
ctx2.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(ctx2), imgData.interpolate);
|
|
20840
21212
|
if (this.dependencyTracker) {
|
|
20841
|
-
this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx,
|
|
20842
|
-
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);
|
|
20843
21215
|
}
|
|
20844
|
-
drawImageAtIntegerCoords(
|
|
21216
|
+
drawImageAtIntegerCoords(ctx2, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height);
|
|
20845
21217
|
if (scaled.tmpCanvas) {
|
|
20846
21218
|
this.canvasFactory.destroy(scaled.tmpCanvas);
|
|
20847
21219
|
}
|
|
@@ -20857,7 +21229,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20857
21229
|
return;
|
|
20858
21230
|
}
|
|
20859
21231
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
20860
|
-
const
|
|
21232
|
+
const ctx2 = this.ctx;
|
|
20861
21233
|
let imgToPaint;
|
|
20862
21234
|
let inlineImgCanvas = null;
|
|
20863
21235
|
if (imgData.bitmap) {
|
|
@@ -20872,12 +21244,12 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20872
21244
|
}
|
|
20873
21245
|
this.dependencyTracker?.resetBBox(opIdx);
|
|
20874
21246
|
for (const entry of map) {
|
|
20875
|
-
|
|
20876
|
-
|
|
20877
|
-
|
|
20878
|
-
drawImageAtIntegerCoords(
|
|
20879
|
-
this.dependencyTracker?.recordBBox(opIdx,
|
|
20880
|
-
|
|
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();
|
|
20881
21253
|
}
|
|
20882
21254
|
if (inlineImgCanvas) {
|
|
20883
21255
|
this.canvasFactory.destroy(inlineImgCanvas);
|
|
@@ -20936,13 +21308,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
20936
21308
|
if (!this.pendingClip) {
|
|
20937
21309
|
this.compose(clipBox);
|
|
20938
21310
|
}
|
|
20939
|
-
const
|
|
21311
|
+
const ctx2 = this.ctx;
|
|
20940
21312
|
if (this.pendingClip) {
|
|
20941
21313
|
if (!isEmpty) {
|
|
20942
21314
|
if (this.pendingClip === EO_CLIP) {
|
|
20943
|
-
|
|
21315
|
+
ctx2.clip(path, "evenodd");
|
|
20944
21316
|
} else {
|
|
20945
|
-
|
|
21317
|
+
ctx2.clip(path);
|
|
20946
21318
|
}
|
|
20947
21319
|
}
|
|
20948
21320
|
this.pendingClip = null;
|
|
@@ -21017,36 +21389,36 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
21017
21389
|
}
|
|
21018
21390
|
rescaleAndStroke(path, saveRestore) {
|
|
21019
21391
|
const {
|
|
21020
|
-
ctx,
|
|
21392
|
+
ctx: ctx2,
|
|
21021
21393
|
current: {
|
|
21022
21394
|
lineWidth
|
|
21023
21395
|
}
|
|
21024
21396
|
} = this;
|
|
21025
21397
|
const [scaleX, scaleY] = this.getScaleForStroking();
|
|
21026
21398
|
if (scaleX === scaleY) {
|
|
21027
|
-
|
|
21028
|
-
|
|
21399
|
+
ctx2.lineWidth = (lineWidth || 1) * scaleX;
|
|
21400
|
+
ctx2.stroke(path);
|
|
21029
21401
|
return;
|
|
21030
21402
|
}
|
|
21031
21403
|
const SCALE_MATRIX = _CanvasGraphics.#SCALE_MATRIX ??= new DOMMatrix();
|
|
21032
|
-
const dashes =
|
|
21404
|
+
const dashes = ctx2.getLineDash();
|
|
21033
21405
|
if (saveRestore) {
|
|
21034
|
-
|
|
21406
|
+
ctx2.save();
|
|
21035
21407
|
}
|
|
21036
|
-
|
|
21408
|
+
ctx2.scale(scaleX, scaleY);
|
|
21037
21409
|
SCALE_MATRIX.a = 1 / scaleX;
|
|
21038
21410
|
SCALE_MATRIX.d = 1 / scaleY;
|
|
21039
21411
|
const newPath = new Path2D();
|
|
21040
21412
|
newPath.addPath(path, SCALE_MATRIX);
|
|
21041
21413
|
if (dashes.length > 0) {
|
|
21042
21414
|
const scale = Math.max(scaleX, scaleY);
|
|
21043
|
-
|
|
21044
|
-
|
|
21415
|
+
ctx2.setLineDash(dashes.map((x) => x / scale));
|
|
21416
|
+
ctx2.lineDashOffset /= scale;
|
|
21045
21417
|
}
|
|
21046
|
-
|
|
21047
|
-
|
|
21418
|
+
ctx2.lineWidth = lineWidth || 1;
|
|
21419
|
+
ctx2.stroke(newPath);
|
|
21048
21420
|
if (saveRestore) {
|
|
21049
|
-
|
|
21421
|
+
ctx2.restore();
|
|
21050
21422
|
}
|
|
21051
21423
|
}
|
|
21052
21424
|
isContentVisible() {
|
|
@@ -22745,7 +23117,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22745
23117
|
const {
|
|
22746
23118
|
div,
|
|
22747
23119
|
properties,
|
|
22748
|
-
ctx
|
|
23120
|
+
ctx: ctx2
|
|
22749
23121
|
} = params;
|
|
22750
23122
|
const {
|
|
22751
23123
|
style
|
|
@@ -22758,10 +23130,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22758
23130
|
canvasWidth,
|
|
22759
23131
|
fontSize
|
|
22760
23132
|
} = properties;
|
|
22761
|
-
_TextLayer.#ensureCtxFont(
|
|
23133
|
+
_TextLayer.#ensureCtxFont(ctx2, fontSize * this.#scale, fontFamily);
|
|
22762
23134
|
const {
|
|
22763
23135
|
width
|
|
22764
|
-
} =
|
|
23136
|
+
} = ctx2.measureText(div.textContent);
|
|
22765
23137
|
if (width > 0) {
|
|
22766
23138
|
style.setProperty("--scale-x", canvasWidth * this.#scale / width);
|
|
22767
23139
|
}
|
|
@@ -22783,30 +23155,30 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22783
23155
|
this.#canvasContexts.clear();
|
|
22784
23156
|
}
|
|
22785
23157
|
static #getCtx(lang = null) {
|
|
22786
|
-
let
|
|
22787
|
-
if (!
|
|
23158
|
+
let ctx2 = this.#canvasContexts.get(lang ||= "");
|
|
23159
|
+
if (!ctx2) {
|
|
22788
23160
|
const canvas = document.createElement("canvas");
|
|
22789
23161
|
canvas.style.cssText = "position:absolute;top:0;left:0;width:0;height:0;display:none;letter-spacing:normal;word-spacing:normal";
|
|
22790
23162
|
canvas.lang = lang;
|
|
22791
23163
|
document.body.append(canvas);
|
|
22792
|
-
|
|
23164
|
+
ctx2 = canvas.getContext("2d", {
|
|
22793
23165
|
alpha: false,
|
|
22794
23166
|
willReadFrequently: true
|
|
22795
23167
|
});
|
|
22796
|
-
this.#canvasContexts.set(lang,
|
|
22797
|
-
this.#canvasCtxFonts.set(
|
|
23168
|
+
this.#canvasContexts.set(lang, ctx2);
|
|
23169
|
+
this.#canvasCtxFonts.set(ctx2, {
|
|
22798
23170
|
size: 0,
|
|
22799
23171
|
family: ""
|
|
22800
23172
|
});
|
|
22801
23173
|
}
|
|
22802
|
-
return
|
|
23174
|
+
return ctx2;
|
|
22803
23175
|
}
|
|
22804
|
-
static #ensureCtxFont(
|
|
22805
|
-
const cached3 = this.#canvasCtxFonts.get(
|
|
23176
|
+
static #ensureCtxFont(ctx2, size, family) {
|
|
23177
|
+
const cached3 = this.#canvasCtxFonts.get(ctx2);
|
|
22806
23178
|
if (size === cached3.size && family === cached3.family) {
|
|
22807
23179
|
return;
|
|
22808
23180
|
}
|
|
22809
|
-
|
|
23181
|
+
ctx2.font = `${size}px ${family}`;
|
|
22810
23182
|
cached3.size = size;
|
|
22811
23183
|
cached3.family = family;
|
|
22812
23184
|
}
|
|
@@ -22829,13 +23201,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
22829
23201
|
if (cachedAscent) {
|
|
22830
23202
|
return cachedAscent;
|
|
22831
23203
|
}
|
|
22832
|
-
const
|
|
22833
|
-
|
|
22834
|
-
this.#ensureCtxFont(
|
|
22835
|
-
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("");
|
|
22836
23208
|
const ascent = metrics.fontBoundingBoxAscent;
|
|
22837
23209
|
const descent = Math.abs(metrics.fontBoundingBoxDescent);
|
|
22838
|
-
|
|
23210
|
+
ctx2.canvas.width = ctx2.canvas.height = 0;
|
|
22839
23211
|
let ratio = 0.8;
|
|
22840
23212
|
if (ascent) {
|
|
22841
23213
|
ratio = ascent / (ascent + descent);
|
|
@@ -32575,8 +32947,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32575
32947
|
newWidth = Math.ceil(prevWidth / 2);
|
|
32576
32948
|
newHeight = Math.ceil(prevHeight / 2);
|
|
32577
32949
|
const offscreen2 = new OffscreenCanvas(newWidth, newHeight);
|
|
32578
|
-
const
|
|
32579
|
-
|
|
32950
|
+
const ctx3 = offscreen2.getContext("2d");
|
|
32951
|
+
ctx3.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
|
|
32580
32952
|
prevWidth = newWidth;
|
|
32581
32953
|
prevHeight = newHeight;
|
|
32582
32954
|
if (bitmap !== originalBitmap) {
|
|
@@ -32589,14 +32961,14 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32589
32961
|
newHeight = Math.round(newHeight * ratio);
|
|
32590
32962
|
}
|
|
32591
32963
|
const offscreen = new OffscreenCanvas(newWidth, newHeight);
|
|
32592
|
-
const
|
|
32964
|
+
const ctx2 = offscreen.getContext("2d", {
|
|
32593
32965
|
willReadFrequently: true
|
|
32594
32966
|
});
|
|
32595
|
-
|
|
32596
|
-
|
|
32597
|
-
|
|
32598
|
-
|
|
32599
|
-
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;
|
|
32600
32972
|
const uint8Buf = this.#toUint8(grayImage);
|
|
32601
32973
|
return [uint8Buf, newWidth, newHeight];
|
|
32602
32974
|
}
|
|
@@ -32606,11 +32978,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32606
32978
|
fontWeight
|
|
32607
32979
|
}, pageWidth, pageHeight, rotation, innerMargin) {
|
|
32608
32980
|
let canvas = new OffscreenCanvas(1, 1);
|
|
32609
|
-
let
|
|
32981
|
+
let ctx2 = canvas.getContext("2d", {
|
|
32610
32982
|
alpha: false
|
|
32611
32983
|
});
|
|
32612
32984
|
const fontSize = 200;
|
|
32613
|
-
const font =
|
|
32985
|
+
const font = ctx2.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
32614
32986
|
const {
|
|
32615
32987
|
actualBoundingBoxLeft,
|
|
32616
32988
|
actualBoundingBoxRight,
|
|
@@ -32619,22 +32991,22 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32619
32991
|
fontBoundingBoxAscent,
|
|
32620
32992
|
fontBoundingBoxDescent,
|
|
32621
32993
|
width
|
|
32622
|
-
} =
|
|
32994
|
+
} = ctx2.measureText(text);
|
|
32623
32995
|
const SCALE = 1.5;
|
|
32624
32996
|
const canvasWidth = Math.ceil(Math.max(Math.abs(actualBoundingBoxLeft) + Math.abs(actualBoundingBoxRight) || 0, width) * SCALE);
|
|
32625
32997
|
const canvasHeight = Math.ceil(Math.max(Math.abs(actualBoundingBoxAscent) + Math.abs(actualBoundingBoxDescent) || fontSize, Math.abs(fontBoundingBoxAscent) + Math.abs(fontBoundingBoxDescent) || fontSize) * SCALE);
|
|
32626
32998
|
canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
|
|
32627
|
-
|
|
32999
|
+
ctx2 = canvas.getContext("2d", {
|
|
32628
33000
|
alpha: true,
|
|
32629
33001
|
willReadFrequently: true
|
|
32630
33002
|
});
|
|
32631
|
-
|
|
32632
|
-
|
|
32633
|
-
|
|
32634
|
-
|
|
32635
|
-
|
|
32636
|
-
|
|
32637
|
-
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);
|
|
32638
33010
|
const histogram = this.#getHistogram(uint8Buf);
|
|
32639
33011
|
const threshold = this.#guessThreshold(histogram);
|
|
32640
33012
|
const contourList = this.#findContours(uint8Buf, canvasWidth, canvasHeight, threshold);
|
|
@@ -33600,8 +33972,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33600
33972
|
if (!this.#isSvg) {
|
|
33601
33973
|
bitmap = this.#scaleBitmap(scaledWidth, scaledHeight);
|
|
33602
33974
|
}
|
|
33603
|
-
const
|
|
33604
|
-
|
|
33975
|
+
const ctx2 = canvas.getContext("2d");
|
|
33976
|
+
ctx2.filter = this._uiManager.hcmFilter;
|
|
33605
33977
|
let white = "white", black = "#cfcfd8";
|
|
33606
33978
|
if (this._uiManager.hcmFilter !== "none") {
|
|
33607
33979
|
black = "black";
|
|
@@ -33619,9 +33991,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33619
33991
|
patternCtx.fillStyle = black;
|
|
33620
33992
|
patternCtx.fillRect(0, 0, boxDimWidth, boxDimHeight);
|
|
33621
33993
|
patternCtx.fillRect(boxDimWidth, boxDimHeight, boxDimWidth, boxDimHeight);
|
|
33622
|
-
|
|
33623
|
-
|
|
33624
|
-
|
|
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);
|
|
33625
33997
|
}
|
|
33626
33998
|
let imageData = null;
|
|
33627
33999
|
if (createImageData) {
|
|
@@ -33676,8 +34048,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33676
34048
|
newHeight = Math.ceil(newHeight / 2);
|
|
33677
34049
|
}
|
|
33678
34050
|
const offscreen = new OffscreenCanvas(newWidth, newHeight);
|
|
33679
|
-
const
|
|
33680
|
-
|
|
34051
|
+
const ctx2 = offscreen.getContext("2d");
|
|
34052
|
+
ctx2.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
|
|
33681
34053
|
bitmap = offscreen.transferToImageBitmap();
|
|
33682
34054
|
}
|
|
33683
34055
|
return bitmap;
|
|
@@ -33698,9 +34070,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33698
34070
|
canvas.width = scaledWidth;
|
|
33699
34071
|
canvas.height = scaledHeight;
|
|
33700
34072
|
const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(scaledWidth, scaledHeight);
|
|
33701
|
-
const
|
|
33702
|
-
|
|
33703
|
-
|
|
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);
|
|
33704
34076
|
}
|
|
33705
34077
|
#serializeBitmap(toUrl) {
|
|
33706
34078
|
if (toUrl) {
|
|
@@ -33715,8 +34087,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33715
34087
|
width: canvas.width,
|
|
33716
34088
|
height: canvas.height
|
|
33717
34089
|
} = this.#bitmap);
|
|
33718
|
-
const
|
|
33719
|
-
|
|
34090
|
+
const ctx2 = canvas.getContext("2d");
|
|
34091
|
+
ctx2.drawImage(this.#bitmap, 0, 0);
|
|
33720
34092
|
return canvas.toDataURL();
|
|
33721
34093
|
}
|
|
33722
34094
|
if (this.#isSvg) {
|
|
@@ -33724,8 +34096,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33724
34096
|
const width = Math.round(this.width * pageWidth * PixelsPerInch.PDF_TO_CSS_UNITS);
|
|
33725
34097
|
const height = Math.round(this.height * pageHeight * PixelsPerInch.PDF_TO_CSS_UNITS);
|
|
33726
34098
|
const offscreen = new OffscreenCanvas(width, height);
|
|
33727
|
-
const
|
|
33728
|
-
|
|
34099
|
+
const ctx2 = offscreen.getContext("2d");
|
|
34100
|
+
ctx2.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height);
|
|
33729
34101
|
return offscreen.transferToImageBitmap();
|
|
33730
34102
|
}
|
|
33731
34103
|
return structuredClone(this.#bitmap);
|
|
@@ -35224,10 +35596,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
35224
35596
|
const imageY2 = Math.floor((y1 + height / this.#pageHeight) * pageCanvas.height);
|
|
35225
35597
|
imgElement.width = imageX2 - imageX1;
|
|
35226
35598
|
imgElement.height = imageY2 - imageY1;
|
|
35227
|
-
const
|
|
35228
|
-
|
|
35229
|
-
|
|
35230
|
-
|
|
35599
|
+
const ctx2 = imgElement.getContext("2d");
|
|
35600
|
+
ctx2.setTransform(...inverseTransform);
|
|
35601
|
+
ctx2.translate(-imageX1, -imageY1);
|
|
35602
|
+
ctx2.drawImage(pageCanvas, 0, 0);
|
|
35231
35603
|
});
|
|
35232
35604
|
return container;
|
|
35233
35605
|
}
|
|
@@ -35345,7 +35717,7 @@ async function pdfjs() {
|
|
|
35345
35717
|
return pdfjsPromise;
|
|
35346
35718
|
}
|
|
35347
35719
|
async function extractPdfText(pdfPath, { maxChars = DEFAULT_MAX_CHARS, force = false } = {}) {
|
|
35348
|
-
const hit =
|
|
35720
|
+
const hit = cache2.get(pdfPath);
|
|
35349
35721
|
if (!force && hit && Date.now() - hit.at < CACHE_TTL_MS) return hit.text;
|
|
35350
35722
|
const data = new Uint8Array(await readFile4(pdfPath));
|
|
35351
35723
|
const getDocument2 = (await pdfjs()).getDocument;
|
|
@@ -35367,16 +35739,16 @@ async function extractPdfText(pdfPath, { maxChars = DEFAULT_MAX_CHARS, force = f
|
|
|
35367
35739
|
doc.cleanup?.();
|
|
35368
35740
|
}
|
|
35369
35741
|
const text = chunks.join("\n").trim();
|
|
35370
|
-
|
|
35742
|
+
cache2.set(pdfPath, { text, at: Date.now() });
|
|
35371
35743
|
return text;
|
|
35372
35744
|
}
|
|
35373
|
-
var DEFAULT_MAX_CHARS, CACHE_TTL_MS,
|
|
35745
|
+
var DEFAULT_MAX_CHARS, CACHE_TTL_MS, cache2, pdfjsPromise;
|
|
35374
35746
|
var init_pdf_text = __esm({
|
|
35375
35747
|
"src/node/pdf-text.js"() {
|
|
35376
35748
|
init_log();
|
|
35377
35749
|
DEFAULT_MAX_CHARS = 12e4;
|
|
35378
35750
|
CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
35379
|
-
|
|
35751
|
+
cache2 = /* @__PURE__ */ new Map();
|
|
35380
35752
|
pdfjsPromise = null;
|
|
35381
35753
|
}
|
|
35382
35754
|
});
|
|
@@ -35385,7 +35757,8 @@ var init_pdf_text = __esm({
|
|
|
35385
35757
|
var ai_exports = {};
|
|
35386
35758
|
__export(ai_exports, {
|
|
35387
35759
|
askAi: () => askAi,
|
|
35388
|
-
buildPrompt: () => buildPrompt
|
|
35760
|
+
buildPrompt: () => buildPrompt,
|
|
35761
|
+
sendFigure: () => sendFigure
|
|
35389
35762
|
});
|
|
35390
35763
|
function buildPrompt({ title, action, question = "", selection = "", text = "" }) {
|
|
35391
35764
|
const head = `\u3010\u6587\u732E\u52A9\u624B \xB7 ${title}\u3011`;
|
|
@@ -35432,7 +35805,7 @@ ${text}
|
|
|
35432
35805
|
"""`;
|
|
35433
35806
|
}
|
|
35434
35807
|
}
|
|
35435
|
-
async function askAi(
|
|
35808
|
+
async function askAi(ctx2, { key, action = "ask", question = "", selection = "", sessionId = null } = {}) {
|
|
35436
35809
|
const entry = await getItem(String(key ?? ""));
|
|
35437
35810
|
if (!entry) throw Object.assign(new Error("\u6761\u76EE\u4E0D\u5B58\u5728"), { code: "not_found" });
|
|
35438
35811
|
if (!["translate", "explain", "summarize", "tldr", "ask"].includes(action)) action = "ask";
|
|
@@ -35440,7 +35813,7 @@ async function askAi(ctx, { key, action = "ask", question = "", selection = "",
|
|
|
35440
35813
|
if (!sid) {
|
|
35441
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" });
|
|
35442
35815
|
}
|
|
35443
|
-
const agent =
|
|
35816
|
+
const agent = ctx2?.agents?.get?.(sid);
|
|
35444
35817
|
if (!agent || typeof agent.steer !== "function") {
|
|
35445
35818
|
throw Object.assign(new Error("\u5F53\u524D\u5BF9\u8BDD\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5"), { code: "no_session" });
|
|
35446
35819
|
}
|
|
@@ -35477,6 +35850,38 @@ async function askAi(ctx, { key, action = "ask", question = "", selection = "",
|
|
|
35477
35850
|
log(`ai ask steered (${action}) into session ${sid}`);
|
|
35478
35851
|
return { ok: true, sessionId: sid, action };
|
|
35479
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
|
+
}
|
|
35480
35885
|
var FULLTEXT_ACTIONS, MAX_CONTEXT_CHARS;
|
|
35481
35886
|
var init_ai = __esm({
|
|
35482
35887
|
"src/node/ai.js"() {
|
|
@@ -35498,13 +35903,13 @@ __export(doctor_selfheal_exports, {
|
|
|
35498
35903
|
pipeAvailable: () => pipeAvailable
|
|
35499
35904
|
});
|
|
35500
35905
|
import { createHash } from "node:crypto";
|
|
35501
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
35502
|
-
import { join as
|
|
35503
|
-
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";
|
|
35504
35909
|
import { spawn } from "node:child_process";
|
|
35505
35910
|
import net from "node:net";
|
|
35506
35911
|
function doctorRoot() {
|
|
35507
|
-
return process.env.DSH_DOCTOR_HOME?.trim() ||
|
|
35912
|
+
return process.env.DSH_DOCTOR_HOME?.trim() || join8(homedir4(), ".dsh-doctor");
|
|
35508
35913
|
}
|
|
35509
35914
|
function doctorPipeName(root = doctorRoot()) {
|
|
35510
35915
|
const hash = createHash("sha256").update(root).digest("hex").slice(0, 16);
|
|
@@ -35529,16 +35934,16 @@ function pipeAvailable(pipe, timeoutMs = 1500) {
|
|
|
35529
35934
|
});
|
|
35530
35935
|
}
|
|
35531
35936
|
function findDoctorCli() {
|
|
35532
|
-
const profilesDir =
|
|
35937
|
+
const profilesDir = join8(homedir4(), ".dsh", "profiles");
|
|
35533
35938
|
let entries = [];
|
|
35534
35939
|
try {
|
|
35535
|
-
entries =
|
|
35940
|
+
entries = readdirSync2(profilesDir);
|
|
35536
35941
|
} catch {
|
|
35537
35942
|
return "";
|
|
35538
35943
|
}
|
|
35539
35944
|
for (const name2 of entries) {
|
|
35540
|
-
const candidate =
|
|
35541
|
-
if (
|
|
35945
|
+
const candidate = join8(profilesDir, name2, "node_modules", "@linxin666", "dsh-doctor", "lib", "cli.mjs");
|
|
35946
|
+
if (existsSync2(candidate)) return candidate;
|
|
35542
35947
|
}
|
|
35543
35948
|
return "";
|
|
35544
35949
|
}
|
|
@@ -35729,7 +36134,7 @@ async function readJsonBody2(req) {
|
|
|
35729
36134
|
const { readJsonBody: read } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
35730
36135
|
return read(req);
|
|
35731
36136
|
}
|
|
35732
|
-
async function handler(req, res,
|
|
36137
|
+
async function handler(req, res, ctx2) {
|
|
35733
36138
|
if (!isLoopbackRequest(req)) {
|
|
35734
36139
|
writeJson(res, 403, { error: "forbidden: loopback-only", code: "forbidden" });
|
|
35735
36140
|
return;
|
|
@@ -35747,6 +36152,29 @@ async function handler(req, res, ctx) {
|
|
|
35747
36152
|
await handleEvents(req, res);
|
|
35748
36153
|
return;
|
|
35749
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
|
+
}
|
|
35750
36178
|
if (head === "state" && methodOk(req, "GET")) {
|
|
35751
36179
|
await handleState(res);
|
|
35752
36180
|
return;
|
|
@@ -35896,6 +36324,11 @@ async function handler(req, res, ctx) {
|
|
|
35896
36324
|
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
35897
36325
|
const filename = url.searchParams.get("filename") || "dropped.pdf";
|
|
35898
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
|
+
}
|
|
35899
36332
|
const item = await importDroppedPdf(buffer, { filename });
|
|
35900
36333
|
writeJson(res, 200, { item });
|
|
35901
36334
|
return;
|
|
@@ -35959,7 +36392,7 @@ async function handler(req, res, ctx) {
|
|
|
35959
36392
|
if (sub === "ask" && methodOk(req, "POST")) {
|
|
35960
36393
|
const body = await readJsonBody2(req);
|
|
35961
36394
|
const { askAi: askAi2 } = await Promise.resolve().then(() => (init_ai(), ai_exports));
|
|
35962
|
-
const result = await askAi2(
|
|
36395
|
+
const result = await askAi2(ctx2, {
|
|
35963
36396
|
key: String(body?.key ?? ""),
|
|
35964
36397
|
action: String(body?.action ?? "ask"),
|
|
35965
36398
|
question: String(body?.question ?? ""),
|
|
@@ -35982,11 +36415,11 @@ async function handler(req, res, ctx) {
|
|
|
35982
36415
|
else res.end();
|
|
35983
36416
|
}
|
|
35984
36417
|
}
|
|
35985
|
-
function registerRoutes(
|
|
35986
|
-
const disposers = [
|
|
35987
|
-
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") {
|
|
35988
36421
|
disposers.push(
|
|
35989
|
-
|
|
36422
|
+
ctx2.on("session/event", (session) => {
|
|
35990
36423
|
noteSession(session);
|
|
35991
36424
|
})
|
|
35992
36425
|
);
|
|
@@ -35998,76 +36431,472 @@ function registerRoutes(ctx) {
|
|
|
35998
36431
|
// src/node/tools.js
|
|
35999
36432
|
init_pipeline();
|
|
36000
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
|
|
36001
36525
|
init_normalize();
|
|
36002
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";
|
|
36003
36530
|
function textResult(value) {
|
|
36004
36531
|
return {
|
|
36005
36532
|
schema: { type: "string" },
|
|
36006
36533
|
render: (_args, v) => [{ type: "text", text: String(v) }]
|
|
36007
36534
|
};
|
|
36008
36535
|
}
|
|
36009
|
-
function
|
|
36010
|
-
|
|
36011
|
-
|
|
36012
|
-
|
|
36013
|
-
|
|
36014
|
-
|
|
36015
|
-
|
|
36016
|
-
|
|
36017
|
-
|
|
36018
|
-
|
|
36019
|
-
|
|
36020
|
-
}
|
|
36021
|
-
|
|
36022
|
-
|
|
36023
|
-
|
|
36024
|
-
|
|
36025
|
-
|
|
36026
|
-
|
|
36027
|
-
|
|
36028
|
-
|
|
36029
|
-
|
|
36030
|
-
|
|
36031
|
-
|
|
36032
|
-
|
|
36033
|
-
|
|
36034
|
-
|
|
36035
|
-
const lines = items.filter(Boolean).map((i) => `- ${i.record?.title || i.display} [${i.key}]`);
|
|
36036
|
-
return `\u5DF2\u52A0\u5165\u4FA7\u7A97 ${items.length} \u6761\uFF1A
|
|
36037
|
-
${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
|
+
}
|
|
36038
36562
|
}
|
|
36039
|
-
|
|
36040
|
-
|
|
36041
|
-
|
|
36042
|
-
|
|
36043
|
-
|
|
36044
|
-
|
|
36045
|
-
|
|
36046
|
-
|
|
36047
|
-
|
|
36048
|
-
|
|
36049
|
-
|
|
36050
|
-
|
|
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
|
+
}
|
|
36051
36788
|
},
|
|
36052
|
-
|
|
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" }
|
|
36053
36792
|
},
|
|
36054
|
-
|
|
36055
|
-
|
|
36056
|
-
|
|
36057
|
-
|
|
36058
|
-
|
|
36059
|
-
|
|
36060
|
-
|
|
36061
|
-
|
|
36062
|
-
|
|
36063
|
-
|
|
36064
|
-
|
|
36065
|
-
|
|
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 {
|
|
36066
36856
|
}
|
|
36067
|
-
|
|
36068
|
-
|
|
36069
|
-
|
|
36070
|
-
|
|
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
|
+
};
|
|
36071
36900
|
}
|
|
36072
36901
|
|
|
36073
36902
|
// src/node/session-hook.js
|
|
@@ -36104,11 +36933,15 @@ function textFromSessionEvent(event) {
|
|
|
36104
36933
|
}
|
|
36105
36934
|
return "";
|
|
36106
36935
|
}
|
|
36107
|
-
function registerSessionHook(
|
|
36936
|
+
function registerSessionHook(ctx2, { activation: activation2, detectIntent: detectIntent2 } = {}) {
|
|
36108
36937
|
const disposers = [];
|
|
36109
36938
|
disposers.push(
|
|
36110
|
-
|
|
36939
|
+
ctx2.on("session/event", (session, event) => {
|
|
36111
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
|
+
}
|
|
36112
36945
|
if (!text || text.length < 20) return;
|
|
36113
36946
|
if (!extractIdentifiers(text).length) return;
|
|
36114
36947
|
checkConfig().then((config) => {
|
|
@@ -36130,26 +36963,184 @@ async function checkConfig() {
|
|
|
36130
36963
|
return cachedConfig;
|
|
36131
36964
|
}
|
|
36132
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
|
+
|
|
36133
37121
|
// src/node/index.js
|
|
36134
37122
|
init_log();
|
|
36135
37123
|
var name = "dsh-literature-pre";
|
|
36136
37124
|
var inject = ["webServer", "tools"];
|
|
36137
|
-
function apply(
|
|
37125
|
+
function apply(ctx2, config) {
|
|
36138
37126
|
const onUncaught = (e) => error("uncaught exception:", e?.stack ?? e);
|
|
36139
37127
|
const onUnhandled = (e) => error("unhandled rejection:", e?.stack ?? e);
|
|
36140
37128
|
process.on("uncaughtException", onUncaught);
|
|
36141
37129
|
process.on("unhandledRejection", onUnhandled);
|
|
36142
37130
|
const disposers = [];
|
|
36143
|
-
|
|
37131
|
+
ctx2.effect(() => {
|
|
36144
37132
|
ensureDirs().then(() => init()).catch((e) => error("storage init failed:", e.message));
|
|
36145
37133
|
}, "dsh-literature: storage");
|
|
36146
37134
|
const ready = (async () => {
|
|
36147
37135
|
await ensureDirs();
|
|
36148
37136
|
await init();
|
|
36149
|
-
|
|
36150
|
-
|
|
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 }));
|
|
36151
37142
|
try {
|
|
36152
|
-
disposers.push(...registerSessionHook(
|
|
37143
|
+
disposers.push(...registerSessionHook(ctx2, { activation: activation2, detectIntent }));
|
|
36153
37144
|
} catch (e) {
|
|
36154
37145
|
error("session hook unavailable:", e.message);
|
|
36155
37146
|
}
|