@files-preview-app/preview-file 1.3.2 → 1.3.3
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/README.md +36 -9
- package/dist/angular.cjs +389 -196
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +5 -0
- package/dist/angular.d.ts +5 -0
- package/dist/angular.js +389 -196
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +370 -193
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +370 -193
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +374 -193
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -0
- package/dist/react.d.ts +4 -0
- package/dist/react.js +374 -193
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +373 -194
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +3 -1
- package/dist/vue.d.ts +3 -1
- package/dist/vue.js +373 -194
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3559,26 +3559,6 @@ var ExcelPlugin = class {
|
|
|
3559
3559
|
instance.zoomIn?.();
|
|
3560
3560
|
}
|
|
3561
3561
|
},
|
|
3562
|
-
{
|
|
3563
|
-
id: "fit-page",
|
|
3564
|
-
icon: "fit-page",
|
|
3565
|
-
label: "Fit to View",
|
|
3566
|
-
type: "button",
|
|
3567
|
-
group: "zoom",
|
|
3568
|
-
execute: () => {
|
|
3569
|
-
instance.fitToPage?.();
|
|
3570
|
-
}
|
|
3571
|
-
},
|
|
3572
|
-
{
|
|
3573
|
-
id: "rotate-cw",
|
|
3574
|
-
icon: "rotate-cw",
|
|
3575
|
-
label: "Rotate",
|
|
3576
|
-
type: "button",
|
|
3577
|
-
group: "view",
|
|
3578
|
-
execute: () => {
|
|
3579
|
-
instance.rotateCW?.();
|
|
3580
|
-
}
|
|
3581
|
-
},
|
|
3582
3562
|
{
|
|
3583
3563
|
id: "download",
|
|
3584
3564
|
icon: "download",
|
|
@@ -3639,12 +3619,11 @@ var ExcelPlugin = class {
|
|
|
3639
3619
|
container.appendChild(tabsArea);
|
|
3640
3620
|
ctx.container.appendChild(container);
|
|
3641
3621
|
let scale = 1;
|
|
3642
|
-
let rotation = 0;
|
|
3643
3622
|
let currentSheetIndex = 1;
|
|
3644
3623
|
let sheetNames = [];
|
|
3645
3624
|
let wb = null;
|
|
3646
3625
|
const applyTransform = () => {
|
|
3647
|
-
contentArea.style.transform = `scale(${scale})
|
|
3626
|
+
contentArea.style.transform = `scale(${scale})`;
|
|
3648
3627
|
contentArea.style.transformOrigin = "top left";
|
|
3649
3628
|
};
|
|
3650
3629
|
const calculateFitScale = () => {
|
|
@@ -3652,7 +3631,7 @@ var ExcelPlugin = class {
|
|
|
3652
3631
|
if (!table) return 1;
|
|
3653
3632
|
const availW = Math.max(280, container.clientWidth - 48);
|
|
3654
3633
|
const tW = table.offsetWidth || 800;
|
|
3655
|
-
return Math.max(0.
|
|
3634
|
+
return Math.max(0.4, Math.min(1, availW / tW));
|
|
3656
3635
|
};
|
|
3657
3636
|
try {
|
|
3658
3637
|
wb = XLSX.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
@@ -3707,7 +3686,16 @@ var ExcelPlugin = class {
|
|
|
3707
3686
|
}
|
|
3708
3687
|
});
|
|
3709
3688
|
ctx.emit("page-change", { page: currentSheetIndex, total: sheetNames.length });
|
|
3689
|
+
requestAnimationFrame(() => {
|
|
3690
|
+
scale = calculateFitScale();
|
|
3691
|
+
applyTransform();
|
|
3692
|
+
});
|
|
3710
3693
|
};
|
|
3694
|
+
const ro = new ResizeObserver(() => {
|
|
3695
|
+
scale = calculateFitScale();
|
|
3696
|
+
applyTransform();
|
|
3697
|
+
});
|
|
3698
|
+
ro.observe(container);
|
|
3711
3699
|
if (sheetNames.length > 0) {
|
|
3712
3700
|
sheetNames.forEach((name, idx) => {
|
|
3713
3701
|
const btn = document.createElement("button");
|
|
@@ -3734,6 +3722,7 @@ var ExcelPlugin = class {
|
|
|
3734
3722
|
`;
|
|
3735
3723
|
}
|
|
3736
3724
|
const cleanup = () => {
|
|
3725
|
+
ro.disconnect();
|
|
3737
3726
|
container.remove();
|
|
3738
3727
|
ctx.container.innerHTML = "";
|
|
3739
3728
|
};
|
|
@@ -3755,16 +3744,11 @@ var ExcelPlugin = class {
|
|
|
3755
3744
|
},
|
|
3756
3745
|
fitToPage: () => {
|
|
3757
3746
|
scale = calculateFitScale();
|
|
3758
|
-
rotation = 0;
|
|
3759
3747
|
applyTransform();
|
|
3760
3748
|
},
|
|
3761
3749
|
rotateCW: () => {
|
|
3762
|
-
rotation = (rotation + 90) % 360;
|
|
3763
|
-
applyTransform();
|
|
3764
3750
|
},
|
|
3765
3751
|
rotateCCW: () => {
|
|
3766
|
-
rotation = (rotation - 90 + 360) % 360;
|
|
3767
|
-
applyTransform();
|
|
3768
3752
|
},
|
|
3769
3753
|
goToPage: (page) => {
|
|
3770
3754
|
if (page > 0 && page <= sheetNames.length) {
|
|
@@ -3862,38 +3846,15 @@ var CsvPlugin = class {
|
|
|
3862
3846
|
return ext === ".csv" || ext === ".tsv" || mime === "text/csv" || mime === "text/tab-separated-values";
|
|
3863
3847
|
}
|
|
3864
3848
|
getToolbarActions(instance) {
|
|
3865
|
-
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3866
3849
|
const actions = [];
|
|
3867
3850
|
actions.push({
|
|
3868
3851
|
id: "thumbnails",
|
|
3869
3852
|
icon: "thumbnails",
|
|
3870
|
-
label: "
|
|
3853
|
+
label: "Sheet Thumbnails",
|
|
3871
3854
|
type: "button",
|
|
3872
3855
|
group: "navigation",
|
|
3873
3856
|
execute: () => instance.toggleThumbnails?.()
|
|
3874
3857
|
});
|
|
3875
|
-
if (totalPages > 1) {
|
|
3876
|
-
actions.push({
|
|
3877
|
-
id: "page-nav",
|
|
3878
|
-
icon: "",
|
|
3879
|
-
label: "Page Navigation",
|
|
3880
|
-
type: "page-nav",
|
|
3881
|
-
group: "navigation",
|
|
3882
|
-
value: instance.getCurrentPage?.() ?? 1,
|
|
3883
|
-
max: totalPages,
|
|
3884
|
-
execute: (action, page) => {
|
|
3885
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3886
|
-
const max = instance.getPageCount?.() ?? 1;
|
|
3887
|
-
if (action === "prev") {
|
|
3888
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3889
|
-
} else if (action === "next") {
|
|
3890
|
-
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3891
|
-
} else if (typeof page === "number") {
|
|
3892
|
-
instance.goToPage?.(page);
|
|
3893
|
-
}
|
|
3894
|
-
}
|
|
3895
|
-
});
|
|
3896
|
-
}
|
|
3897
3858
|
actions.push(
|
|
3898
3859
|
{
|
|
3899
3860
|
id: "zoom-out",
|
|
@@ -3915,16 +3876,6 @@ var CsvPlugin = class {
|
|
|
3915
3876
|
instance.zoomIn?.();
|
|
3916
3877
|
}
|
|
3917
3878
|
},
|
|
3918
|
-
{
|
|
3919
|
-
id: "fit-page",
|
|
3920
|
-
icon: "fit-page",
|
|
3921
|
-
label: "Fit to View",
|
|
3922
|
-
type: "button",
|
|
3923
|
-
group: "zoom",
|
|
3924
|
-
execute: () => {
|
|
3925
|
-
instance.fitToPage?.();
|
|
3926
|
-
}
|
|
3927
|
-
},
|
|
3928
3879
|
{
|
|
3929
3880
|
id: "download",
|
|
3930
3881
|
icon: "download",
|
|
@@ -3967,131 +3918,135 @@ var CsvPlugin = class {
|
|
|
3967
3918
|
container.style.overflow = "auto";
|
|
3968
3919
|
container.style.padding = "16px";
|
|
3969
3920
|
container.style.boxSizing = "border-box";
|
|
3970
|
-
|
|
3921
|
+
const tableWrapper = document.createElement("div");
|
|
3922
|
+
tableWrapper.style.transformOrigin = "top left";
|
|
3971
3923
|
const delimiter = ctx.metadata.extension === ".tsv" ? " " : ",";
|
|
3972
3924
|
const allLines = text.split(/\r?\n/).filter((r) => r.trim().length > 0);
|
|
3973
3925
|
const headerLine = allLines[0] || "";
|
|
3974
3926
|
const headerCells = headerLine.split(delimiter);
|
|
3975
3927
|
const dataLines = allLines.slice(1);
|
|
3976
|
-
const ROWS_PER_PAGE = 100;
|
|
3977
|
-
const totalPages = Math.max(1, Math.ceil(dataLines.length / ROWS_PER_PAGE));
|
|
3978
|
-
let currentPage = 1;
|
|
3979
3928
|
const table = document.createElement("table");
|
|
3980
3929
|
table.style.borderCollapse = "collapse";
|
|
3981
|
-
table.style.
|
|
3930
|
+
table.style.minWidth = "100%";
|
|
3982
3931
|
table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace';
|
|
3983
3932
|
table.style.fontSize = "13px";
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
const
|
|
4000
|
-
|
|
4001
|
-
const
|
|
4002
|
-
|
|
4003
|
-
const
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
td.style.border = "1px solid #d0d7de";
|
|
4010
|
-
td.style.padding = "6px 12px";
|
|
4011
|
-
td.style.whiteSpace = "nowrap";
|
|
4012
|
-
tr.appendChild(td);
|
|
4013
|
-
});
|
|
4014
|
-
table.appendChild(tr);
|
|
3933
|
+
table.style.background = "#ffffff";
|
|
3934
|
+
table.style.border = "1px solid #d0d7de";
|
|
3935
|
+
const headerTr = document.createElement("tr");
|
|
3936
|
+
headerCells.forEach((cell) => {
|
|
3937
|
+
const th = document.createElement("th");
|
|
3938
|
+
th.textContent = cell.trim();
|
|
3939
|
+
th.style.border = "1px solid #d0d7de";
|
|
3940
|
+
th.style.padding = "8px 12px";
|
|
3941
|
+
th.style.backgroundColor = "#f6f8fa";
|
|
3942
|
+
th.style.fontWeight = "600";
|
|
3943
|
+
th.style.whiteSpace = "nowrap";
|
|
3944
|
+
headerTr.appendChild(th);
|
|
3945
|
+
});
|
|
3946
|
+
table.appendChild(headerTr);
|
|
3947
|
+
dataLines.forEach((row, idx) => {
|
|
3948
|
+
const tr = document.createElement("tr");
|
|
3949
|
+
if (idx % 2 === 1) tr.style.backgroundColor = "#f8fafc";
|
|
3950
|
+
const cells = row.split(delimiter);
|
|
3951
|
+
cells.forEach((cell) => {
|
|
3952
|
+
const td = document.createElement("td");
|
|
3953
|
+
td.textContent = cell.trim();
|
|
3954
|
+
td.style.border = "1px solid #d0d7de";
|
|
3955
|
+
td.style.padding = "6px 12px";
|
|
3956
|
+
td.style.whiteSpace = "nowrap";
|
|
3957
|
+
tr.appendChild(td);
|
|
4015
3958
|
});
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
container.appendChild(table);
|
|
3959
|
+
table.appendChild(tr);
|
|
3960
|
+
});
|
|
3961
|
+
tableWrapper.appendChild(table);
|
|
3962
|
+
container.appendChild(tableWrapper);
|
|
4021
3963
|
ctx.container.appendChild(container);
|
|
4022
3964
|
let scale = 1;
|
|
3965
|
+
const calculateFitScale = () => {
|
|
3966
|
+
const availW = Math.max(280, container.clientWidth - 48);
|
|
3967
|
+
const tW = table.offsetWidth || 800;
|
|
3968
|
+
return Math.max(0.4, Math.min(1, availW / tW));
|
|
3969
|
+
};
|
|
4023
3970
|
const applyScale = () => {
|
|
4024
|
-
|
|
4025
|
-
container.style.transformOrigin = "top left";
|
|
3971
|
+
tableWrapper.style.transform = `scale(${scale})`;
|
|
4026
3972
|
};
|
|
3973
|
+
requestAnimationFrame(() => {
|
|
3974
|
+
scale = calculateFitScale();
|
|
3975
|
+
applyScale();
|
|
3976
|
+
});
|
|
3977
|
+
const ro = new ResizeObserver(() => {
|
|
3978
|
+
scale = calculateFitScale();
|
|
3979
|
+
applyScale();
|
|
3980
|
+
});
|
|
3981
|
+
ro.observe(container);
|
|
4027
3982
|
const cleanup = () => {
|
|
3983
|
+
ro.disconnect();
|
|
4028
3984
|
container.remove();
|
|
4029
3985
|
ctx.container.innerHTML = "";
|
|
4030
3986
|
};
|
|
4031
3987
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4032
3988
|
return {
|
|
4033
3989
|
destroy: cleanup,
|
|
4034
|
-
getPageCount: () =>
|
|
4035
|
-
getCurrentPage: () =>
|
|
4036
|
-
goToPage: (
|
|
3990
|
+
getPageCount: () => 1,
|
|
3991
|
+
getCurrentPage: () => 1,
|
|
3992
|
+
goToPage: () => {
|
|
3993
|
+
},
|
|
4037
3994
|
getThumbnails: () => {
|
|
4038
|
-
const
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
c.
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
c.fillText(val.trim().slice(0, 6), 8 + ci * colW, y + 9);
|
|
3995
|
+
const sheetName = ctx.metadata.name?.replace(/\.[^/.]+$/, "") || "Sheet1";
|
|
3996
|
+
return [{
|
|
3997
|
+
index: 0,
|
|
3998
|
+
label: sheetName,
|
|
3999
|
+
render: async (canvas) => {
|
|
4000
|
+
canvas.width = 140;
|
|
4001
|
+
canvas.height = 100;
|
|
4002
|
+
const c = canvas.getContext("2d");
|
|
4003
|
+
if (!c) return;
|
|
4004
|
+
c.fillStyle = "#ffffff";
|
|
4005
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4006
|
+
c.fillStyle = "#107c41";
|
|
4007
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
4008
|
+
c.fillStyle = "#ffffff";
|
|
4009
|
+
c.font = 'bold 8px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
4010
|
+
c.fillText(`\u{1F4CA} ${sheetName.slice(0, 16)}`, 6, 11);
|
|
4011
|
+
const startY = 17;
|
|
4012
|
+
const rowH = 13;
|
|
4013
|
+
const colW = 30;
|
|
4014
|
+
const cols = headerCells.slice(0, 4).map((h) => h.trim() || "Col");
|
|
4015
|
+
c.fillStyle = "#f1f5f9";
|
|
4016
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
4017
|
+
c.strokeStyle = "#cbd5e1";
|
|
4018
|
+
c.lineWidth = 0.8;
|
|
4019
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
4020
|
+
c.fillStyle = "#64748b";
|
|
4021
|
+
c.font = "bold 7px sans-serif";
|
|
4022
|
+
for (let ci = 0; ci < cols.length; ci++) {
|
|
4023
|
+
c.fillText(cols[ci].slice(0, 5), 14 + ci * colW, startY + 9);
|
|
4024
|
+
}
|
|
4025
|
+
for (let ri = 0; ri < Math.min(5, dataLines.length); ri++) {
|
|
4026
|
+
const y = startY + (ri + 1) * rowH;
|
|
4027
|
+
if (y > canvas.height - 2) break;
|
|
4028
|
+
c.fillStyle = "#f8fafc";
|
|
4029
|
+
c.fillRect(0, y, 12, rowH);
|
|
4030
|
+
c.fillStyle = "#94a3b8";
|
|
4031
|
+
c.font = "6px sans-serif";
|
|
4032
|
+
c.fillText(String(ri + 1), 3, y + 9);
|
|
4033
|
+
c.strokeStyle = "#e2e8f0";
|
|
4034
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
4035
|
+
const rowCells = dataLines[ri].split(delimiter);
|
|
4036
|
+
c.fillStyle = "#334155";
|
|
4037
|
+
c.font = "6px sans-serif";
|
|
4038
|
+
for (let ci = 0; ci < cols.length; ci++) {
|
|
4039
|
+
const val = (rowCells[ci] || "").trim();
|
|
4040
|
+
if (val) {
|
|
4041
|
+
c.fillText(val.slice(0, 6), 14 + ci * colW, y + 9);
|
|
4086
4042
|
}
|
|
4087
4043
|
}
|
|
4088
|
-
c.strokeStyle = "#cbd5e1";
|
|
4089
|
-
c.lineWidth = 1;
|
|
4090
|
-
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4091
4044
|
}
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4045
|
+
c.strokeStyle = "#cbd5e1";
|
|
4046
|
+
c.lineWidth = 1;
|
|
4047
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4048
|
+
}
|
|
4049
|
+
}];
|
|
4095
4050
|
},
|
|
4096
4051
|
zoomIn: () => {
|
|
4097
4052
|
scale += 0.1;
|
|
@@ -4107,11 +4062,13 @@ var CsvPlugin = class {
|
|
|
4107
4062
|
applyScale();
|
|
4108
4063
|
},
|
|
4109
4064
|
fitToPage: () => {
|
|
4110
|
-
|
|
4111
|
-
const tW = table.offsetWidth || 600;
|
|
4112
|
-
scale = Math.max(0.35, Math.min(1, availW / tW));
|
|
4065
|
+
scale = calculateFitScale();
|
|
4113
4066
|
applyScale();
|
|
4114
4067
|
},
|
|
4068
|
+
rotateCW: () => {
|
|
4069
|
+
},
|
|
4070
|
+
rotateCCW: () => {
|
|
4071
|
+
},
|
|
4115
4072
|
download: () => {
|
|
4116
4073
|
const blob = new Blob([ctx.buffer], { type: "text/csv" });
|
|
4117
4074
|
const url = URL.createObjectURL(blob);
|
|
@@ -4223,26 +4180,6 @@ var CodePlugin = class {
|
|
|
4223
4180
|
instance.zoomIn?.();
|
|
4224
4181
|
}
|
|
4225
4182
|
},
|
|
4226
|
-
{
|
|
4227
|
-
id: "fit-page",
|
|
4228
|
-
icon: "fit-page",
|
|
4229
|
-
label: "Fit to View",
|
|
4230
|
-
type: "button",
|
|
4231
|
-
group: "zoom",
|
|
4232
|
-
execute: () => {
|
|
4233
|
-
instance.fitToPage?.();
|
|
4234
|
-
}
|
|
4235
|
-
},
|
|
4236
|
-
{
|
|
4237
|
-
id: "rotate-cw",
|
|
4238
|
-
icon: "rotate-cw",
|
|
4239
|
-
label: "Rotate",
|
|
4240
|
-
type: "button",
|
|
4241
|
-
group: "view",
|
|
4242
|
-
execute: () => {
|
|
4243
|
-
instance.rotateCW?.();
|
|
4244
|
-
}
|
|
4245
|
-
},
|
|
4246
4183
|
{
|
|
4247
4184
|
id: "copy",
|
|
4248
4185
|
icon: "copy",
|
|
@@ -5386,6 +5323,148 @@ var ThreeDPlugin = class {
|
|
|
5386
5323
|
function threeDPlugin() {
|
|
5387
5324
|
return new ThreeDPlugin();
|
|
5388
5325
|
}
|
|
5326
|
+
function cleanRtfText(raw) {
|
|
5327
|
+
return raw.replace(/\\bin\d+\s/g, "").replace(/{\\\*[^}]+}/g, "").replace(/\\u(-?\d+)\??/g, (_, code) => {
|
|
5328
|
+
let num = parseInt(code, 10);
|
|
5329
|
+
if (num < 0) num += 65536;
|
|
5330
|
+
return String.fromCharCode(num);
|
|
5331
|
+
}).replace(/\\'([0-9a-fA-F]{2})/g, (_, hex) => {
|
|
5332
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
5333
|
+
}).replace(/\\tab\b/g, " ").replace(/\\emdash\b/g, "\u2014").replace(/\\endash\b/g, "\u2013").replace(/\\bullet\b/g, "\u2022").replace(/\\lquote\b/g, "\u2018").replace(/\\rquote\b/g, "\u2019").replace(/\\ldblquote\b/g, "\u201C").replace(/\\rdblquote\b/g, "\u201D").replace(/\\\w+(?:-?\d+)?\s?/g, " ").replace(/[{}\r\n]/g, " ").replace(/\s+/g, " ").trim();
|
|
5334
|
+
}
|
|
5335
|
+
function parseRtfTables(rtfText) {
|
|
5336
|
+
const rowSegments = rtfText.split(/\\row\b/);
|
|
5337
|
+
if (rowSegments.length <= 1) return [];
|
|
5338
|
+
const rawTables = [];
|
|
5339
|
+
let currentTable = null;
|
|
5340
|
+
let charOffset = 0;
|
|
5341
|
+
for (let i = 0; i < rowSegments.length - 1; i++) {
|
|
5342
|
+
const segment = rowSegments[i];
|
|
5343
|
+
const segmentStart = charOffset;
|
|
5344
|
+
const segmentEnd = charOffset + segment.length + 4;
|
|
5345
|
+
const cellParts = segment.split(/\\cell\b/);
|
|
5346
|
+
if (cellParts.length > 1) {
|
|
5347
|
+
const cellxMatches = [...segment.matchAll(/\\cellx(\d+)/g)].map((m) => parseInt(m[1], 10));
|
|
5348
|
+
let cellWidths = [];
|
|
5349
|
+
if (cellxMatches.length > 0) {
|
|
5350
|
+
let seq = [cellxMatches[0]];
|
|
5351
|
+
for (let k = 1; k < cellxMatches.length; k++) {
|
|
5352
|
+
if (cellxMatches[k] > cellxMatches[k - 1]) seq.push(cellxMatches[k]);
|
|
5353
|
+
else break;
|
|
5354
|
+
}
|
|
5355
|
+
let prev = 0;
|
|
5356
|
+
cellWidths = seq.map((x) => {
|
|
5357
|
+
const w = x - prev;
|
|
5358
|
+
prev = x;
|
|
5359
|
+
return w;
|
|
5360
|
+
});
|
|
5361
|
+
}
|
|
5362
|
+
const cells = [];
|
|
5363
|
+
for (let c = 0; c < cellParts.length - 1; c++) {
|
|
5364
|
+
let rawCell = cellParts[c];
|
|
5365
|
+
if (c === 0) {
|
|
5366
|
+
const lastTrowd = rawCell.lastIndexOf("\\trowd");
|
|
5367
|
+
if (lastTrowd !== -1) rawCell = rawCell.slice(lastTrowd);
|
|
5368
|
+
}
|
|
5369
|
+
cells.push(cleanRtfText(rawCell));
|
|
5370
|
+
}
|
|
5371
|
+
const isNewTable = !currentTable || segmentStart - currentTable.lastEnd > 2500;
|
|
5372
|
+
if (isNewTable) {
|
|
5373
|
+
const prevTextSlice = rtfText.slice(Math.max(0, segmentStart - 4e3), segmentStart);
|
|
5374
|
+
const cleanPrev = cleanRtfText(prevTextSlice);
|
|
5375
|
+
const anchorBefore = cleanPrev.slice(-80).trim();
|
|
5376
|
+
currentTable = {
|
|
5377
|
+
id: `RTF_TABLE_${rawTables.length}`,
|
|
5378
|
+
startPos: segmentStart,
|
|
5379
|
+
lastEnd: segmentEnd,
|
|
5380
|
+
rows: [],
|
|
5381
|
+
columnWidths: cellWidths,
|
|
5382
|
+
anchorBefore,
|
|
5383
|
+
anchorAfter: ""
|
|
5384
|
+
};
|
|
5385
|
+
rawTables.push(currentTable);
|
|
5386
|
+
}
|
|
5387
|
+
if (currentTable) {
|
|
5388
|
+
currentTable.rows.push({
|
|
5389
|
+
cells,
|
|
5390
|
+
widths: cellWidths.length === cells.length ? cellWidths : currentTable.columnWidths
|
|
5391
|
+
});
|
|
5392
|
+
currentTable.lastEnd = segmentEnd;
|
|
5393
|
+
}
|
|
5394
|
+
}
|
|
5395
|
+
charOffset += segment.length + 4;
|
|
5396
|
+
}
|
|
5397
|
+
rawTables.forEach((tbl) => {
|
|
5398
|
+
const afterSlice = rtfText.slice(tbl.lastEnd, Math.min(rtfText.length, tbl.lastEnd + 2e3));
|
|
5399
|
+
const cleanAfter = cleanRtfText(afterSlice);
|
|
5400
|
+
tbl.anchorAfter = cleanAfter.slice(0, 80).trim();
|
|
5401
|
+
});
|
|
5402
|
+
return rawTables.map((tbl) => {
|
|
5403
|
+
const totalW = (tbl.columnWidths || []).reduce((a, b) => a + b, 0);
|
|
5404
|
+
const colPercents = totalW > 0 ? tbl.columnWidths.map((w) => Math.round(w / totalW * 100)) : [];
|
|
5405
|
+
return {
|
|
5406
|
+
id: tbl.id,
|
|
5407
|
+
rows: tbl.rows.map((r) => r.cells),
|
|
5408
|
+
colPercents,
|
|
5409
|
+
anchorBefore: tbl.anchorBefore,
|
|
5410
|
+
anchorAfter: tbl.anchorAfter
|
|
5411
|
+
};
|
|
5412
|
+
});
|
|
5413
|
+
}
|
|
5414
|
+
function renderRtfTableElement(table) {
|
|
5415
|
+
const tableEl = document.createElement("table");
|
|
5416
|
+
tableEl.className = "fp-rtf-table";
|
|
5417
|
+
tableEl.style.width = "100%";
|
|
5418
|
+
tableEl.style.borderCollapse = "collapse";
|
|
5419
|
+
tableEl.style.margin = "16px 0 20px";
|
|
5420
|
+
tableEl.style.fontSize = "10pt";
|
|
5421
|
+
tableEl.style.lineHeight = "1.5";
|
|
5422
|
+
tableEl.style.border = "1px solid #cbd5e1";
|
|
5423
|
+
tableEl.style.borderRadius = "4px";
|
|
5424
|
+
tableEl.style.boxSizing = "border-box";
|
|
5425
|
+
tableEl.style.backgroundColor = "#ffffff";
|
|
5426
|
+
const thead = document.createElement("thead");
|
|
5427
|
+
const tbody = document.createElement("tbody");
|
|
5428
|
+
table.rows.forEach((rowCells, rIdx) => {
|
|
5429
|
+
const tr = document.createElement("tr");
|
|
5430
|
+
const isHeader = rIdx === 0;
|
|
5431
|
+
if (isHeader) {
|
|
5432
|
+
tr.style.backgroundColor = "#f8fafc";
|
|
5433
|
+
tr.style.borderBottom = "2px solid #cbd5e1";
|
|
5434
|
+
} else {
|
|
5435
|
+
tr.style.borderBottom = "1px solid #e2e8f0";
|
|
5436
|
+
if (rIdx % 2 === 0) {
|
|
5437
|
+
tr.style.backgroundColor = "#fcfdfe";
|
|
5438
|
+
}
|
|
5439
|
+
}
|
|
5440
|
+
rowCells.forEach((cellText, cIdx) => {
|
|
5441
|
+
const cellEl = document.createElement(isHeader ? "th" : "td");
|
|
5442
|
+
cellEl.style.padding = "8px 12px";
|
|
5443
|
+
cellEl.style.border = "1px solid #cbd5e1";
|
|
5444
|
+
cellEl.style.verticalAlign = "top";
|
|
5445
|
+
cellEl.style.color = isHeader ? "#0f172a" : "#1e293b";
|
|
5446
|
+
cellEl.style.fontWeight = isHeader ? "600" : "normal";
|
|
5447
|
+
if (table.colPercents && table.colPercents[cIdx]) {
|
|
5448
|
+
cellEl.style.width = `${table.colPercents[cIdx]}%`;
|
|
5449
|
+
}
|
|
5450
|
+
if (/^\d+$/.test(cellText.trim()) || cellText.trim() === "#") {
|
|
5451
|
+
cellEl.style.textAlign = "center";
|
|
5452
|
+
} else {
|
|
5453
|
+
cellEl.style.textAlign = "left";
|
|
5454
|
+
}
|
|
5455
|
+
cellEl.textContent = cellText;
|
|
5456
|
+
tr.appendChild(cellEl);
|
|
5457
|
+
});
|
|
5458
|
+
if (isHeader) {
|
|
5459
|
+
thead.appendChild(tr);
|
|
5460
|
+
} else {
|
|
5461
|
+
tbody.appendChild(tr);
|
|
5462
|
+
}
|
|
5463
|
+
});
|
|
5464
|
+
tableEl.appendChild(thead);
|
|
5465
|
+
tableEl.appendChild(tbody);
|
|
5466
|
+
return tableEl;
|
|
5467
|
+
}
|
|
5389
5468
|
var RtfPlugin = class {
|
|
5390
5469
|
id = "rtf";
|
|
5391
5470
|
name = "Rich Text Format (RTF)";
|
|
@@ -5421,6 +5500,14 @@ var RtfPlugin = class {
|
|
|
5421
5500
|
}
|
|
5422
5501
|
});
|
|
5423
5502
|
actions.push(
|
|
5503
|
+
{
|
|
5504
|
+
id: "thumbnails",
|
|
5505
|
+
icon: "thumbnails",
|
|
5506
|
+
label: "Thumbnails",
|
|
5507
|
+
type: "button",
|
|
5508
|
+
group: "view",
|
|
5509
|
+
execute: () => instance.toggleThumbnails?.()
|
|
5510
|
+
},
|
|
5424
5511
|
{
|
|
5425
5512
|
id: "zoom-out",
|
|
5426
5513
|
icon: "zoom-out",
|
|
@@ -5548,6 +5635,8 @@ var RtfPlugin = class {
|
|
|
5548
5635
|
if (typeof RTFJS.loggingEnabled === "function") {
|
|
5549
5636
|
RTFJS.loggingEnabled(false);
|
|
5550
5637
|
}
|
|
5638
|
+
const rawText = new TextDecoder("latin1").decode(ctx.buffer);
|
|
5639
|
+
const tables = parseRtfTables(rawText);
|
|
5551
5640
|
const doc = new RTFJS.Document(ctx.buffer, {});
|
|
5552
5641
|
const htmlElements = await doc.render();
|
|
5553
5642
|
const contentNodes = [];
|
|
@@ -5562,6 +5651,20 @@ var RtfPlugin = class {
|
|
|
5562
5651
|
if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
|
|
5563
5652
|
extractBlocks(Array.from(item.children));
|
|
5564
5653
|
} else {
|
|
5654
|
+
const svgs = item.querySelectorAll("svg, img");
|
|
5655
|
+
svgs.forEach((s) => {
|
|
5656
|
+
const el = s;
|
|
5657
|
+
el.style.maxWidth = "100%";
|
|
5658
|
+
el.style.maxHeight = "360px";
|
|
5659
|
+
el.style.display = "block";
|
|
5660
|
+
el.style.margin = "12px auto";
|
|
5661
|
+
if (s.tagName.toLowerCase() === "svg") {
|
|
5662
|
+
s.removeAttribute("width");
|
|
5663
|
+
s.removeAttribute("height");
|
|
5664
|
+
el.style.width = "100%";
|
|
5665
|
+
el.style.maxHeight = "360px";
|
|
5666
|
+
}
|
|
5667
|
+
});
|
|
5565
5668
|
if (tag === "p" || tag === "div") {
|
|
5566
5669
|
item.style.display = "block";
|
|
5567
5670
|
item.style.marginBottom = "12px";
|
|
@@ -5572,14 +5675,46 @@ var RtfPlugin = class {
|
|
|
5572
5675
|
}
|
|
5573
5676
|
};
|
|
5574
5677
|
extractBlocks(htmlElements);
|
|
5678
|
+
tables.forEach((table) => {
|
|
5679
|
+
const tableEl = renderRtfTableElement(table);
|
|
5680
|
+
let inserted = false;
|
|
5681
|
+
if (table.anchorBefore && table.anchorBefore.length > 10) {
|
|
5682
|
+
const keyword = table.anchorBefore.slice(-35).trim();
|
|
5683
|
+
for (let i = 0; i < contentNodes.length; i++) {
|
|
5684
|
+
if (contentNodes[i].textContent?.includes(keyword)) {
|
|
5685
|
+
contentNodes.splice(i + 1, 0, tableEl);
|
|
5686
|
+
inserted = true;
|
|
5687
|
+
break;
|
|
5688
|
+
}
|
|
5689
|
+
}
|
|
5690
|
+
}
|
|
5691
|
+
if (!inserted && table.anchorAfter && table.anchorAfter.length > 10) {
|
|
5692
|
+
const keyword = table.anchorAfter.slice(0, 35).trim();
|
|
5693
|
+
for (let i = 0; i < contentNodes.length; i++) {
|
|
5694
|
+
if (contentNodes[i].textContent?.includes(keyword)) {
|
|
5695
|
+
contentNodes.splice(i, 0, tableEl);
|
|
5696
|
+
inserted = true;
|
|
5697
|
+
break;
|
|
5698
|
+
}
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
if (!inserted) {
|
|
5702
|
+
if (contentNodes.length > 2) {
|
|
5703
|
+
contentNodes.splice(2, 0, tableEl);
|
|
5704
|
+
} else {
|
|
5705
|
+
contentNodes.push(tableEl);
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
});
|
|
5575
5709
|
wrapper.innerHTML = "";
|
|
5576
5710
|
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
5577
5711
|
const childHeights = contentNodes.map((c) => {
|
|
5578
5712
|
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
5579
5713
|
const offH = c.offsetHeight || 0;
|
|
5714
|
+
const realH = Math.max(rectH, offH);
|
|
5715
|
+
if (realH > 0) return realH;
|
|
5580
5716
|
const textLen = c.textContent?.trim().length || 0;
|
|
5581
|
-
|
|
5582
|
-
return Math.max(rectH, offH, estH);
|
|
5717
|
+
return Math.max(24, Math.ceil(textLen / 95) * 22 + 12);
|
|
5583
5718
|
});
|
|
5584
5719
|
wrapper.innerHTML = "";
|
|
5585
5720
|
const createRtfCard = () => {
|
|
@@ -5588,7 +5723,7 @@ var RtfPlugin = class {
|
|
|
5588
5723
|
card.style.backgroundColor = "#ffffff";
|
|
5589
5724
|
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
5590
5725
|
card.style.borderRadius = "4px";
|
|
5591
|
-
card.style.padding = "
|
|
5726
|
+
card.style.padding = "64px 56px";
|
|
5592
5727
|
card.style.width = "816px";
|
|
5593
5728
|
card.style.minHeight = "1056px";
|
|
5594
5729
|
card.style.boxSizing = "border-box";
|
|
@@ -5602,22 +5737,35 @@ var RtfPlugin = class {
|
|
|
5602
5737
|
wrapper.appendChild(curCard);
|
|
5603
5738
|
pageElements = [curCard];
|
|
5604
5739
|
let curH = 0;
|
|
5605
|
-
const maxH =
|
|
5740
|
+
const maxH = 928;
|
|
5606
5741
|
for (let i = 0; i < contentNodes.length; i++) {
|
|
5607
5742
|
const child = contentNodes[i];
|
|
5608
5743
|
const chH = childHeights[i];
|
|
5609
|
-
|
|
5610
|
-
curH
|
|
5611
|
-
|
|
5744
|
+
const isChildEmpty = (child.textContent || "").trim().length === 0 && !child.querySelector("table, img, svg, canvas");
|
|
5745
|
+
if (curH === 0 && isChildEmpty) {
|
|
5746
|
+
continue;
|
|
5747
|
+
}
|
|
5748
|
+
if (curH + chH > maxH && curCard.childNodes.length > 0) {
|
|
5612
5749
|
curCard = createRtfCard();
|
|
5613
5750
|
wrapper.appendChild(curCard);
|
|
5614
5751
|
pageElements.push(curCard);
|
|
5615
5752
|
curH = 0;
|
|
5616
5753
|
}
|
|
5754
|
+
curCard.appendChild(child);
|
|
5755
|
+
curH += chH;
|
|
5756
|
+
}
|
|
5757
|
+
pageElements = pageElements.filter((card) => {
|
|
5758
|
+
const hasText = (card.textContent || "").trim().length > 0;
|
|
5759
|
+
const hasMedia = card.querySelector("table, img, svg, canvas") !== null;
|
|
5760
|
+
return hasText || hasMedia;
|
|
5761
|
+
});
|
|
5762
|
+
if (pageElements.length === 0) {
|
|
5763
|
+
pageElements = [curCard];
|
|
5617
5764
|
}
|
|
5618
5765
|
} catch (err) {
|
|
5619
5766
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
5620
5767
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
5768
|
+
const tables = parseRtfTables(text);
|
|
5621
5769
|
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
5622
5770
|
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
5623
5771
|
}).filter((p) => p.length > 0);
|
|
@@ -5628,7 +5776,7 @@ var RtfPlugin = class {
|
|
|
5628
5776
|
pageCard.style.backgroundColor = "#ffffff";
|
|
5629
5777
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
5630
5778
|
pageCard.style.borderRadius = "4px";
|
|
5631
|
-
pageCard.style.padding = "
|
|
5779
|
+
pageCard.style.padding = "64px 56px";
|
|
5632
5780
|
pageCard.style.width = "816px";
|
|
5633
5781
|
pageCard.style.minHeight = "1056px";
|
|
5634
5782
|
pageCard.style.boxSizing = "border-box";
|
|
@@ -5639,6 +5787,9 @@ var RtfPlugin = class {
|
|
|
5639
5787
|
pageCard.style.whiteSpace = "pre-wrap";
|
|
5640
5788
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5641
5789
|
pageCard.textContent = pages[i];
|
|
5790
|
+
if (i === 1 && tables.length > 0) {
|
|
5791
|
+
tables.forEach((tbl) => pageCard.appendChild(renderRtfTableElement(tbl)));
|
|
5792
|
+
}
|
|
5642
5793
|
wrapper.appendChild(pageCard);
|
|
5643
5794
|
pageElements.push(pageCard);
|
|
5644
5795
|
}
|
|
@@ -5669,6 +5820,32 @@ var RtfPlugin = class {
|
|
|
5669
5820
|
getPageCount: () => totalPages,
|
|
5670
5821
|
getCurrentPage: () => currentPage,
|
|
5671
5822
|
goToPage: (page) => showPage(page),
|
|
5823
|
+
getThumbnails: async () => {
|
|
5824
|
+
const items = [];
|
|
5825
|
+
for (let idx = 0; idx < totalPages; idx++) {
|
|
5826
|
+
const pageIdx = idx;
|
|
5827
|
+
items.push({
|
|
5828
|
+
index: pageIdx,
|
|
5829
|
+
label: `Page ${pageIdx + 1}`,
|
|
5830
|
+
render: async (canvas) => {
|
|
5831
|
+
const ctx2d = canvas.getContext("2d");
|
|
5832
|
+
if (!ctx2d) return;
|
|
5833
|
+
canvas.width = 140;
|
|
5834
|
+
canvas.height = 180;
|
|
5835
|
+
ctx2d.fillStyle = "#ffffff";
|
|
5836
|
+
ctx2d.fillRect(0, 0, 140, 180);
|
|
5837
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
5838
|
+
ctx2d.lineWidth = 1;
|
|
5839
|
+
ctx2d.strokeRect(0.5, 0.5, 139, 179);
|
|
5840
|
+
ctx2d.fillStyle = "#334155";
|
|
5841
|
+
ctx2d.font = 'bold 11px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
5842
|
+
ctx2d.textAlign = "center";
|
|
5843
|
+
ctx2d.fillText(`Page ${pageIdx + 1}`, 70, 95);
|
|
5844
|
+
}
|
|
5845
|
+
});
|
|
5846
|
+
}
|
|
5847
|
+
return items;
|
|
5848
|
+
},
|
|
5672
5849
|
zoomIn: () => {
|
|
5673
5850
|
isUserZoomed = true;
|
|
5674
5851
|
scale += 0.15;
|