oasis-editor 0.0.40 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{OasisEditorApp-rHCQJW6I.js → OasisEditorApp-Cx-3bgIC.js} +300 -253
- package/dist/{index-XgdC48U9.js → index-CTh8mekn.js} +70 -70
- package/dist/oasis-editor.js +14 -14
- package/dist/oasis-editor.umd.cjs +4 -4
- package/dist/ui/app/createEditorLayoutOptionsController.d.ts +18 -0
- package/dist/ui/app/createEditorTableContextMenuActions.d.ts +20 -0
- package/dist/ui/app/useEditorContextMenuClipboard.d.ts +23 -17
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { n as normalizeSelection, g as getParagraphs, c as createEditorParagraphFromRuns, a as getParagraphLength, b as createEditorRun, d as getDocumentSections, e as createEditorStyledRun, f as getParagraphText, h as getActiveZone, i as getActiveSectionIndex, p as positionToParagraphOffset, j as paragraphOffsetToPosition, k as clampPosition, l as findParagraphIndex, m as createCollapsedSelection, o as isSelectionCollapsed, q as createEditorParagraph, r as getBlockParagraphs, s as findParagraphTableLocation, t as buildTableCellLayout, u as createEditorTableCell, v as createEditorTableRow, w as createEditorTable, x as underlineStyleToCssDecorationStyle, y as resolveImageSrc, z as createEditorFootnote, A as createFootnoteReferenceRun, B as renumberFootnotes, C as iterateFootnoteReferenceRuns, D as getFootnoteDisplayMarker, E as createSignal, F as createEffect, G as onCleanup, H as buildCanvasLayoutSnapshot, I as on, J as onMount, K as debounce, L as unwrap, M as getDocumentParagraphs, N as getDocumentSectionsCanonical, O as createEditorDocument, P as getPageContentWidth, Q as getDocumentPageSettings, R as getTableCellContentWidthForParagraph, S as resolveResizedDimensions, T as resolveTextBoxRenderHeight, U as resolveEffectiveParagraphStyle, V as resolveEffectiveTextStyleForParagraph, W as iterateEndnoteReferenceRuns, X as JSZip, Y as imageContentTypeDefaults, Z as imageExtensionFromMime, _ as pxToPt$1, $ as resolveFloatingObjectRect, a0 as getTextBoxFloatingGeometry, a1 as getPresetPathSegments, a2 as projectBlocksLayout, a3 as buildListLabels, a4 as textStyleToFontSizePt, a5 as PX_PER_POINT, a6 as DEFAULT_FONT_SIZE_PX, a7 as isDoubleUnderlineStyle, a8 as isWavyUnderlineStyle, a9 as underlineStyleLineWidthPx, aa as underlineStyleDashArray, ab as resolveListLabel, ac as getListLabelInset, ad as getAlignedListLabelInset, ae as getParagraphBorderInsets, af as buildSegmentTable, ag as buildCanvasTableLayout, ah as normalizeFamily, ai as ROBOTO_FONT_FILES, aj as loadFontAsset, ak as OFFICE_COMPAT_FONT_FAMILIES, al as buildSfnt, am as defaultFontDecoderRegistry, an as SfntFontProgram, ao as collectPdfFontFamilies, ap as projectDocumentLayout, aq as getPageHeaderZoneTop, ar as getPageBodyTop, as as getPageColumnRects, at as findFootnoteReference, au as FOOTNOTE_MARKER_GUTTER_PX, av as resolveImporterForFile, aw as createEditorStateFromDocument, ax as getDocumentParagraphsCanonical, ay as getToolbarStyleState, az as STANDARD_FONT_SIZES_PT, aA as fontSizePxToPt, aB as probeLocalFontFamilies, aC as createInitialEditorState, aD as parseFontSizePtToPx, aE as formatFontSizePt, aF as listKindForTag, aG as isParagraphTag, aH as collectInlineRuns, aI as parseParagraphStyle, aJ as
|
|
4
|
+
import { n as normalizeSelection, g as getParagraphs, c as createEditorParagraphFromRuns, a as getParagraphLength, b as createEditorRun, d as getDocumentSections, e as createEditorStyledRun, f as getParagraphText, h as getActiveZone, i as getActiveSectionIndex, p as positionToParagraphOffset, j as paragraphOffsetToPosition, k as clampPosition, l as findParagraphIndex, m as createCollapsedSelection, o as isSelectionCollapsed, q as createEditorParagraph, r as getBlockParagraphs, s as findParagraphTableLocation, t as buildTableCellLayout, u as createEditorTableCell, v as createEditorTableRow, w as createEditorTable, x as underlineStyleToCssDecorationStyle, y as resolveImageSrc, z as createEditorFootnote, A as createFootnoteReferenceRun, B as renumberFootnotes, C as iterateFootnoteReferenceRuns, D as getFootnoteDisplayMarker, E as createSignal, F as createEffect, G as onCleanup, H as buildCanvasLayoutSnapshot, I as on, J as onMount, K as debounce, L as unwrap, M as getDocumentParagraphs, N as getDocumentSectionsCanonical, O as createEditorDocument, P as getPageContentWidth, Q as getDocumentPageSettings, R as getTableCellContentWidthForParagraph, S as resolveResizedDimensions, T as resolveTextBoxRenderHeight, U as resolveEffectiveParagraphStyle, V as resolveEffectiveTextStyleForParagraph, W as iterateEndnoteReferenceRuns, X as JSZip, Y as imageContentTypeDefaults, Z as imageExtensionFromMime, _ as pxToPt$1, $ as resolveFloatingObjectRect, a0 as getTextBoxFloatingGeometry, a1 as getPresetPathSegments, a2 as projectBlocksLayout, a3 as buildListLabels, a4 as textStyleToFontSizePt, a5 as PX_PER_POINT, a6 as DEFAULT_FONT_SIZE_PX, a7 as isDoubleUnderlineStyle, a8 as isWavyUnderlineStyle, a9 as underlineStyleLineWidthPx, aa as underlineStyleDashArray, ab as resolveListLabel, ac as getListLabelInset, ad as getAlignedListLabelInset, ae as getParagraphBorderInsets, af as buildSegmentTable, ag as buildCanvasTableLayout, ah as normalizeFamily, ai as ROBOTO_FONT_FILES, aj as loadFontAsset, ak as OFFICE_COMPAT_FONT_FAMILIES, al as buildSfnt, am as defaultFontDecoderRegistry, an as SfntFontProgram, ao as collectPdfFontFamilies, ap as projectDocumentLayout, aq as getPageHeaderZoneTop, ar as getPageBodyTop, as as getPageColumnRects, at as findFootnoteReference, au as FOOTNOTE_MARKER_GUTTER_PX, av as resolveImporterForFile, aw as createEditorStateFromDocument, ax as getDocumentParagraphsCanonical, ay as getToolbarStyleState, az as STANDARD_FONT_SIZES_PT, aA as fontSizePxToPt, aB as probeLocalFontFamilies, aC as createInitialEditorState, aD as parseFontSizePtToPx, aE as formatFontSizePt, aF as listKindForTag, aG as isParagraphTag, aH as collectInlineRuns, aI as parseParagraphStyle, aJ as getCachedCanvasImage, aK as getHeadingLevel, aL as preciseFontModeVersion, aM as isPreciseFontModeEnabled, aN as togglePreciseFontMode, aO as nextFontSizePt, aP as previousFontSizePt, aQ as fontSizePtToPx, aR as createDefaultToolbarPreset, aS as MenuRegistry, aT as createToolbarRegistry, aU as Editor, aV as resolveCommandRef, aW as commandRefName, aX as InlineShell, aY as BalloonShell, aZ as DocumentShell, a_ as createMemo, a$ as getCaretRectFromSnapshot, b0 as getParagraphRectFromSnapshot, b1 as createComponent, b2 as CaretOverlay, b3 as Show, b4 as createRenderEffect, b5 as style, b6 as setAttribute, b7 as setStyleProperty, b8 as memo, b9 as template, ba as useI18n, bb as insert, bc as use, bd as addEventListener, be as Dialog, bf as delegateEvents, bg as className, bh as For, bi as UNDERLINE_STYLE_OPTIONS, bj as Tabs, bk as measureParagraphMinContentWidthPx, bl as getEditableBlocksForZone, bm as findParagraphLocation, bn as createSectionBoundaryParagraph, bo as normalizePageSettings, bp as DEFAULT_EDITOR_PAGE_SETTINGS, bq as markStart, br as markEnd, bs as getParagraphEntries, bt as getParagraphById, bu as PluginUiHost, bv as OasisEditorEditor, bw as perfTimer, bx as OasisBrandMark, by as setPreciseFontPreference, bz as setWelcomeSeen, bA as enablePreciseFontMode, bB as createOasisEditorClient, bC as createEditorZoom, bD as startLongTaskObserver, bE as installGlobalReport, bF as applyStoredPreciseFontPreference, bG as getWelcomeSeen, bH as isLocalFontAccessSupported, bI as EDITOR_SCROLL_PADDING_PX, bJ as Toolbar, bK as OasisEditorLoading, bL as I18nProvider, bM as createEditorLogger, bN as createTranslator, bO as registerDomStatsSurface } from "./index-CTh8mekn.js";
|
|
5
5
|
function getSelectedObjectRun(state, predicate) {
|
|
6
6
|
const normalized = normalizeSelection(state);
|
|
7
7
|
if (normalized.isCollapsed || normalized.startIndex !== normalized.endIndex || normalized.endParagraphOffset - normalized.startParagraphOffset !== 1) {
|
|
@@ -3840,186 +3840,6 @@ function insertFootnote(state) {
|
|
|
3840
3840
|
activeFootnoteId: footnote.id
|
|
3841
3841
|
};
|
|
3842
3842
|
}
|
|
3843
|
-
const RECTANGLE = [
|
|
3844
|
-
{ x: 0, y: 0 },
|
|
3845
|
-
{ x: 1, y: 0 },
|
|
3846
|
-
{ x: 1, y: 1 },
|
|
3847
|
-
{ x: 0, y: 1 }
|
|
3848
|
-
];
|
|
3849
|
-
const MAX_SIDE = 256;
|
|
3850
|
-
const ALPHA_THRESHOLD = 128;
|
|
3851
|
-
const OPAQUE_RATIO = 0.985;
|
|
3852
|
-
const MAX_POINTS = 40;
|
|
3853
|
-
const contourCache = /* @__PURE__ */ new Map();
|
|
3854
|
-
function rectangle() {
|
|
3855
|
-
return RECTANGLE.map((point) => ({ ...point }));
|
|
3856
|
-
}
|
|
3857
|
-
const DIRS = [
|
|
3858
|
-
[0, -1],
|
|
3859
|
-
[1, -1],
|
|
3860
|
-
[1, 0],
|
|
3861
|
-
[1, 1],
|
|
3862
|
-
[0, 1],
|
|
3863
|
-
[-1, 1],
|
|
3864
|
-
[-1, 0],
|
|
3865
|
-
[-1, -1]
|
|
3866
|
-
];
|
|
3867
|
-
function buildAlphaMask(img) {
|
|
3868
|
-
const naturalW = img.naturalWidth || img.width;
|
|
3869
|
-
const naturalH = img.naturalHeight || img.height;
|
|
3870
|
-
if (!naturalW || !naturalH) {
|
|
3871
|
-
return null;
|
|
3872
|
-
}
|
|
3873
|
-
const scale = Math.min(1, MAX_SIDE / Math.max(naturalW, naturalH));
|
|
3874
|
-
const width = Math.max(1, Math.round(naturalW * scale));
|
|
3875
|
-
const height = Math.max(1, Math.round(naturalH * scale));
|
|
3876
|
-
const canvas = document.createElement("canvas");
|
|
3877
|
-
canvas.width = width;
|
|
3878
|
-
canvas.height = height;
|
|
3879
|
-
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
3880
|
-
if (!ctx) {
|
|
3881
|
-
return null;
|
|
3882
|
-
}
|
|
3883
|
-
ctx.drawImage(img, 0, 0, width, height);
|
|
3884
|
-
let pixels;
|
|
3885
|
-
try {
|
|
3886
|
-
pixels = ctx.getImageData(0, 0, width, height).data;
|
|
3887
|
-
} catch {
|
|
3888
|
-
return null;
|
|
3889
|
-
}
|
|
3890
|
-
const mask = new Uint8Array(width * height);
|
|
3891
|
-
let foreground = 0;
|
|
3892
|
-
for (let i = 0; i < mask.length; i += 1) {
|
|
3893
|
-
if (pixels[i * 4 + 3] >= ALPHA_THRESHOLD) {
|
|
3894
|
-
mask[i] = 1;
|
|
3895
|
-
foreground += 1;
|
|
3896
|
-
}
|
|
3897
|
-
}
|
|
3898
|
-
return { mask, width, height, foreground };
|
|
3899
|
-
}
|
|
3900
|
-
function traceBoundary(mask, width, height) {
|
|
3901
|
-
const at = (x, y) => x >= 0 && x < width && y >= 0 && y < height && mask[y * width + x] === 1;
|
|
3902
|
-
let startX = -1;
|
|
3903
|
-
let startY = -1;
|
|
3904
|
-
for (let y = 0; y < height && startY < 0; y += 1) {
|
|
3905
|
-
for (let x = 0; x < width; x += 1) {
|
|
3906
|
-
if (mask[y * width + x] === 1) {
|
|
3907
|
-
startX = x;
|
|
3908
|
-
startY = y;
|
|
3909
|
-
break;
|
|
3910
|
-
}
|
|
3911
|
-
}
|
|
3912
|
-
}
|
|
3913
|
-
if (startX < 0) {
|
|
3914
|
-
return [];
|
|
3915
|
-
}
|
|
3916
|
-
const contour = [];
|
|
3917
|
-
let bx = startX;
|
|
3918
|
-
let by = startY;
|
|
3919
|
-
let backtrack = 6;
|
|
3920
|
-
const maxSteps = width * height * 4;
|
|
3921
|
-
for (let step = 0; step < maxSteps; step += 1) {
|
|
3922
|
-
let moved = false;
|
|
3923
|
-
for (let k = 1; k <= 8; k += 1) {
|
|
3924
|
-
const dir = (backtrack + k) % 8;
|
|
3925
|
-
const [dx, dy] = DIRS[dir];
|
|
3926
|
-
const nx = bx + dx;
|
|
3927
|
-
const ny = by + dy;
|
|
3928
|
-
if (at(nx, ny)) {
|
|
3929
|
-
contour.push([bx, by]);
|
|
3930
|
-
backtrack = (dir + 4) % 8;
|
|
3931
|
-
bx = nx;
|
|
3932
|
-
by = ny;
|
|
3933
|
-
moved = true;
|
|
3934
|
-
break;
|
|
3935
|
-
}
|
|
3936
|
-
}
|
|
3937
|
-
if (!moved) {
|
|
3938
|
-
contour.push([bx, by]);
|
|
3939
|
-
break;
|
|
3940
|
-
}
|
|
3941
|
-
if (bx === startX && by === startY && contour.length > 1) {
|
|
3942
|
-
break;
|
|
3943
|
-
}
|
|
3944
|
-
}
|
|
3945
|
-
return contour;
|
|
3946
|
-
}
|
|
3947
|
-
function perpendicularDistance(point, lineStart, lineEnd) {
|
|
3948
|
-
const [px, py] = point;
|
|
3949
|
-
const [ax, ay] = lineStart;
|
|
3950
|
-
const [bx, by] = lineEnd;
|
|
3951
|
-
const dx = bx - ax;
|
|
3952
|
-
const dy = by - ay;
|
|
3953
|
-
const lengthSq = dx * dx + dy * dy;
|
|
3954
|
-
if (lengthSq === 0) {
|
|
3955
|
-
return Math.hypot(px - ax, py - ay);
|
|
3956
|
-
}
|
|
3957
|
-
const cross = Math.abs(dx * (ay - py) - dy * (ax - px));
|
|
3958
|
-
return cross / Math.sqrt(lengthSq);
|
|
3959
|
-
}
|
|
3960
|
-
function douglasPeucker(points, tolerance) {
|
|
3961
|
-
if (points.length < 3) {
|
|
3962
|
-
return points.slice();
|
|
3963
|
-
}
|
|
3964
|
-
let maxDist = 0;
|
|
3965
|
-
let index = 0;
|
|
3966
|
-
const first = points[0];
|
|
3967
|
-
const last = points[points.length - 1];
|
|
3968
|
-
for (let i = 1; i < points.length - 1; i += 1) {
|
|
3969
|
-
const dist = perpendicularDistance(points[i], first, last);
|
|
3970
|
-
if (dist > maxDist) {
|
|
3971
|
-
maxDist = dist;
|
|
3972
|
-
index = i;
|
|
3973
|
-
}
|
|
3974
|
-
}
|
|
3975
|
-
if (maxDist <= tolerance) {
|
|
3976
|
-
return [first, last];
|
|
3977
|
-
}
|
|
3978
|
-
const left = douglasPeucker(points.slice(0, index + 1), tolerance);
|
|
3979
|
-
const right = douglasPeucker(points.slice(index), tolerance);
|
|
3980
|
-
return [...left.slice(0, -1), ...right];
|
|
3981
|
-
}
|
|
3982
|
-
function traceAlphaMaskContour(mask, width, height) {
|
|
3983
|
-
let foreground = 0;
|
|
3984
|
-
for (let i = 0; i < mask.length; i += 1) {
|
|
3985
|
-
if (mask[i] === 1) foreground += 1;
|
|
3986
|
-
}
|
|
3987
|
-
if (width <= 0 || height <= 0 || foreground === 0 || foreground / (width * height) >= OPAQUE_RATIO) {
|
|
3988
|
-
return rectangle();
|
|
3989
|
-
}
|
|
3990
|
-
const boundary = traceBoundary(mask, width, height);
|
|
3991
|
-
if (boundary.length < 3) {
|
|
3992
|
-
return rectangle();
|
|
3993
|
-
}
|
|
3994
|
-
const tolerance = Math.max(width, height) * 0.012;
|
|
3995
|
-
let simplified = douglasPeucker(boundary, tolerance);
|
|
3996
|
-
let extraTolerance = tolerance;
|
|
3997
|
-
while (simplified.length > MAX_POINTS) {
|
|
3998
|
-
extraTolerance *= 1.6;
|
|
3999
|
-
simplified = douglasPeucker(boundary, extraTolerance);
|
|
4000
|
-
}
|
|
4001
|
-
if (simplified.length < 3) {
|
|
4002
|
-
return rectangle();
|
|
4003
|
-
}
|
|
4004
|
-
return simplified.map(([x, y]) => ({
|
|
4005
|
-
x: Math.min(1, Math.max(0, x / width)),
|
|
4006
|
-
y: Math.min(1, Math.max(0, y / height))
|
|
4007
|
-
}));
|
|
4008
|
-
}
|
|
4009
|
-
function traceImageAlphaContour(img) {
|
|
4010
|
-
const cacheKey = img.src;
|
|
4011
|
-
const cached = contourCache.get(cacheKey);
|
|
4012
|
-
if (cached) {
|
|
4013
|
-
return cached.map((point) => ({ ...point }));
|
|
4014
|
-
}
|
|
4015
|
-
const built = buildAlphaMask(img);
|
|
4016
|
-
if (!built) {
|
|
4017
|
-
return rectangle();
|
|
4018
|
-
}
|
|
4019
|
-
const polygon = traceAlphaMaskContour(built.mask, built.width, built.height);
|
|
4020
|
-
contourCache.set(cacheKey, polygon);
|
|
4021
|
-
return polygon.map((point) => ({ ...point }));
|
|
4022
|
-
}
|
|
4023
3843
|
function cloneBlock(block) {
|
|
4024
3844
|
return block.type === "paragraph" ? {
|
|
4025
3845
|
...block,
|
|
@@ -40872,6 +40692,293 @@ function createEditorContextMenuClipboard(deps) {
|
|
|
40872
40692
|
programmaticPaste
|
|
40873
40693
|
};
|
|
40874
40694
|
}
|
|
40695
|
+
function createEditorTableContextMenuActions(deps) {
|
|
40696
|
+
const { state, tableOps, applyTableContextCommand } = deps;
|
|
40697
|
+
return {
|
|
40698
|
+
isInsideTable: deps.isInsideTable,
|
|
40699
|
+
canMerge: () => tableOps.canMergeSelectedTable(state()),
|
|
40700
|
+
canSplit: () => tableOps.canSplitSelectedTable(state()),
|
|
40701
|
+
canEditColumn: () => tableOps.canEditSelectedTableColumn(state()),
|
|
40702
|
+
canEditRow: () => tableOps.canEditSelectedTableRow(state()),
|
|
40703
|
+
openProperties: () => deps.openTablePropertiesDialog("table"),
|
|
40704
|
+
openBordersAndShading: () => deps.openTablePropertiesDialog("cell"),
|
|
40705
|
+
merge: () => applyTableContextCommand(
|
|
40706
|
+
(current) => tableOps.mergeSelectedTable(current),
|
|
40707
|
+
"mergeTable"
|
|
40708
|
+
),
|
|
40709
|
+
split: () => applyTableContextCommand(
|
|
40710
|
+
(current) => tableOps.splitSelectedTable(current),
|
|
40711
|
+
"splitTable"
|
|
40712
|
+
),
|
|
40713
|
+
insertColumnBefore: () => applyTableContextCommand(
|
|
40714
|
+
(current) => tableOps.insertSelectedTableColumn(current, -1),
|
|
40715
|
+
"insertTableColumn"
|
|
40716
|
+
),
|
|
40717
|
+
insertColumnAfter: () => applyTableContextCommand(
|
|
40718
|
+
(current) => tableOps.insertSelectedTableColumn(current, 1),
|
|
40719
|
+
"insertTableColumn"
|
|
40720
|
+
),
|
|
40721
|
+
deleteColumn: () => applyTableContextCommand(
|
|
40722
|
+
(current) => tableOps.deleteSelectedTableColumn(current),
|
|
40723
|
+
"deleteTableColumn"
|
|
40724
|
+
),
|
|
40725
|
+
insertRowBefore: () => applyTableContextCommand(
|
|
40726
|
+
(current) => tableOps.insertSelectedTableRow(current, -1),
|
|
40727
|
+
"insertTableRow"
|
|
40728
|
+
),
|
|
40729
|
+
insertRowAfter: () => applyTableContextCommand(
|
|
40730
|
+
(current) => tableOps.insertSelectedTableRow(current, 1),
|
|
40731
|
+
"insertTableRow"
|
|
40732
|
+
),
|
|
40733
|
+
deleteRow: () => applyTableContextCommand(
|
|
40734
|
+
(current) => tableOps.deleteSelectedTableRow(current),
|
|
40735
|
+
"deleteTableRow"
|
|
40736
|
+
)
|
|
40737
|
+
};
|
|
40738
|
+
}
|
|
40739
|
+
const RECTANGLE = [
|
|
40740
|
+
{ x: 0, y: 0 },
|
|
40741
|
+
{ x: 1, y: 0 },
|
|
40742
|
+
{ x: 1, y: 1 },
|
|
40743
|
+
{ x: 0, y: 1 }
|
|
40744
|
+
];
|
|
40745
|
+
const MAX_SIDE = 256;
|
|
40746
|
+
const ALPHA_THRESHOLD = 128;
|
|
40747
|
+
const OPAQUE_RATIO = 0.985;
|
|
40748
|
+
const MAX_POINTS = 40;
|
|
40749
|
+
const contourCache = /* @__PURE__ */ new Map();
|
|
40750
|
+
function rectangle() {
|
|
40751
|
+
return RECTANGLE.map((point) => ({ ...point }));
|
|
40752
|
+
}
|
|
40753
|
+
const DIRS = [
|
|
40754
|
+
[0, -1],
|
|
40755
|
+
[1, -1],
|
|
40756
|
+
[1, 0],
|
|
40757
|
+
[1, 1],
|
|
40758
|
+
[0, 1],
|
|
40759
|
+
[-1, 1],
|
|
40760
|
+
[-1, 0],
|
|
40761
|
+
[-1, -1]
|
|
40762
|
+
];
|
|
40763
|
+
function buildAlphaMask(img) {
|
|
40764
|
+
const naturalW = img.naturalWidth || img.width;
|
|
40765
|
+
const naturalH = img.naturalHeight || img.height;
|
|
40766
|
+
if (!naturalW || !naturalH) {
|
|
40767
|
+
return null;
|
|
40768
|
+
}
|
|
40769
|
+
const scale = Math.min(1, MAX_SIDE / Math.max(naturalW, naturalH));
|
|
40770
|
+
const width = Math.max(1, Math.round(naturalW * scale));
|
|
40771
|
+
const height = Math.max(1, Math.round(naturalH * scale));
|
|
40772
|
+
const canvas = document.createElement("canvas");
|
|
40773
|
+
canvas.width = width;
|
|
40774
|
+
canvas.height = height;
|
|
40775
|
+
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
40776
|
+
if (!ctx) {
|
|
40777
|
+
return null;
|
|
40778
|
+
}
|
|
40779
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
40780
|
+
let pixels;
|
|
40781
|
+
try {
|
|
40782
|
+
pixels = ctx.getImageData(0, 0, width, height).data;
|
|
40783
|
+
} catch {
|
|
40784
|
+
return null;
|
|
40785
|
+
}
|
|
40786
|
+
const mask = new Uint8Array(width * height);
|
|
40787
|
+
let foreground = 0;
|
|
40788
|
+
for (let i = 0; i < mask.length; i += 1) {
|
|
40789
|
+
if (pixels[i * 4 + 3] >= ALPHA_THRESHOLD) {
|
|
40790
|
+
mask[i] = 1;
|
|
40791
|
+
foreground += 1;
|
|
40792
|
+
}
|
|
40793
|
+
}
|
|
40794
|
+
return { mask, width, height, foreground };
|
|
40795
|
+
}
|
|
40796
|
+
function traceBoundary(mask, width, height) {
|
|
40797
|
+
const at = (x, y) => x >= 0 && x < width && y >= 0 && y < height && mask[y * width + x] === 1;
|
|
40798
|
+
let startX = -1;
|
|
40799
|
+
let startY = -1;
|
|
40800
|
+
for (let y = 0; y < height && startY < 0; y += 1) {
|
|
40801
|
+
for (let x = 0; x < width; x += 1) {
|
|
40802
|
+
if (mask[y * width + x] === 1) {
|
|
40803
|
+
startX = x;
|
|
40804
|
+
startY = y;
|
|
40805
|
+
break;
|
|
40806
|
+
}
|
|
40807
|
+
}
|
|
40808
|
+
}
|
|
40809
|
+
if (startX < 0) {
|
|
40810
|
+
return [];
|
|
40811
|
+
}
|
|
40812
|
+
const contour = [];
|
|
40813
|
+
let bx = startX;
|
|
40814
|
+
let by = startY;
|
|
40815
|
+
let backtrack = 6;
|
|
40816
|
+
const maxSteps = width * height * 4;
|
|
40817
|
+
for (let step = 0; step < maxSteps; step += 1) {
|
|
40818
|
+
let moved = false;
|
|
40819
|
+
for (let k = 1; k <= 8; k += 1) {
|
|
40820
|
+
const dir = (backtrack + k) % 8;
|
|
40821
|
+
const [dx, dy] = DIRS[dir];
|
|
40822
|
+
const nx = bx + dx;
|
|
40823
|
+
const ny = by + dy;
|
|
40824
|
+
if (at(nx, ny)) {
|
|
40825
|
+
contour.push([bx, by]);
|
|
40826
|
+
backtrack = (dir + 4) % 8;
|
|
40827
|
+
bx = nx;
|
|
40828
|
+
by = ny;
|
|
40829
|
+
moved = true;
|
|
40830
|
+
break;
|
|
40831
|
+
}
|
|
40832
|
+
}
|
|
40833
|
+
if (!moved) {
|
|
40834
|
+
contour.push([bx, by]);
|
|
40835
|
+
break;
|
|
40836
|
+
}
|
|
40837
|
+
if (bx === startX && by === startY && contour.length > 1) {
|
|
40838
|
+
break;
|
|
40839
|
+
}
|
|
40840
|
+
}
|
|
40841
|
+
return contour;
|
|
40842
|
+
}
|
|
40843
|
+
function perpendicularDistance(point, lineStart, lineEnd) {
|
|
40844
|
+
const [px, py] = point;
|
|
40845
|
+
const [ax, ay] = lineStart;
|
|
40846
|
+
const [bx, by] = lineEnd;
|
|
40847
|
+
const dx = bx - ax;
|
|
40848
|
+
const dy = by - ay;
|
|
40849
|
+
const lengthSq = dx * dx + dy * dy;
|
|
40850
|
+
if (lengthSq === 0) {
|
|
40851
|
+
return Math.hypot(px - ax, py - ay);
|
|
40852
|
+
}
|
|
40853
|
+
const cross = Math.abs(dx * (ay - py) - dy * (ax - px));
|
|
40854
|
+
return cross / Math.sqrt(lengthSq);
|
|
40855
|
+
}
|
|
40856
|
+
function douglasPeucker(points, tolerance) {
|
|
40857
|
+
if (points.length < 3) {
|
|
40858
|
+
return points.slice();
|
|
40859
|
+
}
|
|
40860
|
+
let maxDist = 0;
|
|
40861
|
+
let index = 0;
|
|
40862
|
+
const first = points[0];
|
|
40863
|
+
const last = points[points.length - 1];
|
|
40864
|
+
for (let i = 1; i < points.length - 1; i += 1) {
|
|
40865
|
+
const dist = perpendicularDistance(points[i], first, last);
|
|
40866
|
+
if (dist > maxDist) {
|
|
40867
|
+
maxDist = dist;
|
|
40868
|
+
index = i;
|
|
40869
|
+
}
|
|
40870
|
+
}
|
|
40871
|
+
if (maxDist <= tolerance) {
|
|
40872
|
+
return [first, last];
|
|
40873
|
+
}
|
|
40874
|
+
const left = douglasPeucker(points.slice(0, index + 1), tolerance);
|
|
40875
|
+
const right = douglasPeucker(points.slice(index), tolerance);
|
|
40876
|
+
return [...left.slice(0, -1), ...right];
|
|
40877
|
+
}
|
|
40878
|
+
function traceAlphaMaskContour(mask, width, height) {
|
|
40879
|
+
let foreground = 0;
|
|
40880
|
+
for (let i = 0; i < mask.length; i += 1) {
|
|
40881
|
+
if (mask[i] === 1) foreground += 1;
|
|
40882
|
+
}
|
|
40883
|
+
if (width <= 0 || height <= 0 || foreground === 0 || foreground / (width * height) >= OPAQUE_RATIO) {
|
|
40884
|
+
return rectangle();
|
|
40885
|
+
}
|
|
40886
|
+
const boundary = traceBoundary(mask, width, height);
|
|
40887
|
+
if (boundary.length < 3) {
|
|
40888
|
+
return rectangle();
|
|
40889
|
+
}
|
|
40890
|
+
const tolerance = Math.max(width, height) * 0.012;
|
|
40891
|
+
let simplified = douglasPeucker(boundary, tolerance);
|
|
40892
|
+
let extraTolerance = tolerance;
|
|
40893
|
+
while (simplified.length > MAX_POINTS) {
|
|
40894
|
+
extraTolerance *= 1.6;
|
|
40895
|
+
simplified = douglasPeucker(boundary, extraTolerance);
|
|
40896
|
+
}
|
|
40897
|
+
if (simplified.length < 3) {
|
|
40898
|
+
return rectangle();
|
|
40899
|
+
}
|
|
40900
|
+
return simplified.map(([x, y]) => ({
|
|
40901
|
+
x: Math.min(1, Math.max(0, x / width)),
|
|
40902
|
+
y: Math.min(1, Math.max(0, y / height))
|
|
40903
|
+
}));
|
|
40904
|
+
}
|
|
40905
|
+
function traceImageAlphaContour(img) {
|
|
40906
|
+
const cacheKey = img.src;
|
|
40907
|
+
const cached = contourCache.get(cacheKey);
|
|
40908
|
+
if (cached) {
|
|
40909
|
+
return cached.map((point) => ({ ...point }));
|
|
40910
|
+
}
|
|
40911
|
+
const built = buildAlphaMask(img);
|
|
40912
|
+
if (!built) {
|
|
40913
|
+
return rectangle();
|
|
40914
|
+
}
|
|
40915
|
+
const polygon = traceAlphaMaskContour(built.mask, built.width, built.height);
|
|
40916
|
+
contourCache.set(cacheKey, polygon);
|
|
40917
|
+
return polygon.map((point) => ({ ...point }));
|
|
40918
|
+
}
|
|
40919
|
+
function createEditorLayoutOptionsController(deps) {
|
|
40920
|
+
const { state, resetTransactionGrouping, applyTransactionalState, focusInput } = deps;
|
|
40921
|
+
const layoutOptionsTarget = () => {
|
|
40922
|
+
if (getSelectedImageRun(state())) return "image";
|
|
40923
|
+
if (getSelectedTextBoxRun(state())) return "textBox";
|
|
40924
|
+
return null;
|
|
40925
|
+
};
|
|
40926
|
+
const applyLayoutOptionPatch = (mergeKey, apply) => {
|
|
40927
|
+
const target = layoutOptionsTarget();
|
|
40928
|
+
if (!target) return;
|
|
40929
|
+
resetTransactionGrouping();
|
|
40930
|
+
applyTransactionalState((current) => apply(current, target), { mergeKey });
|
|
40931
|
+
focusInput();
|
|
40932
|
+
};
|
|
40933
|
+
const ensureImageWrapContour = (runId, src) => {
|
|
40934
|
+
const resolved = resolveImageSrc(state().document, src);
|
|
40935
|
+
const applyContour = (img2) => {
|
|
40936
|
+
const polygon = traceImageAlphaContour(img2);
|
|
40937
|
+
applyTransactionalState(
|
|
40938
|
+
(current) => setImageWrapPolygon(current, runId, polygon),
|
|
40939
|
+
{ mergeKey: "layoutWrapPolygon" }
|
|
40940
|
+
);
|
|
40941
|
+
};
|
|
40942
|
+
const img = getCachedCanvasImage(resolved, () => {
|
|
40943
|
+
if (img.naturalWidth > 0) applyContour(img);
|
|
40944
|
+
});
|
|
40945
|
+
if (img.complete && img.naturalWidth > 0) {
|
|
40946
|
+
applyContour(img);
|
|
40947
|
+
}
|
|
40948
|
+
};
|
|
40949
|
+
return {
|
|
40950
|
+
target: layoutOptionsTarget,
|
|
40951
|
+
preset: () => {
|
|
40952
|
+
const target = layoutOptionsTarget();
|
|
40953
|
+
if (target === "image") return getSelectedImageWrapPreset(state());
|
|
40954
|
+
if (target === "textBox") return getSelectedTextBoxWrapPreset(state());
|
|
40955
|
+
return null;
|
|
40956
|
+
},
|
|
40957
|
+
fixedPosition: () => {
|
|
40958
|
+
const target = layoutOptionsTarget();
|
|
40959
|
+
if (target === "image") return isSelectedImageFixedPosition(state());
|
|
40960
|
+
if (target === "textBox") return isSelectedTextBoxFixedPosition(state());
|
|
40961
|
+
return false;
|
|
40962
|
+
},
|
|
40963
|
+
setPreset: (preset) => {
|
|
40964
|
+
applyLayoutOptionPatch(
|
|
40965
|
+
"layoutWrapPreset",
|
|
40966
|
+
(current, target) => target === "image" ? setSelectedImageWrapPreset(current, preset) : setSelectedTextBoxWrapPreset(current, preset)
|
|
40967
|
+
);
|
|
40968
|
+
if (preset === "tight" || preset === "through") {
|
|
40969
|
+
const selected = getSelectedImageRun(state());
|
|
40970
|
+
const image = selected == null ? void 0 : selected.run.image;
|
|
40971
|
+
if (image && !image.wrapPolygon) {
|
|
40972
|
+
ensureImageWrapContour(selected.run.id, image.src);
|
|
40973
|
+
}
|
|
40974
|
+
}
|
|
40975
|
+
},
|
|
40976
|
+
setFixedPosition: (fixed) => applyLayoutOptionPatch(
|
|
40977
|
+
"layoutFixedPosition",
|
|
40978
|
+
(current, target) => target === "image" ? setSelectedImageFixedPosition(current, fixed) : setSelectedTextBoxFixedPosition(current, fixed)
|
|
40979
|
+
)
|
|
40980
|
+
};
|
|
40981
|
+
}
|
|
40875
40982
|
const DEFAULT_TOC_MAX_LEVEL = 3;
|
|
40876
40983
|
const TOC_INSTRUCTION = ' TOC \\o "1-3" \\h \\z \\u ';
|
|
40877
40984
|
const PX_TO_PT = 72 / 96;
|
|
@@ -47085,62 +47192,12 @@ function OasisEditorApp(props = {}) {
|
|
|
47085
47192
|
runtimeClient.emit("selectionChange", snapshot.selection);
|
|
47086
47193
|
});
|
|
47087
47194
|
const selectedImageRun = () => getSelectedImageRun(state);
|
|
47088
|
-
const
|
|
47089
|
-
|
|
47090
|
-
|
|
47091
|
-
|
|
47092
|
-
|
|
47093
|
-
};
|
|
47094
|
-
const applyLayoutOptionPatch = (mergeKey, apply) => {
|
|
47095
|
-
const target = layoutOptionsTarget();
|
|
47096
|
-
if (!target) return;
|
|
47097
|
-
resetTransactionGrouping();
|
|
47098
|
-
applyTransactionalState((current) => apply(current, target), {
|
|
47099
|
-
mergeKey
|
|
47100
|
-
});
|
|
47101
|
-
focusInput();
|
|
47102
|
-
};
|
|
47103
|
-
const ensureImageWrapContour = (runId, src) => {
|
|
47104
|
-
const resolved = resolveImageSrc(state.document, src);
|
|
47105
|
-
const applyContour = (img2) => {
|
|
47106
|
-
const polygon = traceImageAlphaContour(img2);
|
|
47107
|
-
applyTransactionalState((current) => setImageWrapPolygon(current, runId, polygon), {
|
|
47108
|
-
mergeKey: "layoutWrapPolygon"
|
|
47109
|
-
});
|
|
47110
|
-
};
|
|
47111
|
-
const img = getCachedCanvasImage(resolved, () => {
|
|
47112
|
-
if (img.naturalWidth > 0) applyContour(img);
|
|
47113
|
-
});
|
|
47114
|
-
if (img.complete && img.naturalWidth > 0) {
|
|
47115
|
-
applyContour(img);
|
|
47116
|
-
}
|
|
47117
|
-
};
|
|
47118
|
-
const layoutOptionsOverlay = {
|
|
47119
|
-
target: layoutOptionsTarget,
|
|
47120
|
-
preset: () => {
|
|
47121
|
-
const target = layoutOptionsTarget();
|
|
47122
|
-
if (target === "image") return getSelectedImageWrapPreset(state);
|
|
47123
|
-
if (target === "textBox") return getSelectedTextBoxWrapPreset(state);
|
|
47124
|
-
return null;
|
|
47125
|
-
},
|
|
47126
|
-
fixedPosition: () => {
|
|
47127
|
-
const target = layoutOptionsTarget();
|
|
47128
|
-
if (target === "image") return isSelectedImageFixedPosition(state);
|
|
47129
|
-
if (target === "textBox") return isSelectedTextBoxFixedPosition(state);
|
|
47130
|
-
return false;
|
|
47131
|
-
},
|
|
47132
|
-
setPreset: (preset) => {
|
|
47133
|
-
applyLayoutOptionPatch("layoutWrapPreset", (current, target) => target === "image" ? setSelectedImageWrapPreset(current, preset) : setSelectedTextBoxWrapPreset(current, preset));
|
|
47134
|
-
if (preset === "tight" || preset === "through") {
|
|
47135
|
-
const selected = getSelectedImageRun(state);
|
|
47136
|
-
const image = selected == null ? void 0 : selected.run.image;
|
|
47137
|
-
if (image && !image.wrapPolygon) {
|
|
47138
|
-
ensureImageWrapContour(selected.run.id, image.src);
|
|
47139
|
-
}
|
|
47140
|
-
}
|
|
47141
|
-
},
|
|
47142
|
-
setFixedPosition: (fixed) => applyLayoutOptionPatch("layoutFixedPosition", (current, target) => target === "image" ? setSelectedImageFixedPosition(current, fixed) : setSelectedTextBoxFixedPosition(current, fixed))
|
|
47143
|
-
};
|
|
47195
|
+
const layoutOptionsOverlay = createEditorLayoutOptionsController({
|
|
47196
|
+
state: () => state,
|
|
47197
|
+
resetTransactionGrouping,
|
|
47198
|
+
applyTransactionalState,
|
|
47199
|
+
focusInput
|
|
47200
|
+
});
|
|
47144
47201
|
const canvasHitResolver = createCanvasSurfaceHitResolver({
|
|
47145
47202
|
state: () => state,
|
|
47146
47203
|
surfaceRef: () => surfaceRef() ?? null,
|
|
@@ -47501,23 +47558,13 @@ function OasisEditorApp(props = {}) {
|
|
|
47501
47558
|
promptForLink: commandsController.promptForLink,
|
|
47502
47559
|
openFontDialog,
|
|
47503
47560
|
openParagraphDialog,
|
|
47504
|
-
table: {
|
|
47561
|
+
table: createEditorTableContextMenuActions({
|
|
47562
|
+
state: () => state,
|
|
47563
|
+
tableOps,
|
|
47505
47564
|
isInsideTable: tablePropertiesDialogBridge.isInsideTable,
|
|
47506
|
-
|
|
47507
|
-
|
|
47508
|
-
|
|
47509
|
-
canEditRow: () => tableOps.canEditSelectedTableRow(state),
|
|
47510
|
-
openProperties: () => openTablePropertiesDialog("table"),
|
|
47511
|
-
openBordersAndShading: () => openTablePropertiesDialog("cell"),
|
|
47512
|
-
merge: () => applyTableContextCommand((current) => tableOps.mergeSelectedTable(current), "mergeTable"),
|
|
47513
|
-
split: () => applyTableContextCommand((current) => tableOps.splitSelectedTable(current), "splitTable"),
|
|
47514
|
-
insertColumnBefore: () => applyTableContextCommand((current) => tableOps.insertSelectedTableColumn(current, -1), "insertTableColumn"),
|
|
47515
|
-
insertColumnAfter: () => applyTableContextCommand((current) => tableOps.insertSelectedTableColumn(current, 1), "insertTableColumn"),
|
|
47516
|
-
deleteColumn: () => applyTableContextCommand((current) => tableOps.deleteSelectedTableColumn(current), "deleteTableColumn"),
|
|
47517
|
-
insertRowBefore: () => applyTableContextCommand((current) => tableOps.insertSelectedTableRow(current, -1), "insertTableRow"),
|
|
47518
|
-
insertRowAfter: () => applyTableContextCommand((current) => tableOps.insertSelectedTableRow(current, 1), "insertTableRow"),
|
|
47519
|
-
deleteRow: () => applyTableContextCommand((current) => tableOps.deleteSelectedTableRow(current), "deleteTableRow")
|
|
47520
|
-
}
|
|
47565
|
+
openTablePropertiesDialog,
|
|
47566
|
+
applyTableContextCommand
|
|
47567
|
+
})
|
|
47521
47568
|
});
|
|
47522
47569
|
const buildContextMenuItems = contextMenuClipboard.buildContextMenuItems;
|
|
47523
47570
|
const handleEditorContextMenu = contextMenuClipboard.handleEditorContextMenu;
|