superdoc 1.12.0-next.11 → 1.12.0-next.13
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/chunks/{PdfViewer-1H_e-blH.cjs → PdfViewer-BM8GbrHb.cjs} +2 -2
- package/dist/chunks/{PdfViewer-2GmHPcuP.es.js → PdfViewer-D9duMPBd.es.js} +2 -2
- package/dist/chunks/{SuperConverter-DKC3eAnw.cjs → SuperConverter-BMjvGr5r.cjs} +14 -3
- package/dist/chunks/{SuperConverter-Cyd0kGmJ.es.js → SuperConverter-Dx95dNlr.es.js} +14 -3
- package/dist/chunks/{index-BKXPlsQF.cjs → index-BF7DfWLs.cjs} +756 -390
- package/dist/chunks/{index-BlzZBR33.es.js → index-BTrpAvox.es.js} +4 -4
- package/dist/chunks/{index-C22k0MUW.es.js → index-C-t9SDCr.es.js} +756 -390
- package/dist/chunks/{index-CpgpR-lf.cjs → index-DcUDN9u9.cjs} +4 -4
- package/dist/style.css +39 -29
- package/dist/super-editor/converter.cjs +1 -1
- package/dist/super-editor/converter.es.js +1 -1
- package/dist/super-editor/core/Editor.d.ts.map +1 -1
- package/dist/super-editor/core/presentation-editor/PresentationEditor.d.ts.map +1 -1
- package/dist/super-editor/core/super-converter/v3/handlers/w/sdt/helpers/handle-structured-content-node.d.ts.map +1 -1
- package/dist/super-editor/extensions/structured-content/StructuredContentBlockView.d.ts.map +1 -1
- package/dist/super-editor/extensions/structured-content/StructuredContentInlineView.d.ts.map +1 -1
- package/dist/super-editor/extensions/structured-content/StructuredContentViewBase.d.ts +3 -0
- package/dist/super-editor/extensions/structured-content/StructuredContentViewBase.d.ts.map +1 -1
- package/dist/super-editor/extensions/structured-content/structured-content-block.d.ts.map +1 -1
- package/dist/super-editor/extensions/structured-content/structured-content-lock-plugin.d.ts +5 -0
- package/dist/super-editor/extensions/structured-content/structured-content-lock-plugin.d.ts.map +1 -0
- package/dist/super-editor/extensions/structured-content/structured-content-select-plugin.d.ts +14 -0
- package/dist/super-editor/extensions/structured-content/structured-content-select-plugin.d.ts.map +1 -0
- package/dist/super-editor/extensions/structured-content/structured-content.d.ts.map +1 -1
- package/dist/super-editor/extensions/types/node-attributes.d.ts +4 -0
- package/dist/super-editor/extensions/types/node-attributes.d.ts.map +1 -1
- package/dist/super-editor.cjs +2 -2
- package/dist/super-editor.es.js +3 -3
- package/dist/superdoc.cjs +3 -3
- package/dist/superdoc.es.js +3 -3
- package/dist/superdoc.umd.js +770 -393
- package/dist/superdoc.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const superEditor_converter = require("./SuperConverter-
|
|
2
|
+
const superEditor_converter = require("./SuperConverter-BMjvGr5r.cjs");
|
|
3
3
|
const helpers$1 = require("./helpers-OFep8CYR.cjs");
|
|
4
4
|
const vue = require("./vue-BkoOkkmT.cjs");
|
|
5
5
|
require("./jszip.min-oAFpNMh5.cjs");
|
|
@@ -993,7 +993,7 @@ const DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
|
|
|
993
993
|
const COMMUNITY_LICENSE_KEY = "community-and-eval-agplv3";
|
|
994
994
|
function getSuperdocVersion() {
|
|
995
995
|
try {
|
|
996
|
-
return true ? "1.12.0-next.
|
|
996
|
+
return true ? "1.12.0-next.13" : "unknown";
|
|
997
997
|
} catch {
|
|
998
998
|
return "unknown";
|
|
999
999
|
}
|
|
@@ -17068,7 +17068,7 @@ const canUseDOM = () => {
|
|
|
17068
17068
|
return false;
|
|
17069
17069
|
}
|
|
17070
17070
|
};
|
|
17071
|
-
const summaryVersion = "1.12.0-next.
|
|
17071
|
+
const summaryVersion = "1.12.0-next.13";
|
|
17072
17072
|
const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
|
|
17073
17073
|
const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
|
|
17074
17074
|
function mapAttributes(attrs) {
|
|
@@ -19482,8 +19482,7 @@ class Editor extends EventEmitter {
|
|
|
19482
19482
|
"docProps/custom.xml": String(customXml),
|
|
19483
19483
|
"word/_rels/document.xml.rels": String(rels),
|
|
19484
19484
|
"word/numbering.xml": String(numbering),
|
|
19485
|
-
|
|
19486
|
-
"word/styles.xml": String(styles).replace(/&/gi, "&"),
|
|
19485
|
+
"word/styles.xml": String(styles),
|
|
19487
19486
|
...updatedHeadersFooters,
|
|
19488
19487
|
...coreXml ? { "docProps/core.xml": String(coreXml) } : {}
|
|
19489
19488
|
};
|
|
@@ -19873,7 +19872,7 @@ class Editor extends EventEmitter {
|
|
|
19873
19872
|
* Process collaboration migrations
|
|
19874
19873
|
*/
|
|
19875
19874
|
processCollaborationMigrations() {
|
|
19876
|
-
console.debug("[checkVersionMigrations] Current editor version", "1.12.0-next.
|
|
19875
|
+
console.debug("[checkVersionMigrations] Current editor version", "1.12.0-next.13");
|
|
19877
19876
|
if (!this.options.ydoc) return;
|
|
19878
19877
|
const metaMap = this.options.ydoc.getMap("meta");
|
|
19879
19878
|
let docVersion = metaMap.get("version");
|
|
@@ -20051,6 +20050,300 @@ class Editor extends EventEmitter {
|
|
|
20051
20050
|
this.#renderer?.initDevTools?.(this);
|
|
20052
20051
|
}
|
|
20053
20052
|
}
|
|
20053
|
+
function getEditorSurfaceElement(editor) {
|
|
20054
|
+
if (!editor) return null;
|
|
20055
|
+
if (typeof editor.hitTest === "function" && editor.element instanceof HTMLElement) {
|
|
20056
|
+
return editor.element;
|
|
20057
|
+
}
|
|
20058
|
+
return editor.presentationEditor?.element ?? editor.view?.dom ?? editor.options?.element ?? null;
|
|
20059
|
+
}
|
|
20060
|
+
function getSurfaceRelativePoint(editor, eventLocation = {}) {
|
|
20061
|
+
const surface = getEditorSurfaceElement(editor);
|
|
20062
|
+
if (!surface) return null;
|
|
20063
|
+
const rect = surface.getBoundingClientRect();
|
|
20064
|
+
let left2;
|
|
20065
|
+
let top2;
|
|
20066
|
+
if (typeof eventLocation.clientX === "number" && typeof eventLocation.clientY === "number") {
|
|
20067
|
+
left2 = eventLocation.clientX - rect.left;
|
|
20068
|
+
top2 = eventLocation.clientY - rect.top;
|
|
20069
|
+
} else if (editor?.state?.selection) {
|
|
20070
|
+
const selectionFrom = editor.state.selection.from;
|
|
20071
|
+
const coords = editor.coordsAtPos?.(selectionFrom);
|
|
20072
|
+
if (coords) {
|
|
20073
|
+
left2 = coords.left - rect.left;
|
|
20074
|
+
top2 = coords.top - rect.top;
|
|
20075
|
+
}
|
|
20076
|
+
}
|
|
20077
|
+
if (!Number.isFinite(left2) || !Number.isFinite(top2)) {
|
|
20078
|
+
return null;
|
|
20079
|
+
}
|
|
20080
|
+
return { left: left2, top: top2 };
|
|
20081
|
+
}
|
|
20082
|
+
function findContainingBlockAncestor(element) {
|
|
20083
|
+
if (!element) return null;
|
|
20084
|
+
let current = element.parentElement;
|
|
20085
|
+
while (current && current !== document.body && current !== document.documentElement) {
|
|
20086
|
+
try {
|
|
20087
|
+
const style2 = window.getComputedStyle(current);
|
|
20088
|
+
const transform = style2.transform;
|
|
20089
|
+
const filter = style2.filter;
|
|
20090
|
+
const backdropFilter = style2.backdropFilter || style2.webkitBackdropFilter;
|
|
20091
|
+
const perspective = style2.perspective;
|
|
20092
|
+
const willChange = style2.willChange;
|
|
20093
|
+
const contain = style2.contain;
|
|
20094
|
+
if (transform && transform !== "none") {
|
|
20095
|
+
return current;
|
|
20096
|
+
}
|
|
20097
|
+
if (filter && filter !== "none") {
|
|
20098
|
+
return current;
|
|
20099
|
+
}
|
|
20100
|
+
if (backdropFilter && backdropFilter !== "none") {
|
|
20101
|
+
return current;
|
|
20102
|
+
}
|
|
20103
|
+
if (perspective && perspective !== "none") {
|
|
20104
|
+
return current;
|
|
20105
|
+
}
|
|
20106
|
+
if (willChange && willChange !== "auto") {
|
|
20107
|
+
const values = willChange.split(",").map((v) => v.trim());
|
|
20108
|
+
if (values.includes("transform") || values.includes("perspective")) {
|
|
20109
|
+
return current;
|
|
20110
|
+
}
|
|
20111
|
+
}
|
|
20112
|
+
if (contain && /paint|layout|strict|content/.test(contain)) {
|
|
20113
|
+
return current;
|
|
20114
|
+
}
|
|
20115
|
+
} catch (error) {
|
|
20116
|
+
console.warn("SlashMenu: Failed to get computed style for element", current, error);
|
|
20117
|
+
}
|
|
20118
|
+
current = current.parentElement;
|
|
20119
|
+
}
|
|
20120
|
+
return null;
|
|
20121
|
+
}
|
|
20122
|
+
const SlashMenuPluginKey = new superEditor_converter.PluginKey("slashMenu");
|
|
20123
|
+
const MENU_OFFSET_X = 100;
|
|
20124
|
+
const MENU_OFFSET_Y = 28;
|
|
20125
|
+
const CONTEXT_MENU_OFFSET_X = 10;
|
|
20126
|
+
const CONTEXT_MENU_OFFSET_Y = 10;
|
|
20127
|
+
const SLASH_COOLDOWN_MS = 5e3;
|
|
20128
|
+
const SlashMenu = Extension.create({
|
|
20129
|
+
name: "slashMenu",
|
|
20130
|
+
/**
|
|
20131
|
+
* Initialize default options for the SlashMenu extension
|
|
20132
|
+
* @returns {SlashMenuOptions} Empty options object (configuration is inherited from editor options)
|
|
20133
|
+
*/
|
|
20134
|
+
addOptions() {
|
|
20135
|
+
return {};
|
|
20136
|
+
},
|
|
20137
|
+
addPmPlugins() {
|
|
20138
|
+
const editor = this.editor;
|
|
20139
|
+
if (editor.options?.isHeadless) {
|
|
20140
|
+
return [];
|
|
20141
|
+
}
|
|
20142
|
+
let slashCooldown = false;
|
|
20143
|
+
let slashCooldownTimeout = null;
|
|
20144
|
+
const isMenuDisabled = () => Boolean(editor.options?.disableContextMenu);
|
|
20145
|
+
const ensureStateShape = (value = {}) => ({
|
|
20146
|
+
open: false,
|
|
20147
|
+
selected: null,
|
|
20148
|
+
anchorPos: null,
|
|
20149
|
+
menuPosition: null,
|
|
20150
|
+
disabled: isMenuDisabled(),
|
|
20151
|
+
...value
|
|
20152
|
+
});
|
|
20153
|
+
const slashMenuPlugin = new superEditor_converter.Plugin({
|
|
20154
|
+
key: SlashMenuPluginKey,
|
|
20155
|
+
state: {
|
|
20156
|
+
init: () => ensureStateShape(),
|
|
20157
|
+
/**
|
|
20158
|
+
* Apply transaction to update plugin state
|
|
20159
|
+
* Handles state transitions based on transaction metadata:
|
|
20160
|
+
* - 'open': Opens menu at specified position or cursor location
|
|
20161
|
+
* - 'select': Updates the selected menu item
|
|
20162
|
+
* - 'close': Closes the menu and clears anchor position
|
|
20163
|
+
* - 'updatePosition': Triggers menu position recalculation (no-op in apply)
|
|
20164
|
+
*
|
|
20165
|
+
* @param {import('prosemirror-state').Transaction} tr - The transaction
|
|
20166
|
+
* @param {SlashMenuState} value - Previous plugin state
|
|
20167
|
+
* @returns {SlashMenuState} New plugin state
|
|
20168
|
+
*/
|
|
20169
|
+
apply(tr, value) {
|
|
20170
|
+
const meta = tr.getMeta(SlashMenuPluginKey);
|
|
20171
|
+
const disabled = isMenuDisabled();
|
|
20172
|
+
if (disabled) {
|
|
20173
|
+
if (value.open) {
|
|
20174
|
+
editor.emit("slashMenu:close");
|
|
20175
|
+
}
|
|
20176
|
+
return ensureStateShape({ disabled: true });
|
|
20177
|
+
}
|
|
20178
|
+
if (!meta) {
|
|
20179
|
+
if (value.disabled !== disabled) {
|
|
20180
|
+
return ensureStateShape({ ...value, disabled });
|
|
20181
|
+
}
|
|
20182
|
+
return value;
|
|
20183
|
+
}
|
|
20184
|
+
switch (meta.type) {
|
|
20185
|
+
case "open": {
|
|
20186
|
+
if (typeof meta.pos !== "number" || meta.pos < 0 || meta.pos > tr.doc.content.size) {
|
|
20187
|
+
console.warn("SlashMenu: Invalid position", meta.pos);
|
|
20188
|
+
return ensureStateShape(value);
|
|
20189
|
+
}
|
|
20190
|
+
let left2 = 0;
|
|
20191
|
+
let top2 = 0;
|
|
20192
|
+
let isContextMenu = false;
|
|
20193
|
+
if (typeof meta.clientX === "number" && typeof meta.clientY === "number") {
|
|
20194
|
+
left2 = meta.clientX;
|
|
20195
|
+
top2 = meta.clientY;
|
|
20196
|
+
isContextMenu = true;
|
|
20197
|
+
} else {
|
|
20198
|
+
const relativePoint = getSurfaceRelativePoint(editor, meta);
|
|
20199
|
+
if (relativePoint) {
|
|
20200
|
+
const surface = editor.presentationEditor?.element ?? editor.view?.dom ?? editor.options?.element;
|
|
20201
|
+
if (surface) {
|
|
20202
|
+
try {
|
|
20203
|
+
const rect = surface.getBoundingClientRect();
|
|
20204
|
+
left2 = rect.left + relativePoint.left;
|
|
20205
|
+
top2 = rect.top + relativePoint.top;
|
|
20206
|
+
} catch (error) {
|
|
20207
|
+
console.warn("SlashMenu: Failed to get surface bounds", error);
|
|
20208
|
+
return ensureStateShape(value);
|
|
20209
|
+
}
|
|
20210
|
+
}
|
|
20211
|
+
}
|
|
20212
|
+
}
|
|
20213
|
+
const menuSurface = editor.presentationEditor?.element ?? editor.view?.dom ?? editor.options?.element;
|
|
20214
|
+
const containingBlock = findContainingBlockAncestor(menuSurface);
|
|
20215
|
+
if (containingBlock) {
|
|
20216
|
+
try {
|
|
20217
|
+
const cbRect = containingBlock.getBoundingClientRect();
|
|
20218
|
+
left2 -= cbRect.left;
|
|
20219
|
+
top2 -= cbRect.top;
|
|
20220
|
+
left2 += containingBlock.scrollLeft || 0;
|
|
20221
|
+
top2 += containingBlock.scrollTop || 0;
|
|
20222
|
+
} catch (error) {
|
|
20223
|
+
console.warn("SlashMenu: Failed to adjust for containing block", error);
|
|
20224
|
+
}
|
|
20225
|
+
}
|
|
20226
|
+
const offsetX = isContextMenu ? CONTEXT_MENU_OFFSET_X : MENU_OFFSET_X;
|
|
20227
|
+
const offsetY = isContextMenu ? CONTEXT_MENU_OFFSET_Y : MENU_OFFSET_Y;
|
|
20228
|
+
const menuPosition = {
|
|
20229
|
+
left: `${left2 + offsetX}px`,
|
|
20230
|
+
top: `${top2 + offsetY}px`
|
|
20231
|
+
};
|
|
20232
|
+
const newState = {
|
|
20233
|
+
...value,
|
|
20234
|
+
open: true,
|
|
20235
|
+
anchorPos: meta.pos,
|
|
20236
|
+
menuPosition
|
|
20237
|
+
};
|
|
20238
|
+
editor.emit("slashMenu:open", { menuPosition });
|
|
20239
|
+
return ensureStateShape(newState);
|
|
20240
|
+
}
|
|
20241
|
+
case "select": {
|
|
20242
|
+
return ensureStateShape({ ...value, selected: meta.id });
|
|
20243
|
+
}
|
|
20244
|
+
case "close": {
|
|
20245
|
+
editor.emit("slashMenu:close");
|
|
20246
|
+
return ensureStateShape({ ...value, open: false, anchorPos: null });
|
|
20247
|
+
}
|
|
20248
|
+
default:
|
|
20249
|
+
return ensureStateShape({ ...value, disabled });
|
|
20250
|
+
}
|
|
20251
|
+
}
|
|
20252
|
+
},
|
|
20253
|
+
/**
|
|
20254
|
+
* Create view plugin to handle window event listeners
|
|
20255
|
+
* @param {import('prosemirror-view').EditorView} editorView - The ProseMirror editor view
|
|
20256
|
+
* @returns {Object} View plugin with destroy method
|
|
20257
|
+
*/
|
|
20258
|
+
view(editorView) {
|
|
20259
|
+
const updatePosition2 = () => {
|
|
20260
|
+
if (isMenuDisabled()) return;
|
|
20261
|
+
const state = SlashMenuPluginKey.getState(editorView.state);
|
|
20262
|
+
if (state.open) {
|
|
20263
|
+
editorView.dispatch(
|
|
20264
|
+
editorView.state.tr.setMeta(SlashMenuPluginKey, {
|
|
20265
|
+
type: "updatePosition"
|
|
20266
|
+
})
|
|
20267
|
+
);
|
|
20268
|
+
}
|
|
20269
|
+
};
|
|
20270
|
+
window.addEventListener("scroll", updatePosition2, true);
|
|
20271
|
+
window.addEventListener("resize", updatePosition2);
|
|
20272
|
+
return {
|
|
20273
|
+
destroy() {
|
|
20274
|
+
window.removeEventListener("scroll", updatePosition2, true);
|
|
20275
|
+
window.removeEventListener("resize", updatePosition2);
|
|
20276
|
+
if (slashCooldownTimeout) {
|
|
20277
|
+
clearTimeout(slashCooldownTimeout);
|
|
20278
|
+
slashCooldownTimeout = null;
|
|
20279
|
+
}
|
|
20280
|
+
}
|
|
20281
|
+
};
|
|
20282
|
+
},
|
|
20283
|
+
props: {
|
|
20284
|
+
/**
|
|
20285
|
+
* Handle keyboard events to open/close the slash menu
|
|
20286
|
+
* - '/': Opens menu at cursor if conditions are met (in paragraph, after space/start)
|
|
20287
|
+
* - 'Escape' or 'ArrowLeft': Closes menu and restores cursor position
|
|
20288
|
+
*
|
|
20289
|
+
* @param {import('prosemirror-view').EditorView} view - The ProseMirror editor view
|
|
20290
|
+
* @param {KeyboardEvent} event - The keyboard event
|
|
20291
|
+
* @returns {boolean} True if the event was handled, false otherwise
|
|
20292
|
+
*/
|
|
20293
|
+
handleKeyDown(view, event) {
|
|
20294
|
+
if (isMenuDisabled()) {
|
|
20295
|
+
return false;
|
|
20296
|
+
}
|
|
20297
|
+
const pluginState = this.getState(view.state);
|
|
20298
|
+
if (event.key === "/" && slashCooldown) {
|
|
20299
|
+
return false;
|
|
20300
|
+
}
|
|
20301
|
+
if (event.key === "/" && !pluginState.open) {
|
|
20302
|
+
const { $cursor } = view.state.selection;
|
|
20303
|
+
if (!$cursor) return false;
|
|
20304
|
+
const isParagraph = $cursor.parent.type.name === "paragraph";
|
|
20305
|
+
if (!isParagraph) return false;
|
|
20306
|
+
const textBefore = $cursor.parent.textContent.slice(0, $cursor.parentOffset);
|
|
20307
|
+
const isEmptyOrAfterSpace = !textBefore || textBefore.endsWith(" ");
|
|
20308
|
+
if (!isEmptyOrAfterSpace) return false;
|
|
20309
|
+
event.preventDefault();
|
|
20310
|
+
slashCooldown = true;
|
|
20311
|
+
if (slashCooldownTimeout) clearTimeout(slashCooldownTimeout);
|
|
20312
|
+
slashCooldownTimeout = setTimeout(() => {
|
|
20313
|
+
slashCooldown = false;
|
|
20314
|
+
slashCooldownTimeout = null;
|
|
20315
|
+
}, SLASH_COOLDOWN_MS);
|
|
20316
|
+
view.dispatch(
|
|
20317
|
+
view.state.tr.setMeta(SlashMenuPluginKey, {
|
|
20318
|
+
type: "open",
|
|
20319
|
+
pos: $cursor.pos
|
|
20320
|
+
})
|
|
20321
|
+
);
|
|
20322
|
+
return true;
|
|
20323
|
+
}
|
|
20324
|
+
if (pluginState.open && (event.key === "Escape" || event.key === "ArrowLeft")) {
|
|
20325
|
+
const { anchorPos } = pluginState;
|
|
20326
|
+
view.dispatch(
|
|
20327
|
+
view.state.tr.setMeta(SlashMenuPluginKey, {
|
|
20328
|
+
type: "close"
|
|
20329
|
+
})
|
|
20330
|
+
);
|
|
20331
|
+
if (anchorPos !== null) {
|
|
20332
|
+
const tr = view.state.tr.setSelection(
|
|
20333
|
+
view.state.selection.constructor.near(view.state.doc.resolve(anchorPos))
|
|
20334
|
+
);
|
|
20335
|
+
view.dispatch(tr);
|
|
20336
|
+
view.focus();
|
|
20337
|
+
}
|
|
20338
|
+
return true;
|
|
20339
|
+
}
|
|
20340
|
+
return false;
|
|
20341
|
+
}
|
|
20342
|
+
}
|
|
20343
|
+
});
|
|
20344
|
+
return [slashMenuPlugin];
|
|
20345
|
+
}
|
|
20346
|
+
});
|
|
20054
20347
|
let readFromCache;
|
|
20055
20348
|
let addToCache;
|
|
20056
20349
|
if (typeof WeakMap != "undefined") {
|
|
@@ -25084,21 +25377,21 @@ const SDT_CONTAINER_STYLES = `
|
|
|
25084
25377
|
|
|
25085
25378
|
/* Structured content drag handle/label - positioned above */
|
|
25086
25379
|
.superdoc-structured-content__label {
|
|
25087
|
-
font-size:
|
|
25380
|
+
font-size: 11px;
|
|
25088
25381
|
align-items: center;
|
|
25089
25382
|
justify-content: center;
|
|
25090
25383
|
position: absolute;
|
|
25091
25384
|
left: 2px;
|
|
25092
25385
|
top: -19px;
|
|
25093
25386
|
width: calc(100% - 4px);
|
|
25094
|
-
max-width:
|
|
25387
|
+
max-width: 130px;
|
|
25095
25388
|
min-width: 0;
|
|
25096
25389
|
height: 18px;
|
|
25097
25390
|
padding: 0 4px;
|
|
25098
25391
|
border: 1px solid #629be7;
|
|
25099
25392
|
border-bottom: none;
|
|
25100
25393
|
border-radius: 6px 6px 0 0;
|
|
25101
|
-
background-color: #
|
|
25394
|
+
background-color: #629be7ee;
|
|
25102
25395
|
box-sizing: border-box;
|
|
25103
25396
|
z-index: 10;
|
|
25104
25397
|
display: none;
|
|
@@ -25112,7 +25405,9 @@ const SDT_CONTAINER_STYLES = `
|
|
|
25112
25405
|
text-overflow: ellipsis;
|
|
25113
25406
|
}
|
|
25114
25407
|
|
|
25115
|
-
|
|
25408
|
+
/* Hover effect for block structured content (via event delegation class).
|
|
25409
|
+
* Shows label on hover — border reveal is handled by the lock-mode hover rule below. */
|
|
25410
|
+
.superdoc-structured-content-block.sdt-hover .superdoc-structured-content__label {
|
|
25116
25411
|
display: inline-flex;
|
|
25117
25412
|
}
|
|
25118
25413
|
|
|
@@ -25141,6 +25436,13 @@ const SDT_CONTAINER_STYLES = `
|
|
|
25141
25436
|
border-bottom: none;
|
|
25142
25437
|
}
|
|
25143
25438
|
|
|
25439
|
+
/* Collapse double borders between adjacent SDT blocks */
|
|
25440
|
+
.superdoc-structured-content-block + .superdoc-structured-content-block {
|
|
25441
|
+
border-top: none;
|
|
25442
|
+
border-top-left-radius: 0;
|
|
25443
|
+
border-top-right-radius: 0;
|
|
25444
|
+
}
|
|
25445
|
+
|
|
25144
25446
|
/* Structured Content Inline - Inline wrapper with blue border */
|
|
25145
25447
|
.superdoc-structured-content-inline {
|
|
25146
25448
|
padding: 1px;
|
|
@@ -25152,21 +25454,15 @@ const SDT_CONTAINER_STYLES = `
|
|
|
25152
25454
|
z-index: 10;
|
|
25153
25455
|
}
|
|
25154
25456
|
|
|
25155
|
-
/* Hover effect for inline structured content */
|
|
25156
|
-
.superdoc-structured-content-inline:hover {
|
|
25157
|
-
background-color: rgba(98, 155, 231, 0.15);
|
|
25158
|
-
border-color: #4a8ad9;
|
|
25159
|
-
}
|
|
25160
|
-
|
|
25161
25457
|
/* Inline structured content label - shown on hover */
|
|
25162
25458
|
.superdoc-structured-content-inline__label {
|
|
25163
25459
|
position: absolute;
|
|
25164
25460
|
bottom: calc(100% + 2px);
|
|
25165
25461
|
left: 50%;
|
|
25166
25462
|
transform: translateX(-50%);
|
|
25167
|
-
font-size:
|
|
25168
|
-
padding:
|
|
25169
|
-
background-color: #
|
|
25463
|
+
font-size: 11px;
|
|
25464
|
+
padding: 0 4px;
|
|
25465
|
+
background-color: #629be7ee;
|
|
25170
25466
|
color: white;
|
|
25171
25467
|
border-radius: 4px;
|
|
25172
25468
|
white-space: nowrap;
|
|
@@ -25179,6 +25475,17 @@ const SDT_CONTAINER_STYLES = `
|
|
|
25179
25475
|
display: block;
|
|
25180
25476
|
}
|
|
25181
25477
|
|
|
25478
|
+
/* Hover highlight for SDT containers.
|
|
25479
|
+
* Blue border is always visible (set in base rules above).
|
|
25480
|
+
* Hover adds background highlight and z-index boost.
|
|
25481
|
+
* Block SDTs use .sdt-hover class (event delegation for multi-fragment coordination).
|
|
25482
|
+
* Inline SDTs use :hover (single element, no coordination needed). */
|
|
25483
|
+
.superdoc-structured-content-block[data-lock-mode].sdt-hover,
|
|
25484
|
+
.superdoc-structured-content-inline[data-lock-mode]:hover {
|
|
25485
|
+
background-color: rgba(98, 155, 231, 0.08);
|
|
25486
|
+
z-index: 9999999;
|
|
25487
|
+
}
|
|
25488
|
+
|
|
25182
25489
|
/* Viewing mode: remove structured content affordances */
|
|
25183
25490
|
.presentation-editor--viewing .superdoc-structured-content-block,
|
|
25184
25491
|
.presentation-editor--viewing .superdoc-structured-content-inline {
|
|
@@ -25224,7 +25531,7 @@ const FIELD_ANNOTATION_STYLES = `
|
|
|
25224
25531
|
.superdoc-layout .annotation *::selection {
|
|
25225
25532
|
background: transparent;
|
|
25226
25533
|
}
|
|
25227
|
-
|
|
25534
|
+
|
|
25228
25535
|
.superdoc-layout .annotation::-moz-selection,
|
|
25229
25536
|
.superdoc-layout .annotation *::-moz-selection {
|
|
25230
25537
|
background: transparent;
|
|
@@ -25376,7 +25683,16 @@ const DOM_CLASS_NAMES = {
|
|
|
25376
25683
|
* within this wrapper should be used for character-level positioning, not the
|
|
25377
25684
|
* wrapper itself.
|
|
25378
25685
|
*/
|
|
25379
|
-
INLINE_SDT_WRAPPER: "superdoc-structured-content-inline"
|
|
25686
|
+
INLINE_SDT_WRAPPER: "superdoc-structured-content-inline",
|
|
25687
|
+
/**
|
|
25688
|
+
* Class name for block-level structured content containers.
|
|
25689
|
+
*/
|
|
25690
|
+
BLOCK_SDT: "superdoc-structured-content-block",
|
|
25691
|
+
/**
|
|
25692
|
+
* Class name added to block SDT fragments on hover via event delegation.
|
|
25693
|
+
* Applied/removed by SdtGroupedHover to highlight all fragments of the same SDT.
|
|
25694
|
+
*/
|
|
25695
|
+
SDT_HOVER: "sdt-hover"
|
|
25380
25696
|
};
|
|
25381
25697
|
const DEFAULT_ALLOWED_PROTOCOLS = ["http", "https", "mailto", "tel", "sms"];
|
|
25382
25698
|
const OPTIONAL_PROTOCOLS = ["ftp", "sftp", "irc"];
|
|
@@ -25781,6 +26097,11 @@ function applySdtContainerStyling(doc2, container, sdt, containerSdt, boundaryOp
|
|
|
25781
26097
|
container.dataset.sdtContainerStart = String(isStart);
|
|
25782
26098
|
container.dataset.sdtContainerEnd = String(isEnd);
|
|
25783
26099
|
container.style.overflow = "visible";
|
|
26100
|
+
if (isStructuredContentMetadata(sdt)) {
|
|
26101
|
+
container.dataset.lockMode = sdt.lockMode || "unlocked";
|
|
26102
|
+
} else if (isStructuredContentMetadata(containerSdt)) {
|
|
26103
|
+
container.dataset.lockMode = containerSdt.lockMode || "unlocked";
|
|
26104
|
+
}
|
|
25784
26105
|
if (boundaryOptions?.widthOverride != null) {
|
|
25785
26106
|
container.style.width = `${boundaryOptions.widthOverride}px`;
|
|
25786
26107
|
}
|
|
@@ -25793,6 +26114,19 @@ function applySdtContainerStyling(doc2, container, sdt, containerSdt, boundaryOp
|
|
|
25793
26114
|
container.appendChild(labelEl);
|
|
25794
26115
|
}
|
|
25795
26116
|
}
|
|
26117
|
+
function shouldRebuildForSdtBoundary(element, boundary) {
|
|
26118
|
+
if (!boundary) {
|
|
26119
|
+
return element.dataset.sdtContainerStart !== void 0;
|
|
26120
|
+
}
|
|
26121
|
+
const startAttr = element.dataset.sdtContainerStart;
|
|
26122
|
+
const endAttr = element.dataset.sdtContainerEnd;
|
|
26123
|
+
const expectedStart = String(boundary.isStart ?? true);
|
|
26124
|
+
const expectedEnd = String(boundary.isEnd ?? true);
|
|
26125
|
+
if (startAttr === void 0 || endAttr === void 0) {
|
|
26126
|
+
return true;
|
|
26127
|
+
}
|
|
26128
|
+
return startAttr !== expectedStart || endAttr !== expectedEnd;
|
|
26129
|
+
}
|
|
25796
26130
|
const TWIPS_PER_INCH$4 = 1440;
|
|
25797
26131
|
const PX_PER_INCH$3 = 96;
|
|
25798
26132
|
const PX_PER_PT = 96 / 72;
|
|
@@ -27271,6 +27605,65 @@ function assertFragmentPmPositions(fragment, _context) {
|
|
|
27271
27605
|
const hasPmEnd = fragment.pmEnd != null;
|
|
27272
27606
|
globalValidationStats.record(hasPmStart, hasPmEnd);
|
|
27273
27607
|
}
|
|
27608
|
+
const SDT_BLOCK_SELECTOR = `.${DOM_CLASS_NAMES.BLOCK_SDT}[data-sdt-id]`;
|
|
27609
|
+
const HOVER_CLASS = DOM_CLASS_NAMES.SDT_HOVER;
|
|
27610
|
+
function sdtElementsById(root2, sdtId) {
|
|
27611
|
+
return root2.querySelectorAll(`.${DOM_CLASS_NAMES.BLOCK_SDT}[data-sdt-id="${sdtId}"]`);
|
|
27612
|
+
}
|
|
27613
|
+
class SdtGroupedHover {
|
|
27614
|
+
constructor() {
|
|
27615
|
+
this.hoveredSdtId = null;
|
|
27616
|
+
this.mount = null;
|
|
27617
|
+
this.onMouseOver = null;
|
|
27618
|
+
this.onMouseLeave = null;
|
|
27619
|
+
}
|
|
27620
|
+
/** Attach hover listeners to the mount element. Safe to call again on remount. */
|
|
27621
|
+
bind(mount2) {
|
|
27622
|
+
this.destroy();
|
|
27623
|
+
this.mount = mount2;
|
|
27624
|
+
this.onMouseOver = (e) => {
|
|
27625
|
+
const target = e.target.closest?.(SDT_BLOCK_SELECTOR);
|
|
27626
|
+
const sdtId = target?.dataset.sdtId ?? null;
|
|
27627
|
+
if (sdtId === this.hoveredSdtId) return;
|
|
27628
|
+
if (this.hoveredSdtId) {
|
|
27629
|
+
sdtElementsById(mount2, this.hoveredSdtId).forEach((el) => el.classList.remove(HOVER_CLASS));
|
|
27630
|
+
}
|
|
27631
|
+
this.hoveredSdtId = sdtId;
|
|
27632
|
+
if (sdtId) {
|
|
27633
|
+
sdtElementsById(mount2, sdtId).forEach((el) => el.classList.add(HOVER_CLASS));
|
|
27634
|
+
}
|
|
27635
|
+
};
|
|
27636
|
+
this.onMouseLeave = () => {
|
|
27637
|
+
if (this.hoveredSdtId) {
|
|
27638
|
+
sdtElementsById(mount2, this.hoveredSdtId).forEach((el) => el.classList.remove(HOVER_CLASS));
|
|
27639
|
+
this.hoveredSdtId = null;
|
|
27640
|
+
}
|
|
27641
|
+
};
|
|
27642
|
+
mount2.addEventListener("mouseover", this.onMouseOver);
|
|
27643
|
+
mount2.addEventListener("mouseleave", this.onMouseLeave);
|
|
27644
|
+
}
|
|
27645
|
+
/** Re-apply hover class after render. New/rebuilt elements lose the class. */
|
|
27646
|
+
reapply() {
|
|
27647
|
+
if (this.hoveredSdtId && this.mount) {
|
|
27648
|
+
sdtElementsById(this.mount, this.hoveredSdtId).forEach((el) => el.classList.add(HOVER_CLASS));
|
|
27649
|
+
}
|
|
27650
|
+
}
|
|
27651
|
+
/** Remove listeners and reset state. */
|
|
27652
|
+
destroy() {
|
|
27653
|
+
if (this.mount) {
|
|
27654
|
+
if (this.onMouseOver) {
|
|
27655
|
+
this.mount.removeEventListener("mouseover", this.onMouseOver);
|
|
27656
|
+
}
|
|
27657
|
+
if (this.onMouseLeave) {
|
|
27658
|
+
this.mount.removeEventListener("mouseleave", this.onMouseLeave);
|
|
27659
|
+
}
|
|
27660
|
+
}
|
|
27661
|
+
this.mount = null;
|
|
27662
|
+
this.onMouseOver = null;
|
|
27663
|
+
this.onMouseLeave = null;
|
|
27664
|
+
this.hoveredSdtId = null;
|
|
27665
|
+
}
|
|
27666
|
+
}
|
|
27274
27667
|
const DEFAULT_PPI = 96;
|
|
27275
27668
|
const DEFAULT_RULER_HEIGHT = 25;
|
|
27276
27669
|
const TICK_SPACING_PX = DEFAULT_PPI / 8;
|
|
@@ -27979,6 +28372,7 @@ class DomPainter {
|
|
|
27979
28372
|
this.onScrollHandler = null;
|
|
27980
28373
|
this.onWindowScrollHandler = null;
|
|
27981
28374
|
this.onResizeHandler = null;
|
|
28375
|
+
this.sdtHover = new SdtGroupedHover();
|
|
27982
28376
|
this.activeCommentId = null;
|
|
27983
28377
|
this.options = options;
|
|
27984
28378
|
this.layoutMode = options.layoutMode ?? "vertical";
|
|
@@ -28244,6 +28638,7 @@ class DomPainter {
|
|
|
28244
28638
|
};
|
|
28245
28639
|
win.addEventListener("resize", this.onResizeHandler);
|
|
28246
28640
|
}
|
|
28641
|
+
this.sdtHover.bind(mount2);
|
|
28247
28642
|
}
|
|
28248
28643
|
computeVirtualMetrics() {
|
|
28249
28644
|
if (!this.currentLayout) return;
|
|
@@ -28386,6 +28781,7 @@ class DomPainter {
|
|
|
28386
28781
|
}
|
|
28387
28782
|
this.changedBlocks.clear();
|
|
28388
28783
|
this.processedLayoutVersion = this.layoutVersion;
|
|
28784
|
+
this.sdtHover.reapply();
|
|
28389
28785
|
}
|
|
28390
28786
|
updateSpacers(start2, end2) {
|
|
28391
28787
|
if (!this.topSpacerEl || !this.bottomSpacerEl) return;
|
|
@@ -28670,6 +29066,7 @@ class DomPainter {
|
|
|
28670
29066
|
this.onScrollHandler = null;
|
|
28671
29067
|
this.onWindowScrollHandler = null;
|
|
28672
29068
|
this.onResizeHandler = null;
|
|
29069
|
+
this.sdtHover.destroy();
|
|
28673
29070
|
this.layoutVersion = 0;
|
|
28674
29071
|
this.processedLayoutVersion = -1;
|
|
28675
29072
|
}
|
|
@@ -28731,7 +29128,9 @@ class DomPainter {
|
|
|
28731
29128
|
if (current) {
|
|
28732
29129
|
existing.delete(key2);
|
|
28733
29130
|
const sdtBoundaryMismatch = shouldRebuildForSdtBoundary(current.element, sdtBoundary);
|
|
28734
|
-
const
|
|
29131
|
+
const newPmStart = fragment.pmStart;
|
|
29132
|
+
const mappingUnreliable = this.currentMapping != null && newPmStart != null && current.element.dataset.pmStart != null && this.currentMapping.map(Number(current.element.dataset.pmStart)) !== newPmStart;
|
|
29133
|
+
const needsRebuild = this.changedBlocks.has(fragment.blockId) || current.signature !== fragmentSignature(fragment, this.blockLookup) || sdtBoundaryMismatch || mappingUnreliable;
|
|
28735
29134
|
if (needsRebuild) {
|
|
28736
29135
|
const replacement = this.renderFragment(fragment, contextBase, sdtBoundary);
|
|
28737
29136
|
pageEl.replaceChild(replacement, current.element);
|
|
@@ -30817,6 +31216,43 @@ class DomPainter {
|
|
|
30817
31216
|
}
|
|
30818
31217
|
return void 0;
|
|
30819
31218
|
};
|
|
31219
|
+
let geoSdtWrapper = null;
|
|
31220
|
+
let geoSdtId = null;
|
|
31221
|
+
let geoSdtWrapperLeft = 0;
|
|
31222
|
+
let geoSdtMaxRight = 0;
|
|
31223
|
+
const closeGeoSdtWrapper = () => {
|
|
31224
|
+
if (geoSdtWrapper) {
|
|
31225
|
+
geoSdtWrapper.style.width = `${geoSdtMaxRight - geoSdtWrapperLeft}px`;
|
|
31226
|
+
el.appendChild(geoSdtWrapper);
|
|
31227
|
+
geoSdtWrapper = null;
|
|
31228
|
+
geoSdtId = null;
|
|
31229
|
+
}
|
|
31230
|
+
};
|
|
31231
|
+
const appendToLineGeo = (elem, runForSdt, elemLeftPx, elemWidthPx) => {
|
|
31232
|
+
const resolved = this.resolveRunSdtId(runForSdt);
|
|
31233
|
+
const thisRunSdtId = resolved?.sdtId ?? null;
|
|
31234
|
+
if (thisRunSdtId !== geoSdtId) {
|
|
31235
|
+
closeGeoSdtWrapper();
|
|
31236
|
+
}
|
|
31237
|
+
if (resolved && this.doc) {
|
|
31238
|
+
if (!geoSdtWrapper) {
|
|
31239
|
+
geoSdtWrapper = this.createInlineSdtWrapper(resolved.sdt);
|
|
31240
|
+
geoSdtId = thisRunSdtId;
|
|
31241
|
+
geoSdtWrapperLeft = elemLeftPx;
|
|
31242
|
+
geoSdtMaxRight = elemLeftPx;
|
|
31243
|
+
geoSdtWrapper.style.position = "absolute";
|
|
31244
|
+
geoSdtWrapper.style.left = `${elemLeftPx}px`;
|
|
31245
|
+
geoSdtWrapper.style.top = "0px";
|
|
31246
|
+
geoSdtWrapper.style.height = `${line.lineHeight}px`;
|
|
31247
|
+
}
|
|
31248
|
+
elem.style.left = `${elemLeftPx - geoSdtWrapperLeft}px`;
|
|
31249
|
+
geoSdtMaxRight = Math.max(geoSdtMaxRight, elemLeftPx + elemWidthPx);
|
|
31250
|
+
this.expandSdtWrapperPmRange(geoSdtWrapper, runForSdt.pmStart, runForSdt.pmEnd);
|
|
31251
|
+
geoSdtWrapper.appendChild(elem);
|
|
31252
|
+
} else {
|
|
31253
|
+
el.appendChild(elem);
|
|
31254
|
+
}
|
|
31255
|
+
};
|
|
30820
31256
|
for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
|
|
30821
31257
|
const baseRun = block.runs[runIndex];
|
|
30822
31258
|
if (!baseRun) continue;
|
|
@@ -30848,7 +31284,7 @@ class DomPainter {
|
|
|
30848
31284
|
if (baseRun.pmStart != null) tabEl.dataset.pmStart = String(baseRun.pmStart);
|
|
30849
31285
|
if (baseRun.pmEnd != null) tabEl.dataset.pmEnd = String(baseRun.pmEnd);
|
|
30850
31286
|
tabEl.dataset.layoutEpoch = String(this.layoutEpoch);
|
|
30851
|
-
|
|
31287
|
+
appendToLineGeo(tabEl, baseRun, tabStartX + indentOffset, actualTabWidth);
|
|
30852
31288
|
cumulativeX = tabEndX;
|
|
30853
31289
|
continue;
|
|
30854
31290
|
}
|
|
@@ -30864,7 +31300,7 @@ class DomPainter {
|
|
|
30864
31300
|
const segWidth = (runSegments2 && runSegments2[0]?.width !== void 0 ? runSegments2[0].width : elem.offsetWidth) ?? 0;
|
|
30865
31301
|
elem.style.position = "absolute";
|
|
30866
31302
|
elem.style.left = `${segX}px`;
|
|
30867
|
-
|
|
31303
|
+
appendToLineGeo(elem, baseRun, segX, segWidth);
|
|
30868
31304
|
cumulativeX = baseSegX + segWidth;
|
|
30869
31305
|
}
|
|
30870
31306
|
continue;
|
|
@@ -30887,7 +31323,7 @@ class DomPainter {
|
|
|
30887
31323
|
const segWidth = (runSegments2 && runSegments2[0]?.width !== void 0 ? runSegments2[0].width : 0) ?? 0;
|
|
30888
31324
|
elem.style.position = "absolute";
|
|
30889
31325
|
elem.style.left = `${segX}px`;
|
|
30890
|
-
|
|
31326
|
+
appendToLineGeo(elem, baseRun, segX, segWidth);
|
|
30891
31327
|
cumulativeX = baseSegX + segWidth;
|
|
30892
31328
|
}
|
|
30893
31329
|
continue;
|
|
@@ -30922,7 +31358,7 @@ class DomPainter {
|
|
|
30922
31358
|
const xPos = baseX + indentOffset;
|
|
30923
31359
|
elem.style.position = "absolute";
|
|
30924
31360
|
elem.style.left = `${xPos}px`;
|
|
30925
|
-
|
|
31361
|
+
appendToLineGeo(elem, segmentRun, xPos, segment.width ?? 0);
|
|
30926
31362
|
let width = segment.width ?? 0;
|
|
30927
31363
|
if (width <= 0 && this.doc) {
|
|
30928
31364
|
const measureEl = elem.cloneNode(true);
|
|
@@ -30934,9 +31370,13 @@ class DomPainter {
|
|
|
30934
31370
|
this.doc.body.removeChild(measureEl);
|
|
30935
31371
|
}
|
|
30936
31372
|
cumulativeX = baseX + width;
|
|
31373
|
+
if (geoSdtWrapper) {
|
|
31374
|
+
geoSdtMaxRight = Math.max(geoSdtMaxRight, xPos + width);
|
|
31375
|
+
}
|
|
30937
31376
|
}
|
|
30938
31377
|
});
|
|
30939
31378
|
}
|
|
31379
|
+
closeGeoSdtWrapper();
|
|
30940
31380
|
} else {
|
|
30941
31381
|
let currentInlineSdtWrapper = null;
|
|
30942
31382
|
let currentInlineSdtId = null;
|
|
@@ -30948,12 +31388,12 @@ class DomPainter {
|
|
|
30948
31388
|
}
|
|
30949
31389
|
};
|
|
30950
31390
|
runsForLine.forEach((run) => {
|
|
30951
|
-
const
|
|
30952
|
-
const
|
|
30953
|
-
const runSdtId = isInlineSdt && runSdt?.id ? String(runSdt.id) : null;
|
|
31391
|
+
const resolved = this.resolveRunSdtId(run);
|
|
31392
|
+
const runSdtId = resolved?.sdtId ?? null;
|
|
30954
31393
|
if (runSdtId !== currentInlineSdtId) {
|
|
30955
31394
|
closeCurrentWrapper();
|
|
30956
31395
|
}
|
|
31396
|
+
let elem = null;
|
|
30957
31397
|
if (run.kind === "tab") {
|
|
30958
31398
|
const tabEl = this.doc.createElement("span");
|
|
30959
31399
|
tabEl.classList.add("superdoc-tab");
|
|
@@ -30974,39 +31414,20 @@ class DomPainter {
|
|
|
30974
31414
|
if (run.pmStart != null) tabEl.dataset.pmStart = String(run.pmStart);
|
|
30975
31415
|
if (run.pmEnd != null) tabEl.dataset.pmEnd = String(run.pmEnd);
|
|
30976
31416
|
tabEl.dataset.layoutEpoch = String(this.layoutEpoch);
|
|
30977
|
-
|
|
30978
|
-
|
|
31417
|
+
elem = tabEl;
|
|
31418
|
+
} else {
|
|
31419
|
+
elem = this.renderRun(run, context, trackedConfig);
|
|
30979
31420
|
}
|
|
30980
|
-
const elem = this.renderRun(run, context, trackedConfig);
|
|
30981
31421
|
if (elem) {
|
|
30982
31422
|
if (styleId) {
|
|
30983
31423
|
elem.setAttribute("styleid", styleId);
|
|
30984
31424
|
}
|
|
30985
|
-
if (
|
|
31425
|
+
if (resolved && this.doc) {
|
|
30986
31426
|
if (!currentInlineSdtWrapper) {
|
|
30987
|
-
currentInlineSdtWrapper = this.
|
|
30988
|
-
currentInlineSdtWrapper.className = DOM_CLASS_NAMES.INLINE_SDT_WRAPPER;
|
|
30989
|
-
currentInlineSdtWrapper.dataset.layoutEpoch = String(this.layoutEpoch);
|
|
31427
|
+
currentInlineSdtWrapper = this.createInlineSdtWrapper(resolved.sdt);
|
|
30990
31428
|
currentInlineSdtId = runSdtId;
|
|
30991
|
-
this.applySdtDataset(currentInlineSdtWrapper, runSdt);
|
|
30992
|
-
const alias = runSdt?.alias || "Inline content";
|
|
30993
|
-
const labelEl = this.doc.createElement("span");
|
|
30994
|
-
labelEl.className = `${DOM_CLASS_NAMES.INLINE_SDT_WRAPPER}__label`;
|
|
30995
|
-
labelEl.textContent = alias;
|
|
30996
|
-
currentInlineSdtWrapper.appendChild(labelEl);
|
|
30997
|
-
}
|
|
30998
|
-
const wrapperPmStart = currentInlineSdtWrapper.dataset.pmStart;
|
|
30999
|
-
const wrapperPmEnd = currentInlineSdtWrapper.dataset.pmEnd;
|
|
31000
|
-
if (run.pmStart != null) {
|
|
31001
|
-
if (!wrapperPmStart || run.pmStart < parseInt(wrapperPmStart, 10)) {
|
|
31002
|
-
currentInlineSdtWrapper.dataset.pmStart = String(run.pmStart);
|
|
31003
|
-
}
|
|
31004
|
-
}
|
|
31005
|
-
if (run.pmEnd != null) {
|
|
31006
|
-
if (!wrapperPmEnd || run.pmEnd > parseInt(wrapperPmEnd, 10)) {
|
|
31007
|
-
currentInlineSdtWrapper.dataset.pmEnd = String(run.pmEnd);
|
|
31008
|
-
}
|
|
31009
31429
|
}
|
|
31430
|
+
this.expandSdtWrapperPmRange(currentInlineSdtWrapper, run.pmStart, run.pmEnd);
|
|
31010
31431
|
currentInlineSdtWrapper.appendChild(elem);
|
|
31011
31432
|
} else {
|
|
31012
31433
|
el.appendChild(elem);
|
|
@@ -31183,6 +31604,7 @@ class DomPainter {
|
|
|
31183
31604
|
"sdtScope",
|
|
31184
31605
|
"sdtTag",
|
|
31185
31606
|
"sdtAlias",
|
|
31607
|
+
"lockMode",
|
|
31186
31608
|
"sdtSectionTitle",
|
|
31187
31609
|
"sdtSectionType",
|
|
31188
31610
|
"sdtSectionLocked",
|
|
@@ -31207,6 +31629,49 @@ class DomPainter {
|
|
|
31207
31629
|
el.dataset[key2] = String(value);
|
|
31208
31630
|
}
|
|
31209
31631
|
}
|
|
31632
|
+
/**
|
|
31633
|
+
* Resolve the inline SDT id from a run, or null if the run is not inside an inline SDT.
|
|
31634
|
+
*/
|
|
31635
|
+
resolveRunSdtId(run) {
|
|
31636
|
+
const sdt = run.sdt;
|
|
31637
|
+
if (sdt?.type === "structuredContent" && sdt?.scope === "inline" && sdt?.id) {
|
|
31638
|
+
return { sdtId: String(sdt.id), sdt };
|
|
31639
|
+
}
|
|
31640
|
+
return null;
|
|
31641
|
+
}
|
|
31642
|
+
/**
|
|
31643
|
+
* Create an inline SDT wrapper `<span>` with className, layoutEpoch, dataset, and label.
|
|
31644
|
+
* Shared by both the geometry and run-based rendering paths.
|
|
31645
|
+
*/
|
|
31646
|
+
createInlineSdtWrapper(sdt) {
|
|
31647
|
+
const wrapper = this.doc.createElement("span");
|
|
31648
|
+
wrapper.className = DOM_CLASS_NAMES.INLINE_SDT_WRAPPER;
|
|
31649
|
+
wrapper.dataset.layoutEpoch = String(this.layoutEpoch);
|
|
31650
|
+
this.applySdtDataset(wrapper, sdt);
|
|
31651
|
+
const alias = sdt?.alias || "Inline content";
|
|
31652
|
+
const labelEl = this.doc.createElement("span");
|
|
31653
|
+
labelEl.className = `${DOM_CLASS_NAMES.INLINE_SDT_WRAPPER}__label`;
|
|
31654
|
+
labelEl.textContent = alias;
|
|
31655
|
+
wrapper.appendChild(labelEl);
|
|
31656
|
+
return wrapper;
|
|
31657
|
+
}
|
|
31658
|
+
/**
|
|
31659
|
+
* Expand the PM position range tracked on an SDT wrapper to include a new run's range.
|
|
31660
|
+
*/
|
|
31661
|
+
expandSdtWrapperPmRange(wrapper, pmStart, pmEnd) {
|
|
31662
|
+
if (pmStart != null) {
|
|
31663
|
+
const cur = wrapper.dataset.pmStart;
|
|
31664
|
+
if (!cur || pmStart < parseInt(cur, 10)) {
|
|
31665
|
+
wrapper.dataset.pmStart = String(pmStart);
|
|
31666
|
+
}
|
|
31667
|
+
}
|
|
31668
|
+
if (pmEnd != null) {
|
|
31669
|
+
const cur = wrapper.dataset.pmEnd;
|
|
31670
|
+
if (!cur || pmEnd > parseInt(cur, 10)) {
|
|
31671
|
+
wrapper.dataset.pmEnd = String(pmEnd);
|
|
31672
|
+
}
|
|
31673
|
+
}
|
|
31674
|
+
}
|
|
31210
31675
|
/**
|
|
31211
31676
|
* Applies SDT (Structured Document Tag) metadata to an element's dataset as data-sdt-* attributes.
|
|
31212
31677
|
* Supports field annotations, structured content, document sections, and doc parts.
|
|
@@ -31234,6 +31699,7 @@ class DomPainter {
|
|
|
31234
31699
|
this.setDatasetString(el, "sdtScope", metadata.scope);
|
|
31235
31700
|
this.setDatasetString(el, "sdtTag", metadata.tag);
|
|
31236
31701
|
this.setDatasetString(el, "sdtAlias", metadata.alias);
|
|
31702
|
+
this.setDatasetString(el, "lockMode", metadata.lockMode || "unlocked");
|
|
31237
31703
|
} else if (metadata.type === "documentSection") {
|
|
31238
31704
|
this.setDatasetString(el, "sdtSectionTitle", metadata.title);
|
|
31239
31705
|
this.setDatasetString(el, "sdtSectionType", metadata.sectionType);
|
|
@@ -31322,17 +31788,6 @@ const computeSdtBoundaries = (fragments, blockLookup) => {
|
|
|
31322
31788
|
}
|
|
31323
31789
|
return boundaries;
|
|
31324
31790
|
};
|
|
31325
|
-
const shouldRebuildForSdtBoundary = (element, boundary) => {
|
|
31326
|
-
if (!boundary) return false;
|
|
31327
|
-
const startAttr = element.dataset.sdtContainerStart;
|
|
31328
|
-
const endAttr = element.dataset.sdtContainerEnd;
|
|
31329
|
-
const expectedStart = String(boundary.isStart ?? true);
|
|
31330
|
-
const expectedEnd = String(boundary.isEnd ?? true);
|
|
31331
|
-
if (startAttr === void 0 || endAttr === void 0) {
|
|
31332
|
-
return true;
|
|
31333
|
-
}
|
|
31334
|
-
return startAttr !== expectedStart || endAttr !== expectedEnd;
|
|
31335
|
-
};
|
|
31336
31791
|
const fragmentKey = (fragment) => {
|
|
31337
31792
|
if (fragment.kind === "para") {
|
|
31338
31793
|
return `para:${fragment.blockId}:${fragment.fromLine}:${fragment.toLine}`;
|
|
@@ -40777,6 +41232,7 @@ function normalizeStructuredContentMetadata(nodeType, attrs) {
|
|
|
40777
41232
|
id: toNullableString(attrs.id),
|
|
40778
41233
|
tag: toOptionalString(attrs.tag),
|
|
40779
41234
|
alias: toOptionalString(attrs.alias),
|
|
41235
|
+
lockMode: attrs.lockMode,
|
|
40780
41236
|
sdtPr: attrs.sdtPr
|
|
40781
41237
|
};
|
|
40782
41238
|
}
|
|
@@ -41601,7 +42057,8 @@ function tabNodeToRun({
|
|
|
41601
42057
|
positions,
|
|
41602
42058
|
tabOrdinal,
|
|
41603
42059
|
paragraphAttrs,
|
|
41604
|
-
inheritedMarks
|
|
42060
|
+
inheritedMarks,
|
|
42061
|
+
sdtMetadata
|
|
41605
42062
|
}) {
|
|
41606
42063
|
const pos = positions.get(node);
|
|
41607
42064
|
if (!pos) return null;
|
|
@@ -41617,6 +42074,9 @@ function tabNodeToRun({
|
|
|
41617
42074
|
indent,
|
|
41618
42075
|
leader: node.attrs?.leader ?? null
|
|
41619
42076
|
};
|
|
42077
|
+
if (sdtMetadata) {
|
|
42078
|
+
run.sdt = sdtMetadata;
|
|
42079
|
+
}
|
|
41620
42080
|
const marks = [...node.marks ?? [], ...inheritedMarks ?? []];
|
|
41621
42081
|
if (marks.length > 0) {
|
|
41622
42082
|
applyMarksToRun(run, marks);
|
|
@@ -64201,7 +64661,8 @@ class PresentationEditor extends EventEmitter {
|
|
|
64201
64661
|
}
|
|
64202
64662
|
const activeEditor = this.getActiveEditor();
|
|
64203
64663
|
const hasFocus = activeEditor?.view?.hasFocus?.() ?? false;
|
|
64204
|
-
|
|
64664
|
+
const slashMenuOpen = activeEditor?.state ? !!SlashMenuPluginKey.getState(activeEditor.state)?.open : false;
|
|
64665
|
+
if (!hasFocus && !slashMenuOpen) {
|
|
64205
64666
|
try {
|
|
64206
64667
|
this.#clearSelectedFieldAnnotationClass();
|
|
64207
64668
|
this.#localSelectionLayer.innerHTML = "";
|
|
@@ -66438,300 +66899,6 @@ const processAiHighlights = (editor, doc2, highlightColor, customClass = null) =
|
|
|
66438
66899
|
});
|
|
66439
66900
|
return { decorations };
|
|
66440
66901
|
};
|
|
66441
|
-
function getEditorSurfaceElement(editor) {
|
|
66442
|
-
if (!editor) return null;
|
|
66443
|
-
if (typeof editor.hitTest === "function" && editor.element instanceof HTMLElement) {
|
|
66444
|
-
return editor.element;
|
|
66445
|
-
}
|
|
66446
|
-
return editor.presentationEditor?.element ?? editor.view?.dom ?? editor.options?.element ?? null;
|
|
66447
|
-
}
|
|
66448
|
-
function getSurfaceRelativePoint(editor, eventLocation = {}) {
|
|
66449
|
-
const surface = getEditorSurfaceElement(editor);
|
|
66450
|
-
if (!surface) return null;
|
|
66451
|
-
const rect = surface.getBoundingClientRect();
|
|
66452
|
-
let left2;
|
|
66453
|
-
let top2;
|
|
66454
|
-
if (typeof eventLocation.clientX === "number" && typeof eventLocation.clientY === "number") {
|
|
66455
|
-
left2 = eventLocation.clientX - rect.left;
|
|
66456
|
-
top2 = eventLocation.clientY - rect.top;
|
|
66457
|
-
} else if (editor?.state?.selection) {
|
|
66458
|
-
const selectionFrom = editor.state.selection.from;
|
|
66459
|
-
const coords = editor.coordsAtPos?.(selectionFrom);
|
|
66460
|
-
if (coords) {
|
|
66461
|
-
left2 = coords.left - rect.left;
|
|
66462
|
-
top2 = coords.top - rect.top;
|
|
66463
|
-
}
|
|
66464
|
-
}
|
|
66465
|
-
if (!Number.isFinite(left2) || !Number.isFinite(top2)) {
|
|
66466
|
-
return null;
|
|
66467
|
-
}
|
|
66468
|
-
return { left: left2, top: top2 };
|
|
66469
|
-
}
|
|
66470
|
-
function findContainingBlockAncestor(element) {
|
|
66471
|
-
if (!element) return null;
|
|
66472
|
-
let current = element.parentElement;
|
|
66473
|
-
while (current && current !== document.body && current !== document.documentElement) {
|
|
66474
|
-
try {
|
|
66475
|
-
const style2 = window.getComputedStyle(current);
|
|
66476
|
-
const transform = style2.transform;
|
|
66477
|
-
const filter = style2.filter;
|
|
66478
|
-
const backdropFilter = style2.backdropFilter || style2.webkitBackdropFilter;
|
|
66479
|
-
const perspective = style2.perspective;
|
|
66480
|
-
const willChange = style2.willChange;
|
|
66481
|
-
const contain = style2.contain;
|
|
66482
|
-
if (transform && transform !== "none") {
|
|
66483
|
-
return current;
|
|
66484
|
-
}
|
|
66485
|
-
if (filter && filter !== "none") {
|
|
66486
|
-
return current;
|
|
66487
|
-
}
|
|
66488
|
-
if (backdropFilter && backdropFilter !== "none") {
|
|
66489
|
-
return current;
|
|
66490
|
-
}
|
|
66491
|
-
if (perspective && perspective !== "none") {
|
|
66492
|
-
return current;
|
|
66493
|
-
}
|
|
66494
|
-
if (willChange && willChange !== "auto") {
|
|
66495
|
-
const values = willChange.split(",").map((v) => v.trim());
|
|
66496
|
-
if (values.includes("transform") || values.includes("perspective")) {
|
|
66497
|
-
return current;
|
|
66498
|
-
}
|
|
66499
|
-
}
|
|
66500
|
-
if (contain && /paint|layout|strict|content/.test(contain)) {
|
|
66501
|
-
return current;
|
|
66502
|
-
}
|
|
66503
|
-
} catch (error) {
|
|
66504
|
-
console.warn("SlashMenu: Failed to get computed style for element", current, error);
|
|
66505
|
-
}
|
|
66506
|
-
current = current.parentElement;
|
|
66507
|
-
}
|
|
66508
|
-
return null;
|
|
66509
|
-
}
|
|
66510
|
-
const SlashMenuPluginKey = new superEditor_converter.PluginKey("slashMenu");
|
|
66511
|
-
const MENU_OFFSET_X = 100;
|
|
66512
|
-
const MENU_OFFSET_Y = 28;
|
|
66513
|
-
const CONTEXT_MENU_OFFSET_X = 10;
|
|
66514
|
-
const CONTEXT_MENU_OFFSET_Y = 10;
|
|
66515
|
-
const SLASH_COOLDOWN_MS = 5e3;
|
|
66516
|
-
const SlashMenu = Extension.create({
|
|
66517
|
-
name: "slashMenu",
|
|
66518
|
-
/**
|
|
66519
|
-
* Initialize default options for the SlashMenu extension
|
|
66520
|
-
* @returns {SlashMenuOptions} Empty options object (configuration is inherited from editor options)
|
|
66521
|
-
*/
|
|
66522
|
-
addOptions() {
|
|
66523
|
-
return {};
|
|
66524
|
-
},
|
|
66525
|
-
addPmPlugins() {
|
|
66526
|
-
const editor = this.editor;
|
|
66527
|
-
if (editor.options?.isHeadless) {
|
|
66528
|
-
return [];
|
|
66529
|
-
}
|
|
66530
|
-
let slashCooldown = false;
|
|
66531
|
-
let slashCooldownTimeout = null;
|
|
66532
|
-
const isMenuDisabled = () => Boolean(editor.options?.disableContextMenu);
|
|
66533
|
-
const ensureStateShape = (value = {}) => ({
|
|
66534
|
-
open: false,
|
|
66535
|
-
selected: null,
|
|
66536
|
-
anchorPos: null,
|
|
66537
|
-
menuPosition: null,
|
|
66538
|
-
disabled: isMenuDisabled(),
|
|
66539
|
-
...value
|
|
66540
|
-
});
|
|
66541
|
-
const slashMenuPlugin = new superEditor_converter.Plugin({
|
|
66542
|
-
key: SlashMenuPluginKey,
|
|
66543
|
-
state: {
|
|
66544
|
-
init: () => ensureStateShape(),
|
|
66545
|
-
/**
|
|
66546
|
-
* Apply transaction to update plugin state
|
|
66547
|
-
* Handles state transitions based on transaction metadata:
|
|
66548
|
-
* - 'open': Opens menu at specified position or cursor location
|
|
66549
|
-
* - 'select': Updates the selected menu item
|
|
66550
|
-
* - 'close': Closes the menu and clears anchor position
|
|
66551
|
-
* - 'updatePosition': Triggers menu position recalculation (no-op in apply)
|
|
66552
|
-
*
|
|
66553
|
-
* @param {import('prosemirror-state').Transaction} tr - The transaction
|
|
66554
|
-
* @param {SlashMenuState} value - Previous plugin state
|
|
66555
|
-
* @returns {SlashMenuState} New plugin state
|
|
66556
|
-
*/
|
|
66557
|
-
apply(tr, value) {
|
|
66558
|
-
const meta = tr.getMeta(SlashMenuPluginKey);
|
|
66559
|
-
const disabled = isMenuDisabled();
|
|
66560
|
-
if (disabled) {
|
|
66561
|
-
if (value.open) {
|
|
66562
|
-
editor.emit("slashMenu:close");
|
|
66563
|
-
}
|
|
66564
|
-
return ensureStateShape({ disabled: true });
|
|
66565
|
-
}
|
|
66566
|
-
if (!meta) {
|
|
66567
|
-
if (value.disabled !== disabled) {
|
|
66568
|
-
return ensureStateShape({ ...value, disabled });
|
|
66569
|
-
}
|
|
66570
|
-
return value;
|
|
66571
|
-
}
|
|
66572
|
-
switch (meta.type) {
|
|
66573
|
-
case "open": {
|
|
66574
|
-
if (typeof meta.pos !== "number" || meta.pos < 0 || meta.pos > tr.doc.content.size) {
|
|
66575
|
-
console.warn("SlashMenu: Invalid position", meta.pos);
|
|
66576
|
-
return ensureStateShape(value);
|
|
66577
|
-
}
|
|
66578
|
-
let left2 = 0;
|
|
66579
|
-
let top2 = 0;
|
|
66580
|
-
let isContextMenu = false;
|
|
66581
|
-
if (typeof meta.clientX === "number" && typeof meta.clientY === "number") {
|
|
66582
|
-
left2 = meta.clientX;
|
|
66583
|
-
top2 = meta.clientY;
|
|
66584
|
-
isContextMenu = true;
|
|
66585
|
-
} else {
|
|
66586
|
-
const relativePoint = getSurfaceRelativePoint(editor, meta);
|
|
66587
|
-
if (relativePoint) {
|
|
66588
|
-
const surface = editor.presentationEditor?.element ?? editor.view?.dom ?? editor.options?.element;
|
|
66589
|
-
if (surface) {
|
|
66590
|
-
try {
|
|
66591
|
-
const rect = surface.getBoundingClientRect();
|
|
66592
|
-
left2 = rect.left + relativePoint.left;
|
|
66593
|
-
top2 = rect.top + relativePoint.top;
|
|
66594
|
-
} catch (error) {
|
|
66595
|
-
console.warn("SlashMenu: Failed to get surface bounds", error);
|
|
66596
|
-
return ensureStateShape(value);
|
|
66597
|
-
}
|
|
66598
|
-
}
|
|
66599
|
-
}
|
|
66600
|
-
}
|
|
66601
|
-
const menuSurface = editor.presentationEditor?.element ?? editor.view?.dom ?? editor.options?.element;
|
|
66602
|
-
const containingBlock = findContainingBlockAncestor(menuSurface);
|
|
66603
|
-
if (containingBlock) {
|
|
66604
|
-
try {
|
|
66605
|
-
const cbRect = containingBlock.getBoundingClientRect();
|
|
66606
|
-
left2 -= cbRect.left;
|
|
66607
|
-
top2 -= cbRect.top;
|
|
66608
|
-
left2 += containingBlock.scrollLeft || 0;
|
|
66609
|
-
top2 += containingBlock.scrollTop || 0;
|
|
66610
|
-
} catch (error) {
|
|
66611
|
-
console.warn("SlashMenu: Failed to adjust for containing block", error);
|
|
66612
|
-
}
|
|
66613
|
-
}
|
|
66614
|
-
const offsetX = isContextMenu ? CONTEXT_MENU_OFFSET_X : MENU_OFFSET_X;
|
|
66615
|
-
const offsetY = isContextMenu ? CONTEXT_MENU_OFFSET_Y : MENU_OFFSET_Y;
|
|
66616
|
-
const menuPosition = {
|
|
66617
|
-
left: `${left2 + offsetX}px`,
|
|
66618
|
-
top: `${top2 + offsetY}px`
|
|
66619
|
-
};
|
|
66620
|
-
const newState = {
|
|
66621
|
-
...value,
|
|
66622
|
-
open: true,
|
|
66623
|
-
anchorPos: meta.pos,
|
|
66624
|
-
menuPosition
|
|
66625
|
-
};
|
|
66626
|
-
editor.emit("slashMenu:open", { menuPosition });
|
|
66627
|
-
return ensureStateShape(newState);
|
|
66628
|
-
}
|
|
66629
|
-
case "select": {
|
|
66630
|
-
return ensureStateShape({ ...value, selected: meta.id });
|
|
66631
|
-
}
|
|
66632
|
-
case "close": {
|
|
66633
|
-
editor.emit("slashMenu:close");
|
|
66634
|
-
return ensureStateShape({ ...value, open: false, anchorPos: null });
|
|
66635
|
-
}
|
|
66636
|
-
default:
|
|
66637
|
-
return ensureStateShape({ ...value, disabled });
|
|
66638
|
-
}
|
|
66639
|
-
}
|
|
66640
|
-
},
|
|
66641
|
-
/**
|
|
66642
|
-
* Create view plugin to handle window event listeners
|
|
66643
|
-
* @param {import('prosemirror-view').EditorView} editorView - The ProseMirror editor view
|
|
66644
|
-
* @returns {Object} View plugin with destroy method
|
|
66645
|
-
*/
|
|
66646
|
-
view(editorView) {
|
|
66647
|
-
const updatePosition2 = () => {
|
|
66648
|
-
if (isMenuDisabled()) return;
|
|
66649
|
-
const state = SlashMenuPluginKey.getState(editorView.state);
|
|
66650
|
-
if (state.open) {
|
|
66651
|
-
editorView.dispatch(
|
|
66652
|
-
editorView.state.tr.setMeta(SlashMenuPluginKey, {
|
|
66653
|
-
type: "updatePosition"
|
|
66654
|
-
})
|
|
66655
|
-
);
|
|
66656
|
-
}
|
|
66657
|
-
};
|
|
66658
|
-
window.addEventListener("scroll", updatePosition2, true);
|
|
66659
|
-
window.addEventListener("resize", updatePosition2);
|
|
66660
|
-
return {
|
|
66661
|
-
destroy() {
|
|
66662
|
-
window.removeEventListener("scroll", updatePosition2, true);
|
|
66663
|
-
window.removeEventListener("resize", updatePosition2);
|
|
66664
|
-
if (slashCooldownTimeout) {
|
|
66665
|
-
clearTimeout(slashCooldownTimeout);
|
|
66666
|
-
slashCooldownTimeout = null;
|
|
66667
|
-
}
|
|
66668
|
-
}
|
|
66669
|
-
};
|
|
66670
|
-
},
|
|
66671
|
-
props: {
|
|
66672
|
-
/**
|
|
66673
|
-
* Handle keyboard events to open/close the slash menu
|
|
66674
|
-
* - '/': Opens menu at cursor if conditions are met (in paragraph, after space/start)
|
|
66675
|
-
* - 'Escape' or 'ArrowLeft': Closes menu and restores cursor position
|
|
66676
|
-
*
|
|
66677
|
-
* @param {import('prosemirror-view').EditorView} view - The ProseMirror editor view
|
|
66678
|
-
* @param {KeyboardEvent} event - The keyboard event
|
|
66679
|
-
* @returns {boolean} True if the event was handled, false otherwise
|
|
66680
|
-
*/
|
|
66681
|
-
handleKeyDown(view, event) {
|
|
66682
|
-
if (isMenuDisabled()) {
|
|
66683
|
-
return false;
|
|
66684
|
-
}
|
|
66685
|
-
const pluginState = this.getState(view.state);
|
|
66686
|
-
if (event.key === "/" && slashCooldown) {
|
|
66687
|
-
return false;
|
|
66688
|
-
}
|
|
66689
|
-
if (event.key === "/" && !pluginState.open) {
|
|
66690
|
-
const { $cursor } = view.state.selection;
|
|
66691
|
-
if (!$cursor) return false;
|
|
66692
|
-
const isParagraph = $cursor.parent.type.name === "paragraph";
|
|
66693
|
-
if (!isParagraph) return false;
|
|
66694
|
-
const textBefore = $cursor.parent.textContent.slice(0, $cursor.parentOffset);
|
|
66695
|
-
const isEmptyOrAfterSpace = !textBefore || textBefore.endsWith(" ");
|
|
66696
|
-
if (!isEmptyOrAfterSpace) return false;
|
|
66697
|
-
event.preventDefault();
|
|
66698
|
-
slashCooldown = true;
|
|
66699
|
-
if (slashCooldownTimeout) clearTimeout(slashCooldownTimeout);
|
|
66700
|
-
slashCooldownTimeout = setTimeout(() => {
|
|
66701
|
-
slashCooldown = false;
|
|
66702
|
-
slashCooldownTimeout = null;
|
|
66703
|
-
}, SLASH_COOLDOWN_MS);
|
|
66704
|
-
view.dispatch(
|
|
66705
|
-
view.state.tr.setMeta(SlashMenuPluginKey, {
|
|
66706
|
-
type: "open",
|
|
66707
|
-
pos: $cursor.pos
|
|
66708
|
-
})
|
|
66709
|
-
);
|
|
66710
|
-
return true;
|
|
66711
|
-
}
|
|
66712
|
-
if (pluginState.open && (event.key === "Escape" || event.key === "ArrowLeft")) {
|
|
66713
|
-
const { anchorPos } = pluginState;
|
|
66714
|
-
view.dispatch(
|
|
66715
|
-
view.state.tr.setMeta(SlashMenuPluginKey, {
|
|
66716
|
-
type: "close"
|
|
66717
|
-
})
|
|
66718
|
-
);
|
|
66719
|
-
if (anchorPos !== null) {
|
|
66720
|
-
const tr = view.state.tr.setSelection(
|
|
66721
|
-
view.state.selection.constructor.near(view.state.doc.resolve(anchorPos))
|
|
66722
|
-
);
|
|
66723
|
-
view.dispatch(tr);
|
|
66724
|
-
view.focus();
|
|
66725
|
-
}
|
|
66726
|
-
return true;
|
|
66727
|
-
}
|
|
66728
|
-
return false;
|
|
66729
|
-
}
|
|
66730
|
-
}
|
|
66731
|
-
});
|
|
66732
|
-
return [slashMenuPlugin];
|
|
66733
|
-
}
|
|
66734
|
-
});
|
|
66735
66902
|
class StructuredContentViewBase {
|
|
66736
66903
|
node;
|
|
66737
66904
|
view;
|
|
@@ -66871,6 +67038,20 @@ class StructuredContentViewBase {
|
|
|
66871
67038
|
dragHandle.append(textElement);
|
|
66872
67039
|
return dragHandle;
|
|
66873
67040
|
}
|
|
67041
|
+
isContentLocked() {
|
|
67042
|
+
const lockMode = this.node.attrs.lockMode;
|
|
67043
|
+
return lockMode === "contentLocked" || lockMode === "sdtContentLocked";
|
|
67044
|
+
}
|
|
67045
|
+
isSdtLocked() {
|
|
67046
|
+
const lockMode = this.node.attrs.lockMode;
|
|
67047
|
+
return lockMode === "sdtLocked" || lockMode === "sdtContentLocked";
|
|
67048
|
+
}
|
|
67049
|
+
updateContentEditability() {
|
|
67050
|
+
if (this.dom) {
|
|
67051
|
+
this.dom.classList.toggle("sd-structured-content--content-locked", this.isContentLocked());
|
|
67052
|
+
this.dom.classList.toggle("sd-structured-content--sdt-locked", this.isSdtLocked());
|
|
67053
|
+
}
|
|
67054
|
+
}
|
|
66874
67055
|
onDragStart(event) {
|
|
66875
67056
|
const { view } = this.editor;
|
|
66876
67057
|
const target = event.target;
|
|
@@ -66926,10 +67107,12 @@ class StructuredContentInlineView extends StructuredContentViewBase {
|
|
|
66926
67107
|
element.prepend(dragHandle);
|
|
66927
67108
|
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
66928
67109
|
this.root = element;
|
|
67110
|
+
this.updateContentEditability();
|
|
66929
67111
|
}
|
|
66930
67112
|
updateView() {
|
|
66931
67113
|
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
66932
67114
|
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
67115
|
+
this.updateContentEditability();
|
|
66933
67116
|
}
|
|
66934
67117
|
update(node, decorations, innerDecorations) {
|
|
66935
67118
|
const result = super.update(node, decorations, innerDecorations);
|
|
@@ -66938,6 +67121,157 @@ class StructuredContentInlineView extends StructuredContentViewBase {
|
|
|
66938
67121
|
return true;
|
|
66939
67122
|
}
|
|
66940
67123
|
}
|
|
67124
|
+
const STRUCTURED_CONTENT_LOCK_KEY = new superEditor_converter.PluginKey("structuredContentLock");
|
|
67125
|
+
function collectSDTNodes(doc2) {
|
|
67126
|
+
const sdtNodes = [];
|
|
67127
|
+
doc2.descendants((node, pos) => {
|
|
67128
|
+
if (node.type.name === "structuredContent" || node.type.name === "structuredContentBlock") {
|
|
67129
|
+
sdtNodes.push({
|
|
67130
|
+
type: node.type.name,
|
|
67131
|
+
lockMode: node.attrs.lockMode,
|
|
67132
|
+
pos,
|
|
67133
|
+
end: pos + node.nodeSize
|
|
67134
|
+
});
|
|
67135
|
+
}
|
|
67136
|
+
});
|
|
67137
|
+
return sdtNodes;
|
|
67138
|
+
}
|
|
67139
|
+
function checkLockViolation(sdtNodes, from3, to) {
|
|
67140
|
+
for (const sdt of sdtNodes) {
|
|
67141
|
+
const overlaps = from3 < sdt.end && to > sdt.pos;
|
|
67142
|
+
if (!overlaps) continue;
|
|
67143
|
+
const containsSDT = from3 <= sdt.pos && to >= sdt.end;
|
|
67144
|
+
const insideSDT = from3 >= sdt.pos && to <= sdt.end;
|
|
67145
|
+
const crossesStart = from3 < sdt.pos && to > sdt.pos && to < sdt.end;
|
|
67146
|
+
const crossesEnd = from3 > sdt.pos && from3 < sdt.end && to > sdt.end;
|
|
67147
|
+
const wouldDamageWrapper = containsSDT || crossesStart || crossesEnd;
|
|
67148
|
+
const wouldModifyContent = insideSDT && !containsSDT;
|
|
67149
|
+
const isSdtLocked = sdt.lockMode === "sdtLocked" || sdt.lockMode === "sdtContentLocked";
|
|
67150
|
+
const isContentLocked = sdt.lockMode === "contentLocked" || sdt.lockMode === "sdtContentLocked";
|
|
67151
|
+
if (isSdtLocked && wouldDamageWrapper) {
|
|
67152
|
+
return { blocked: true, reason: `Cannot delete SDT wrapper (${sdt.lockMode})` };
|
|
67153
|
+
}
|
|
67154
|
+
if (isContentLocked && wouldModifyContent) {
|
|
67155
|
+
return { blocked: true, reason: `Cannot modify content (${sdt.lockMode})` };
|
|
67156
|
+
}
|
|
67157
|
+
}
|
|
67158
|
+
return { blocked: false };
|
|
67159
|
+
}
|
|
67160
|
+
function createStructuredContentLockPlugin() {
|
|
67161
|
+
return new superEditor_converter.Plugin({
|
|
67162
|
+
key: STRUCTURED_CONTENT_LOCK_KEY,
|
|
67163
|
+
state: {
|
|
67164
|
+
init(_2, editorState) {
|
|
67165
|
+
return collectSDTNodes(editorState.doc);
|
|
67166
|
+
},
|
|
67167
|
+
apply(tr, cachedSDTNodes, _oldState, newState) {
|
|
67168
|
+
if (!tr.docChanged) return cachedSDTNodes;
|
|
67169
|
+
return collectSDTNodes(newState.doc);
|
|
67170
|
+
}
|
|
67171
|
+
},
|
|
67172
|
+
props: {
|
|
67173
|
+
/**
|
|
67174
|
+
* Intercept key events BEFORE any transaction is created.
|
|
67175
|
+
* This prevents the browser selection from getting out of sync.
|
|
67176
|
+
*/
|
|
67177
|
+
handleKeyDown(view, event) {
|
|
67178
|
+
const { state } = view;
|
|
67179
|
+
const { selection } = state;
|
|
67180
|
+
const { from: from3, to } = selection;
|
|
67181
|
+
const isDelete = event.key === "Delete";
|
|
67182
|
+
const isBackspace = event.key === "Backspace";
|
|
67183
|
+
const isCut = (event.metaKey || event.ctrlKey) && event.key === "x";
|
|
67184
|
+
if (!isDelete && !isBackspace && !isCut) {
|
|
67185
|
+
return false;
|
|
67186
|
+
}
|
|
67187
|
+
const sdtNodes = STRUCTURED_CONTENT_LOCK_KEY.getState(state);
|
|
67188
|
+
if (sdtNodes.length === 0) {
|
|
67189
|
+
return false;
|
|
67190
|
+
}
|
|
67191
|
+
let affectedFrom = from3;
|
|
67192
|
+
let affectedTo = to;
|
|
67193
|
+
if (from3 === to) {
|
|
67194
|
+
if (isBackspace && from3 > 0) {
|
|
67195
|
+
affectedFrom = from3 - 1;
|
|
67196
|
+
} else if (isDelete && to < state.doc.content.size) {
|
|
67197
|
+
affectedTo = to + 1;
|
|
67198
|
+
}
|
|
67199
|
+
}
|
|
67200
|
+
const result = checkLockViolation(sdtNodes, affectedFrom, affectedTo);
|
|
67201
|
+
if (result.blocked) {
|
|
67202
|
+
event.preventDefault();
|
|
67203
|
+
return true;
|
|
67204
|
+
}
|
|
67205
|
+
return false;
|
|
67206
|
+
},
|
|
67207
|
+
/**
|
|
67208
|
+
* Handle text input (typing) for content-locked nodes
|
|
67209
|
+
*/
|
|
67210
|
+
handleTextInput(view, from3, to, _text) {
|
|
67211
|
+
const sdtNodes = STRUCTURED_CONTENT_LOCK_KEY.getState(view.state);
|
|
67212
|
+
if (sdtNodes.length === 0) {
|
|
67213
|
+
return false;
|
|
67214
|
+
}
|
|
67215
|
+
const result = checkLockViolation(sdtNodes, from3, to);
|
|
67216
|
+
if (result.blocked) {
|
|
67217
|
+
return true;
|
|
67218
|
+
}
|
|
67219
|
+
return false;
|
|
67220
|
+
}
|
|
67221
|
+
},
|
|
67222
|
+
/**
|
|
67223
|
+
* Safety net: filter transactions that slip through
|
|
67224
|
+
* (e.g., programmatic changes, paste, drag-drop)
|
|
67225
|
+
*/
|
|
67226
|
+
filterTransaction(tr, state) {
|
|
67227
|
+
if (!tr.docChanged) {
|
|
67228
|
+
return true;
|
|
67229
|
+
}
|
|
67230
|
+
const sdtNodes = STRUCTURED_CONTENT_LOCK_KEY.getState(state);
|
|
67231
|
+
if (sdtNodes.length === 0) {
|
|
67232
|
+
return true;
|
|
67233
|
+
}
|
|
67234
|
+
for (const step of tr.steps) {
|
|
67235
|
+
if (step.from === void 0 || step.to === void 0) {
|
|
67236
|
+
continue;
|
|
67237
|
+
}
|
|
67238
|
+
const result = checkLockViolation(sdtNodes, step.from, step.to);
|
|
67239
|
+
if (result.blocked) {
|
|
67240
|
+
return false;
|
|
67241
|
+
}
|
|
67242
|
+
}
|
|
67243
|
+
return true;
|
|
67244
|
+
}
|
|
67245
|
+
});
|
|
67246
|
+
}
|
|
67247
|
+
function createStructuredContentSelectPlugin() {
|
|
67248
|
+
return new superEditor_converter.Plugin({
|
|
67249
|
+
appendTransaction(transactions, oldState, newState) {
|
|
67250
|
+
const { selection } = newState;
|
|
67251
|
+
if (!selection.empty) return null;
|
|
67252
|
+
if (oldState.selection.eq(newState.selection)) return null;
|
|
67253
|
+
if (transactions.some((tr) => tr.docChanged)) return null;
|
|
67254
|
+
const $pos = selection.$from;
|
|
67255
|
+
for (let d = $pos.depth; d > 0; d--) {
|
|
67256
|
+
const node = $pos.node(d);
|
|
67257
|
+
if (node.type.name === "structuredContent") {
|
|
67258
|
+
const sdtStart = $pos.before(d);
|
|
67259
|
+
const contentFrom = $pos.start(d);
|
|
67260
|
+
const contentTo = $pos.end(d);
|
|
67261
|
+
if (contentFrom === contentTo) return null;
|
|
67262
|
+
const old$pos = oldState.selection.$from;
|
|
67263
|
+
for (let od = old$pos.depth; od > 0; od--) {
|
|
67264
|
+
if (old$pos.node(od).type.name === "structuredContent" && old$pos.before(od) === sdtStart) {
|
|
67265
|
+
return null;
|
|
67266
|
+
}
|
|
67267
|
+
}
|
|
67268
|
+
return newState.tr.setSelection(superEditor_converter.TextSelection.create(newState.doc, contentFrom, contentTo));
|
|
67269
|
+
}
|
|
67270
|
+
}
|
|
67271
|
+
return null;
|
|
67272
|
+
}
|
|
67273
|
+
});
|
|
67274
|
+
}
|
|
66941
67275
|
const structuredContentClass = "sd-structured-content";
|
|
66942
67276
|
const structuredContentInnerClass = "sd-structured-content__content";
|
|
66943
67277
|
const StructuredContent = Node$1.create({
|
|
@@ -66983,6 +67317,14 @@ const StructuredContent = Node$1.create({
|
|
|
66983
67317
|
return { "data-alias": attrs.alias };
|
|
66984
67318
|
}
|
|
66985
67319
|
},
|
|
67320
|
+
lockMode: {
|
|
67321
|
+
default: "unlocked",
|
|
67322
|
+
parseDOM: (elem) => elem.getAttribute("data-lock-mode") || "unlocked",
|
|
67323
|
+
renderDOM: (attrs) => {
|
|
67324
|
+
if (!attrs.lockMode || attrs.lockMode === "unlocked") return {};
|
|
67325
|
+
return { "data-lock-mode": attrs.lockMode };
|
|
67326
|
+
}
|
|
67327
|
+
},
|
|
66986
67328
|
sdtPr: {
|
|
66987
67329
|
rendered: false
|
|
66988
67330
|
}
|
|
@@ -67000,6 +67342,9 @@ const StructuredContent = Node$1.create({
|
|
|
67000
67342
|
0
|
|
67001
67343
|
];
|
|
67002
67344
|
},
|
|
67345
|
+
addPmPlugins() {
|
|
67346
|
+
return [createStructuredContentLockPlugin(), createStructuredContentSelectPlugin()];
|
|
67347
|
+
},
|
|
67003
67348
|
addNodeView() {
|
|
67004
67349
|
return (props) => {
|
|
67005
67350
|
return new StructuredContentInlineView({ ...props });
|
|
@@ -67034,10 +67379,12 @@ class StructuredContentBlockView extends StructuredContentViewBase {
|
|
|
67034
67379
|
element.prepend(dragHandle);
|
|
67035
67380
|
element.addEventListener("dragstart", (e) => this.onDragStart(e));
|
|
67036
67381
|
this.root = element;
|
|
67382
|
+
this.updateContentEditability();
|
|
67037
67383
|
}
|
|
67038
67384
|
updateView() {
|
|
67039
67385
|
const domAttrs = Attribute.mergeAttributes(this.htmlAttributes);
|
|
67040
67386
|
updateDOMAttributes(this.dom, { ...domAttrs });
|
|
67387
|
+
this.updateContentEditability();
|
|
67041
67388
|
}
|
|
67042
67389
|
update(node, decorations, innerDecorations) {
|
|
67043
67390
|
const result = super.update(node, decorations, innerDecorations);
|
|
@@ -67090,6 +67437,14 @@ const StructuredContentBlock = Node$1.create({
|
|
|
67090
67437
|
return { "data-alias": attrs.alias };
|
|
67091
67438
|
}
|
|
67092
67439
|
},
|
|
67440
|
+
lockMode: {
|
|
67441
|
+
default: "unlocked",
|
|
67442
|
+
parseDOM: (elem) => elem.getAttribute("data-lock-mode") || "unlocked",
|
|
67443
|
+
renderDOM: (attrs) => {
|
|
67444
|
+
if (!attrs.lockMode || attrs.lockMode === "unlocked") return {};
|
|
67445
|
+
return { "data-lock-mode": attrs.lockMode };
|
|
67446
|
+
}
|
|
67447
|
+
},
|
|
67093
67448
|
sdtPr: {
|
|
67094
67449
|
rendered: false
|
|
67095
67450
|
}
|
|
@@ -86366,18 +86721,25 @@ const _hoisted_3$8 = {
|
|
|
86366
86721
|
};
|
|
86367
86722
|
const _hoisted_4$4 = {
|
|
86368
86723
|
key: 3,
|
|
86369
|
-
class: "link-
|
|
86724
|
+
class: "link-title"
|
|
86370
86725
|
};
|
|
86371
|
-
const _hoisted_5$2 = {
|
|
86372
|
-
const _hoisted_6$1 = ["onKeydown"];
|
|
86373
|
-
const _hoisted_7$1 = { class: "input-row url-input-row" };
|
|
86374
|
-
const _hoisted_8$1 = ["innerHTML"];
|
|
86375
|
-
const _hoisted_9 = ["onKeydown"];
|
|
86376
|
-
const _hoisted_10 = ["innerHTML"];
|
|
86377
|
-
const _hoisted_11 = { class: "input-row link-buttons" };
|
|
86378
|
-
const _hoisted_12 = ["innerHTML"];
|
|
86379
|
-
const _hoisted_13 = {
|
|
86726
|
+
const _hoisted_5$2 = {
|
|
86380
86727
|
key: 4,
|
|
86728
|
+
class: "link-input-wrapper"
|
|
86729
|
+
};
|
|
86730
|
+
const _hoisted_6$1 = { class: "input-row text-input-row" };
|
|
86731
|
+
const _hoisted_7$1 = ["readonly"];
|
|
86732
|
+
const _hoisted_8$1 = { class: "input-row url-input-row" };
|
|
86733
|
+
const _hoisted_9 = ["innerHTML"];
|
|
86734
|
+
const _hoisted_10 = ["readonly", "onKeydown"];
|
|
86735
|
+
const _hoisted_11 = ["innerHTML"];
|
|
86736
|
+
const _hoisted_12 = {
|
|
86737
|
+
key: 0,
|
|
86738
|
+
class: "input-row link-buttons"
|
|
86739
|
+
};
|
|
86740
|
+
const _hoisted_13 = ["innerHTML"];
|
|
86741
|
+
const _hoisted_14 = {
|
|
86742
|
+
key: 5,
|
|
86381
86743
|
class: "input-row go-to-anchor clickable"
|
|
86382
86744
|
};
|
|
86383
86745
|
const _sfc_main$j = {
|
|
@@ -86471,6 +86833,7 @@ const _sfc_main$j = {
|
|
|
86471
86833
|
});
|
|
86472
86834
|
const isEditing = vue.computed(() => !isAnchor.value && !!getLinkHrefAtSelection());
|
|
86473
86835
|
const isDisabled2 = vue.computed(() => !validUrl.value);
|
|
86836
|
+
const isViewingMode = vue.computed(() => props.editor?.options?.documentMode === "viewing");
|
|
86474
86837
|
const openLink = () => {
|
|
86475
86838
|
window.open(url.value, "_blank");
|
|
86476
86839
|
};
|
|
@@ -86496,6 +86859,7 @@ const _sfc_main$j = {
|
|
|
86496
86859
|
if (props.showInput) focusInput();
|
|
86497
86860
|
});
|
|
86498
86861
|
const handleSubmit = () => {
|
|
86862
|
+
if (isViewingMode.value) return;
|
|
86499
86863
|
const editor = props.editor;
|
|
86500
86864
|
if (!editor) return;
|
|
86501
86865
|
if (!rawUrl.value) {
|
|
@@ -86526,36 +86890,38 @@ const _sfc_main$j = {
|
|
|
86526
86890
|
return vue.openBlock(), vue.createElementBlock("div", {
|
|
86527
86891
|
class: vue.normalizeClass(["link-input-ctn", { "high-contrast": vue.unref(isHighContrastMode2) }])
|
|
86528
86892
|
}, [
|
|
86529
|
-
isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$g, "Page anchor")) :
|
|
86530
|
-
__props.showInput && !isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div",
|
|
86531
|
-
vue.createBaseVNode("div",
|
|
86532
|
-
_cache[
|
|
86893
|
+
isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$g, "Page anchor")) : isViewingMode.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$b, "Link details")) : isEditing.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$8, "Edit link")) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$4, "Add link")),
|
|
86894
|
+
__props.showInput && !isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$2, [
|
|
86895
|
+
vue.createBaseVNode("div", _hoisted_6$1, [
|
|
86896
|
+
_cache[5] || (_cache[5] = vue.createBaseVNode("div", { class: "input-icon text-input-icon" }, "T", -1)),
|
|
86533
86897
|
vue.withDirectives(vue.createBaseVNode("input", {
|
|
86534
86898
|
type: "text",
|
|
86535
86899
|
name: "text",
|
|
86536
86900
|
placeholder: "Text",
|
|
86537
86901
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => text.value = $event),
|
|
86538
|
-
|
|
86539
|
-
|
|
86902
|
+
readonly: isViewingMode.value,
|
|
86903
|
+
onKeydown: _cache[1] || (_cache[1] = vue.withKeys(vue.withModifiers(($event) => !isViewingMode.value && handleSubmit, ["stop", "prevent"]), ["enter"]))
|
|
86904
|
+
}, null, 40, _hoisted_7$1), [
|
|
86540
86905
|
[vue.vModelText, text.value]
|
|
86541
86906
|
])
|
|
86542
86907
|
]),
|
|
86543
|
-
vue.createBaseVNode("div",
|
|
86908
|
+
vue.createBaseVNode("div", _hoisted_8$1, [
|
|
86544
86909
|
vue.createBaseVNode("div", {
|
|
86545
86910
|
class: "input-icon",
|
|
86546
86911
|
innerHTML: vue.unref(toolbarIcons).linkInput
|
|
86547
|
-
}, null, 8,
|
|
86912
|
+
}, null, 8, _hoisted_9),
|
|
86548
86913
|
vue.withDirectives(vue.createBaseVNode("input", {
|
|
86549
86914
|
type: "text",
|
|
86550
86915
|
name: "link",
|
|
86551
86916
|
placeholder: "Type or paste a link",
|
|
86552
86917
|
class: vue.normalizeClass({ error: urlError.value }),
|
|
86553
|
-
"onUpdate:modelValue": _cache[
|
|
86918
|
+
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => rawUrl.value = $event),
|
|
86919
|
+
readonly: isViewingMode.value,
|
|
86554
86920
|
onKeydown: [
|
|
86555
86921
|
vue.withKeys(vue.withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"]),
|
|
86556
|
-
_cache[
|
|
86922
|
+
_cache[3] || (_cache[3] = ($event) => urlError.value = false)
|
|
86557
86923
|
]
|
|
86558
|
-
}, null, 42,
|
|
86924
|
+
}, null, 42, _hoisted_10), [
|
|
86559
86925
|
[vue.vModelText, rawUrl.value]
|
|
86560
86926
|
]),
|
|
86561
86927
|
vue.createBaseVNode("div", {
|
|
@@ -86563,9 +86929,9 @@ const _sfc_main$j = {
|
|
|
86563
86929
|
innerHTML: vue.unref(toolbarIcons).openLink,
|
|
86564
86930
|
onClick: openLink,
|
|
86565
86931
|
"data-item": "btn-link-open"
|
|
86566
|
-
}, null, 10,
|
|
86932
|
+
}, null, 10, _hoisted_11)
|
|
86567
86933
|
]),
|
|
86568
|
-
vue.
|
|
86934
|
+
!isViewingMode.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_12, [
|
|
86569
86935
|
isEditing.value ? (vue.openBlock(), vue.createElementBlock("button", {
|
|
86570
86936
|
key: 0,
|
|
86571
86937
|
class: "remove-btn",
|
|
@@ -86575,25 +86941,25 @@ const _sfc_main$j = {
|
|
|
86575
86941
|
vue.createBaseVNode("div", {
|
|
86576
86942
|
class: "remove-btn__icon",
|
|
86577
86943
|
innerHTML: vue.unref(toolbarIcons).removeLink
|
|
86578
|
-
}, null, 8,
|
|
86579
|
-
_cache[
|
|
86944
|
+
}, null, 8, _hoisted_13),
|
|
86945
|
+
_cache[6] || (_cache[6] = vue.createTextVNode(" Remove ", -1))
|
|
86580
86946
|
])) : vue.createCommentVNode("", true),
|
|
86581
86947
|
vue.createBaseVNode("button", {
|
|
86582
86948
|
class: vue.normalizeClass(["submit-btn", { "disable-btn": isDisabled2.value }]),
|
|
86583
86949
|
onClick: handleSubmit,
|
|
86584
86950
|
"data-item": "btn-link-apply"
|
|
86585
86951
|
}, " Apply ", 2)
|
|
86586
|
-
])
|
|
86587
|
-
])) : isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div",
|
|
86952
|
+
])) : vue.createCommentVNode("", true)
|
|
86953
|
+
])) : isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_14, [
|
|
86588
86954
|
vue.createBaseVNode("a", {
|
|
86589
|
-
onClick: _cache[
|
|
86955
|
+
onClick: _cache[4] || (_cache[4] = vue.withModifiers((...args) => __props.goToAnchor && __props.goToAnchor(...args), ["stop", "prevent"]))
|
|
86590
86956
|
}, "Go to " + vue.toDisplayString(rawUrl.value.startsWith("#_") ? rawUrl.value.substring(2) : rawUrl.value), 1)
|
|
86591
86957
|
])) : vue.createCommentVNode("", true)
|
|
86592
86958
|
], 2);
|
|
86593
86959
|
};
|
|
86594
86960
|
}
|
|
86595
86961
|
};
|
|
86596
|
-
const LinkInput = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-
|
|
86962
|
+
const LinkInput = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-198fc596"]]);
|
|
86597
86963
|
const _hoisted_1$f = ["aria-label", "onClick", "onKeydown"];
|
|
86598
86964
|
const _hoisted_2$a = ["innerHTML"];
|
|
86599
86965
|
const _hoisted_3$7 = ["innerHTML"];
|