@jvs-milkdown/crepe 1.2.25 → 1.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/feature/block-edit/index.js +3 -3
- package/lib/cjs/feature/block-edit/index.js.map +1 -1
- package/lib/cjs/feature/toolbar/index.js +1 -1
- package/lib/cjs/feature/toolbar/index.js.map +1 -1
- package/lib/cjs/index.js +420 -6
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/feature/block-edit/index.js +3 -3
- package/lib/esm/feature/block-edit/index.js.map +1 -1
- package/lib/esm/feature/toolbar/index.js +1 -1
- package/lib/esm/feature/toolbar/index.js.map +1 -1
- package/lib/esm/index.js +421 -7
- package/lib/esm/index.js.map +1 -1
- package/lib/theme/common/block-edit.css +5 -3
- package/lib/theme/common/code-mirror.css +19 -0
- package/lib/theme/common/link-tooltip.css +2 -2
- package/lib/theme/common/toolbar.css +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/default-config/index.d.ts.map +1 -1
- package/lib/types/feature/block-edit/handle/index.d.ts.map +1 -1
- package/lib/types/feature/block-edit/menu/component.d.ts.map +1 -1
- package/lib/types/feature/fixed-toolbar/config.d.ts.map +1 -1
- package/lib/types/feature/fixed-toolbar/index.d.ts +2 -0
- package/lib/types/feature/fixed-toolbar/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/default-config/default-config.spec.ts +15 -0
- package/src/default-config/index.ts +17 -1
- package/src/feature/block-edit/handle/index.ts +8 -2
- package/src/feature/block-edit/menu/component.tsx +4 -1
- package/src/feature/fixed-toolbar/config.ts +482 -3
- package/src/feature/fixed-toolbar/index.ts +2 -0
- package/src/theme/common/block-edit.css +5 -3
- package/src/theme/common/code-mirror.css +19 -0
- package/src/theme/common/link-tooltip.css +2 -2
- package/src/theme/common/toolbar.css +1 -1
package/lib/cjs/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var utils$1 = require('@jvs-milkdown/utils');
|
|
4
4
|
var lodashEs = require('lodash-es');
|
|
5
|
+
var language = require('@codemirror/language');
|
|
5
6
|
var languageData = require('@codemirror/language-data');
|
|
6
7
|
var themeOneDark = require('@codemirror/theme-one-dark');
|
|
7
8
|
var ctx = require('@jvs-milkdown/kit/ctx');
|
|
@@ -696,10 +697,21 @@ const importIcon = `
|
|
|
696
697
|
</svg>
|
|
697
698
|
`;
|
|
698
699
|
|
|
700
|
+
const mermaidLanguage = language.LanguageDescription.of({
|
|
701
|
+
name: "Mermaid",
|
|
702
|
+
alias: ["mermaid"],
|
|
703
|
+
load: () => {
|
|
704
|
+
const fallback = languageData.languages.find((l) => l.name === "YAML") || languageData.languages.find((l) => l.name === "Markdown");
|
|
705
|
+
return fallback ? fallback.load() : Promise.resolve(null);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
const allLanguages = [mermaidLanguage, ...languageData.languages].sort(
|
|
709
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
710
|
+
);
|
|
699
711
|
const defaultConfig = {
|
|
700
712
|
[CrepeFeature.CodeMirror]: {
|
|
701
713
|
theme: themeOneDark.oneDark,
|
|
702
|
-
languages:
|
|
714
|
+
languages: allLanguages,
|
|
703
715
|
expandIcon: chevronDownIcon,
|
|
704
716
|
searchIcon,
|
|
705
717
|
clearSearchIcon: clearIcon,
|
|
@@ -3085,7 +3097,7 @@ const Menu = vue.defineComponent({
|
|
|
3085
3097
|
const isTableBlock = (node == null ? void 0 : node.type.name) === "table";
|
|
3086
3098
|
const isMedia = ((_a = node == null ? void 0 : node.type.name) == null ? void 0 : _a.includes("image")) || isAttachmentBlock || isImageParagraph || (node == null ? void 0 : node.type.name) === "hr" || isTableBlock;
|
|
3087
3099
|
const showAlign = !isMedia || isImageBlock;
|
|
3088
|
-
const isEmpty = node ? node.textContent.length === 0 && node.content.size <= 2 && !isMedia : false;
|
|
3100
|
+
const isEmpty = node ? node.type.name === "paragraph" && node.textContent.length === 0 && node.content.size <= 2 && !isMedia : false;
|
|
3089
3101
|
const currentAlign = ((_b = node == null ? void 0 : node.attrs) == null ? void 0 : _b.align) || "left";
|
|
3090
3102
|
const currentIndent = ((_c = node == null ? void 0 : node.attrs) == null ? void 0 : _c.indent) || 0;
|
|
3091
3103
|
const setAlign = (alignValue) => {
|
|
@@ -4041,7 +4053,7 @@ class BlockHandleView {
|
|
|
4041
4053
|
});
|
|
4042
4054
|
}
|
|
4043
4055
|
const isMedia = node.type.name.includes("image") || node.type.name.includes("attachment") || node.type.name === "hr" || node.type.name.includes("math") || hasMediaChild;
|
|
4044
|
-
const isEmpty = node.textContent.length === 0 && node.content.size <= 2 && !isMedia;
|
|
4056
|
+
const isEmpty = node.type.name === "paragraph" && node.textContent.length === 0 && node.content.size <= 2 && !isMedia;
|
|
4045
4057
|
if (isEmpty) {
|
|
4046
4058
|
__privateGet$5(this, _content$3).classList.add("empty-block");
|
|
4047
4059
|
} else {
|
|
@@ -4192,7 +4204,7 @@ class BlockHandleView {
|
|
|
4192
4204
|
});
|
|
4193
4205
|
}
|
|
4194
4206
|
const isMedia = node.type.name.includes("image") || node.type.name.includes("attachment") || node.type.name === "hr" || node.type.name.includes("math") || hasMediaChild;
|
|
4195
|
-
const isEmpty = node.textContent.length === 0 && node.content.size <= 2 && !isMedia;
|
|
4207
|
+
const isEmpty = node.type.name === "paragraph" && node.textContent.length === 0 && node.content.size <= 2 && !isMedia;
|
|
4196
4208
|
if (isEmpty) {
|
|
4197
4209
|
__privateGet$5(this, _content$3).classList.add("empty-block");
|
|
4198
4210
|
} else {
|
|
@@ -9117,7 +9129,17 @@ function buildDefaultFixedToolbar(builder, _config, ctx) {
|
|
|
9117
9129
|
active: () => false,
|
|
9118
9130
|
onRun: (ctx2) => {
|
|
9119
9131
|
const markdown = utils.getMarkdown()(ctx2);
|
|
9120
|
-
|
|
9132
|
+
const view = ctx2.get(core.editorViewCtx);
|
|
9133
|
+
const root = ctx2.get(core.rootCtx);
|
|
9134
|
+
const rootNode = view.dom.getRootNode();
|
|
9135
|
+
if ((_config == null ? void 0 : _config.exportItems) && _config.exportItems.length > 0) {
|
|
9136
|
+
const exportItems = _config.exportItems;
|
|
9137
|
+
if (exportItems.length === 1) {
|
|
9138
|
+
handleDirectExport(exportItems[0], markdown, view, root);
|
|
9139
|
+
} else {
|
|
9140
|
+
showDownloadPopover(rootNode, root, view, markdown, exportItems);
|
|
9141
|
+
}
|
|
9142
|
+
} else if (_config == null ? void 0 : _config.onExport) {
|
|
9121
9143
|
_config.onExport(markdown, ctx2);
|
|
9122
9144
|
} else {
|
|
9123
9145
|
const blob = new Blob([markdown], {
|
|
@@ -9139,7 +9161,17 @@ function buildDefaultFixedToolbar(builder, _config, ctx) {
|
|
|
9139
9161
|
icon: importIcon,
|
|
9140
9162
|
active: () => false,
|
|
9141
9163
|
onRun: (ctx2) => {
|
|
9142
|
-
|
|
9164
|
+
const view = ctx2.get(core.editorViewCtx);
|
|
9165
|
+
const root = ctx2.get(core.rootCtx);
|
|
9166
|
+
const rootNode = view.dom.getRootNode();
|
|
9167
|
+
if ((_config == null ? void 0 : _config.importItems) && _config.importItems.length > 0) {
|
|
9168
|
+
const importItems = _config.importItems;
|
|
9169
|
+
if (importItems.length === 1) {
|
|
9170
|
+
handleDirectImport(importItems[0], root, ctx2);
|
|
9171
|
+
} else {
|
|
9172
|
+
showImportPopover(rootNode, root, ctx2, importItems);
|
|
9173
|
+
}
|
|
9174
|
+
} else if (_config == null ? void 0 : _config.onImport) {
|
|
9143
9175
|
_config.onImport((markdown) => utils$1.replaceAll(markdown)(ctx2), ctx2);
|
|
9144
9176
|
} else {
|
|
9145
9177
|
const input = document.createElement("input");
|
|
@@ -9170,6 +9202,388 @@ function buildDefaultFixedToolbar(builder, _config, ctx) {
|
|
|
9170
9202
|
});
|
|
9171
9203
|
return builder.build();
|
|
9172
9204
|
}
|
|
9205
|
+
const activeDownloadPopovers = /* @__PURE__ */ new WeakMap();
|
|
9206
|
+
const activeImportPopovers = /* @__PURE__ */ new WeakMap();
|
|
9207
|
+
const ensureStyles = (rootNode) => {
|
|
9208
|
+
const target = rootNode instanceof ShadowRoot ? rootNode : document.head;
|
|
9209
|
+
if (target.querySelector("#download-popover-styles")) return;
|
|
9210
|
+
const styleEl = document.createElement("style");
|
|
9211
|
+
styleEl.id = "download-popover-styles";
|
|
9212
|
+
styleEl.textContent = `
|
|
9213
|
+
.download-popover, .import-popover {
|
|
9214
|
+
position: fixed;
|
|
9215
|
+
z-index: 10000;
|
|
9216
|
+
width: 140px;
|
|
9217
|
+
padding: 6px 0;
|
|
9218
|
+
display: flex;
|
|
9219
|
+
flex-direction: column;
|
|
9220
|
+
background-color: var(--crepe-color-surface, #ffffff);
|
|
9221
|
+
border: 1px solid var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%));
|
|
9222
|
+
border-radius: 8px;
|
|
9223
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
9224
|
+
opacity: 0;
|
|
9225
|
+
transform: translateY(-8px);
|
|
9226
|
+
transition: opacity 0.15s ease, transform 0.15s ease;
|
|
9227
|
+
pointer-events: none;
|
|
9228
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
9229
|
+
}
|
|
9230
|
+
.download-popover.show, .import-popover.show {
|
|
9231
|
+
opacity: 1;
|
|
9232
|
+
transform: translateY(0);
|
|
9233
|
+
pointer-events: auto;
|
|
9234
|
+
}
|
|
9235
|
+
.download-popover-item, .import-popover-item {
|
|
9236
|
+
cursor: pointer;
|
|
9237
|
+
padding: 8px 14px;
|
|
9238
|
+
display: flex;
|
|
9239
|
+
align-items: center;
|
|
9240
|
+
gap: 8px;
|
|
9241
|
+
font-size: 13px;
|
|
9242
|
+
font-weight: 500;
|
|
9243
|
+
color: var(--crepe-color-primary, #363B4C);
|
|
9244
|
+
transition: background-color 0.2s;
|
|
9245
|
+
user-select: none;
|
|
9246
|
+
}
|
|
9247
|
+
.download-popover-item:hover, .import-popover-item:hover {
|
|
9248
|
+
background-color: var(--crepe-color-hover, #f5f5f5);
|
|
9249
|
+
}
|
|
9250
|
+
.download-popover-item-icon, .import-popover-item-icon {
|
|
9251
|
+
display: flex;
|
|
9252
|
+
align-items: center;
|
|
9253
|
+
justify-content: center;
|
|
9254
|
+
width: 14px;
|
|
9255
|
+
height: 14px;
|
|
9256
|
+
color: var(--crepe-color-primary, #363B4C);
|
|
9257
|
+
opacity: 0.8;
|
|
9258
|
+
}
|
|
9259
|
+
`;
|
|
9260
|
+
target.appendChild(styleEl);
|
|
9261
|
+
};
|
|
9262
|
+
function handleDirectExport(type, markdown, view, root) {
|
|
9263
|
+
if (type === "markdown") {
|
|
9264
|
+
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8;" });
|
|
9265
|
+
const url = URL.createObjectURL(blob);
|
|
9266
|
+
const link = document.createElement("a");
|
|
9267
|
+
link.href = url;
|
|
9268
|
+
link.download = "document.md";
|
|
9269
|
+
link.click();
|
|
9270
|
+
URL.revokeObjectURL(url);
|
|
9271
|
+
}
|
|
9272
|
+
const event = new CustomEvent("download-click", {
|
|
9273
|
+
detail: {
|
|
9274
|
+
type,
|
|
9275
|
+
markdown,
|
|
9276
|
+
html: view.dom.innerHTML || ""
|
|
9277
|
+
},
|
|
9278
|
+
bubbles: true,
|
|
9279
|
+
composed: true
|
|
9280
|
+
});
|
|
9281
|
+
root.dispatchEvent(event);
|
|
9282
|
+
}
|
|
9283
|
+
function handleDirectImport(type, root, ctx) {
|
|
9284
|
+
if (type === "markdown") {
|
|
9285
|
+
const input = document.createElement("input");
|
|
9286
|
+
input.type = "file";
|
|
9287
|
+
input.accept = ".md";
|
|
9288
|
+
input.onchange = (evt) => {
|
|
9289
|
+
var _a;
|
|
9290
|
+
const file = (_a = evt.target.files) == null ? void 0 : _a[0];
|
|
9291
|
+
if (!file) return;
|
|
9292
|
+
file.text().then((text) => {
|
|
9293
|
+
utils$1.replaceAll(text)(ctx);
|
|
9294
|
+
const event = new CustomEvent("import-click", {
|
|
9295
|
+
detail: { type: "markdown", file },
|
|
9296
|
+
bubbles: true,
|
|
9297
|
+
composed: true
|
|
9298
|
+
});
|
|
9299
|
+
root.dispatchEvent(event);
|
|
9300
|
+
}).catch((err) => {
|
|
9301
|
+
console.error("Failed to read file:", err);
|
|
9302
|
+
});
|
|
9303
|
+
};
|
|
9304
|
+
input.click();
|
|
9305
|
+
} else {
|
|
9306
|
+
const event = new CustomEvent("import-click", {
|
|
9307
|
+
detail: { type },
|
|
9308
|
+
bubbles: true,
|
|
9309
|
+
composed: true
|
|
9310
|
+
});
|
|
9311
|
+
root.dispatchEvent(event);
|
|
9312
|
+
}
|
|
9313
|
+
}
|
|
9314
|
+
function showDownloadPopover(rootNode, root, view, markdown, exportItems) {
|
|
9315
|
+
var _a, _b, _c;
|
|
9316
|
+
const button = root.querySelector('button[data-key="export"]');
|
|
9317
|
+
if (!button) return;
|
|
9318
|
+
const existing = activeDownloadPopovers.get(button);
|
|
9319
|
+
if (existing) {
|
|
9320
|
+
existing.closePopover();
|
|
9321
|
+
return;
|
|
9322
|
+
}
|
|
9323
|
+
ensureStyles(rootNode);
|
|
9324
|
+
const container = rootNode instanceof ShadowRoot ? rootNode : document.body;
|
|
9325
|
+
const popover = document.createElement("div");
|
|
9326
|
+
popover.className = "download-popover";
|
|
9327
|
+
let popoverHtml = "";
|
|
9328
|
+
if (exportItems.includes("markdown")) {
|
|
9329
|
+
popoverHtml += `
|
|
9330
|
+
<div class="download-popover-item" id="download-md-btn">
|
|
9331
|
+
<span class="download-popover-item-icon">
|
|
9332
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><line x1="10" y1="9" x2="8" y2="9"></line></svg>
|
|
9333
|
+
</span>
|
|
9334
|
+
<span>\u4E0B\u8F7D MD</span>
|
|
9335
|
+
</div>
|
|
9336
|
+
`;
|
|
9337
|
+
}
|
|
9338
|
+
if (exportItems.includes("word")) {
|
|
9339
|
+
popoverHtml += `
|
|
9340
|
+
<div class="download-popover-item" id="download-word-btn">
|
|
9341
|
+
<span class="download-popover-item-icon">
|
|
9342
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
|
9343
|
+
</span>
|
|
9344
|
+
<span>\u4E0B\u8F7D WORD</span>
|
|
9345
|
+
</div>
|
|
9346
|
+
`;
|
|
9347
|
+
}
|
|
9348
|
+
if (exportItems.includes("pdf")) {
|
|
9349
|
+
popoverHtml += `
|
|
9350
|
+
<div class="download-popover-item" id="download-pdf-btn">
|
|
9351
|
+
<span class="download-popover-item-icon">
|
|
9352
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect></svg>
|
|
9353
|
+
</span>
|
|
9354
|
+
<span>\u4E0B\u8F7D PDF</span>
|
|
9355
|
+
</div>
|
|
9356
|
+
`;
|
|
9357
|
+
}
|
|
9358
|
+
popover.innerHTML = popoverHtml;
|
|
9359
|
+
container.appendChild(popover);
|
|
9360
|
+
activeDownloadPopovers.set(button, popover);
|
|
9361
|
+
const updatePosition = () => {
|
|
9362
|
+
const rect = button.getBoundingClientRect();
|
|
9363
|
+
popover.style.top = `${rect.bottom + 4}px`;
|
|
9364
|
+
popover.style.left = `${rect.left + (rect.width - 140) / 2}px`;
|
|
9365
|
+
};
|
|
9366
|
+
updatePosition();
|
|
9367
|
+
requestAnimationFrame(() => {
|
|
9368
|
+
popover.classList.add("show");
|
|
9369
|
+
});
|
|
9370
|
+
const closePopover = () => {
|
|
9371
|
+
popover.classList.remove("show");
|
|
9372
|
+
activeDownloadPopovers.delete(button);
|
|
9373
|
+
container.removeEventListener("pointerdown", handleContainerClick, true);
|
|
9374
|
+
document.removeEventListener("pointerdown", handleOuterClick, true);
|
|
9375
|
+
window.removeEventListener("resize", updatePosition);
|
|
9376
|
+
popover.addEventListener(
|
|
9377
|
+
"transitionend",
|
|
9378
|
+
() => {
|
|
9379
|
+
popover.remove();
|
|
9380
|
+
},
|
|
9381
|
+
{ once: true }
|
|
9382
|
+
);
|
|
9383
|
+
};
|
|
9384
|
+
popover.closePopover = closePopover;
|
|
9385
|
+
const handleContainerClick = (e) => {
|
|
9386
|
+
const target = e.target;
|
|
9387
|
+
if (!popover.contains(target) && target !== button && !button.contains(target)) {
|
|
9388
|
+
closePopover();
|
|
9389
|
+
}
|
|
9390
|
+
};
|
|
9391
|
+
const handleOuterClick = (e) => {
|
|
9392
|
+
const target = e.target;
|
|
9393
|
+
if (target !== root && !root.contains(target)) {
|
|
9394
|
+
closePopover();
|
|
9395
|
+
}
|
|
9396
|
+
};
|
|
9397
|
+
popover.addEventListener("pointerdown", (e) => {
|
|
9398
|
+
e.stopPropagation();
|
|
9399
|
+
});
|
|
9400
|
+
container.addEventListener("pointerdown", handleContainerClick, true);
|
|
9401
|
+
document.addEventListener("pointerdown", handleOuterClick, true);
|
|
9402
|
+
window.addEventListener("resize", updatePosition);
|
|
9403
|
+
(_a = popover.querySelector("#download-md-btn")) == null ? void 0 : _a.addEventListener("click", (e) => {
|
|
9404
|
+
e.stopPropagation();
|
|
9405
|
+
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8;" });
|
|
9406
|
+
const url = URL.createObjectURL(blob);
|
|
9407
|
+
const link = document.createElement("a");
|
|
9408
|
+
link.href = url;
|
|
9409
|
+
link.download = "document.md";
|
|
9410
|
+
link.click();
|
|
9411
|
+
URL.revokeObjectURL(url);
|
|
9412
|
+
closePopover();
|
|
9413
|
+
const event = new CustomEvent("download-click", {
|
|
9414
|
+
detail: {
|
|
9415
|
+
type: "markdown",
|
|
9416
|
+
markdown,
|
|
9417
|
+
html: view.dom.innerHTML || ""
|
|
9418
|
+
},
|
|
9419
|
+
bubbles: true,
|
|
9420
|
+
composed: true
|
|
9421
|
+
});
|
|
9422
|
+
root.dispatchEvent(event);
|
|
9423
|
+
});
|
|
9424
|
+
(_b = popover.querySelector("#download-word-btn")) == null ? void 0 : _b.addEventListener("click", (e) => {
|
|
9425
|
+
e.stopPropagation();
|
|
9426
|
+
closePopover();
|
|
9427
|
+
const event = new CustomEvent("download-click", {
|
|
9428
|
+
detail: {
|
|
9429
|
+
type: "word",
|
|
9430
|
+
markdown,
|
|
9431
|
+
html: view.dom.innerHTML || ""
|
|
9432
|
+
},
|
|
9433
|
+
bubbles: true,
|
|
9434
|
+
composed: true
|
|
9435
|
+
});
|
|
9436
|
+
root.dispatchEvent(event);
|
|
9437
|
+
});
|
|
9438
|
+
(_c = popover.querySelector("#download-pdf-btn")) == null ? void 0 : _c.addEventListener("click", (e) => {
|
|
9439
|
+
e.stopPropagation();
|
|
9440
|
+
closePopover();
|
|
9441
|
+
const event = new CustomEvent("download-click", {
|
|
9442
|
+
detail: {
|
|
9443
|
+
type: "pdf",
|
|
9444
|
+
markdown,
|
|
9445
|
+
html: view.dom.innerHTML || ""
|
|
9446
|
+
},
|
|
9447
|
+
bubbles: true,
|
|
9448
|
+
composed: true
|
|
9449
|
+
});
|
|
9450
|
+
root.dispatchEvent(event);
|
|
9451
|
+
});
|
|
9452
|
+
}
|
|
9453
|
+
function showImportPopover(rootNode, root, ctx, importItems) {
|
|
9454
|
+
var _a, _b, _c;
|
|
9455
|
+
const button = root.querySelector('button[data-key="import"]');
|
|
9456
|
+
if (!button) return;
|
|
9457
|
+
const existing = activeImportPopovers.get(button);
|
|
9458
|
+
if (existing) {
|
|
9459
|
+
existing.closePopover();
|
|
9460
|
+
return;
|
|
9461
|
+
}
|
|
9462
|
+
ensureStyles(rootNode);
|
|
9463
|
+
const container = rootNode instanceof ShadowRoot ? rootNode : document.body;
|
|
9464
|
+
const popover = document.createElement("div");
|
|
9465
|
+
popover.className = "import-popover";
|
|
9466
|
+
let popoverHtml = "";
|
|
9467
|
+
if (importItems.includes("markdown")) {
|
|
9468
|
+
popoverHtml += `
|
|
9469
|
+
<div class="import-popover-item" id="import-md-btn">
|
|
9470
|
+
<span class="import-popover-item-icon">
|
|
9471
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><line x1="10" y1="9" x2="8" y2="9"></line></svg>
|
|
9472
|
+
</span>
|
|
9473
|
+
<span>\u5BFC\u5165 MD</span>
|
|
9474
|
+
</div>
|
|
9475
|
+
`;
|
|
9476
|
+
}
|
|
9477
|
+
if (importItems.includes("word")) {
|
|
9478
|
+
popoverHtml += `
|
|
9479
|
+
<div class="import-popover-item" id="import-word-btn">
|
|
9480
|
+
<span class="import-popover-item-icon">
|
|
9481
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
|
9482
|
+
</span>
|
|
9483
|
+
<span>\u5BFC\u5165 WORD</span>
|
|
9484
|
+
</div>
|
|
9485
|
+
`;
|
|
9486
|
+
}
|
|
9487
|
+
if (importItems.includes("pdf")) {
|
|
9488
|
+
popoverHtml += `
|
|
9489
|
+
<div class="import-popover-item" id="import-pdf-btn">
|
|
9490
|
+
<span class="import-popover-item-icon">
|
|
9491
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect></svg>
|
|
9492
|
+
</span>
|
|
9493
|
+
<span>\u5BFC\u5165 PDF</span>
|
|
9494
|
+
</div>
|
|
9495
|
+
`;
|
|
9496
|
+
}
|
|
9497
|
+
popover.innerHTML = popoverHtml;
|
|
9498
|
+
container.appendChild(popover);
|
|
9499
|
+
activeImportPopovers.set(button, popover);
|
|
9500
|
+
const updatePosition = () => {
|
|
9501
|
+
const rect = button.getBoundingClientRect();
|
|
9502
|
+
popover.style.top = `${rect.bottom + 4}px`;
|
|
9503
|
+
popover.style.left = `${rect.left + (rect.width - 140) / 2}px`;
|
|
9504
|
+
};
|
|
9505
|
+
updatePosition();
|
|
9506
|
+
requestAnimationFrame(() => {
|
|
9507
|
+
popover.classList.add("show");
|
|
9508
|
+
});
|
|
9509
|
+
const closePopover = () => {
|
|
9510
|
+
popover.classList.remove("show");
|
|
9511
|
+
activeImportPopovers.delete(button);
|
|
9512
|
+
container.removeEventListener("pointerdown", handleContainerClick, true);
|
|
9513
|
+
document.removeEventListener("pointerdown", handleOuterClick, true);
|
|
9514
|
+
window.removeEventListener("resize", updatePosition);
|
|
9515
|
+
popover.addEventListener(
|
|
9516
|
+
"transitionend",
|
|
9517
|
+
() => {
|
|
9518
|
+
popover.remove();
|
|
9519
|
+
},
|
|
9520
|
+
{ once: true }
|
|
9521
|
+
);
|
|
9522
|
+
};
|
|
9523
|
+
popover.closePopover = closePopover;
|
|
9524
|
+
const handleContainerClick = (e) => {
|
|
9525
|
+
const target = e.target;
|
|
9526
|
+
if (!popover.contains(target) && target !== button && !button.contains(target)) {
|
|
9527
|
+
closePopover();
|
|
9528
|
+
}
|
|
9529
|
+
};
|
|
9530
|
+
const handleOuterClick = (e) => {
|
|
9531
|
+
const target = e.target;
|
|
9532
|
+
if (target !== root && !root.contains(target)) {
|
|
9533
|
+
closePopover();
|
|
9534
|
+
}
|
|
9535
|
+
};
|
|
9536
|
+
popover.addEventListener("pointerdown", (e) => {
|
|
9537
|
+
e.stopPropagation();
|
|
9538
|
+
});
|
|
9539
|
+
container.addEventListener("pointerdown", handleContainerClick, true);
|
|
9540
|
+
document.addEventListener("pointerdown", handleOuterClick, true);
|
|
9541
|
+
window.addEventListener("resize", updatePosition);
|
|
9542
|
+
(_a = popover.querySelector("#import-md-btn")) == null ? void 0 : _a.addEventListener("click", (e) => {
|
|
9543
|
+
e.stopPropagation();
|
|
9544
|
+
closePopover();
|
|
9545
|
+
const input = document.createElement("input");
|
|
9546
|
+
input.type = "file";
|
|
9547
|
+
input.accept = ".md";
|
|
9548
|
+
input.onchange = (evt) => {
|
|
9549
|
+
var _a2;
|
|
9550
|
+
const file = (_a2 = evt.target.files) == null ? void 0 : _a2[0];
|
|
9551
|
+
if (!file) return;
|
|
9552
|
+
file.text().then((text) => {
|
|
9553
|
+
utils$1.replaceAll(text)(ctx);
|
|
9554
|
+
const event = new CustomEvent("import-click", {
|
|
9555
|
+
detail: { type: "markdown", file },
|
|
9556
|
+
bubbles: true,
|
|
9557
|
+
composed: true
|
|
9558
|
+
});
|
|
9559
|
+
root.dispatchEvent(event);
|
|
9560
|
+
}).catch((err) => {
|
|
9561
|
+
console.error("Failed to read file:", err);
|
|
9562
|
+
});
|
|
9563
|
+
};
|
|
9564
|
+
input.click();
|
|
9565
|
+
});
|
|
9566
|
+
(_b = popover.querySelector("#import-word-btn")) == null ? void 0 : _b.addEventListener("click", (e) => {
|
|
9567
|
+
e.stopPropagation();
|
|
9568
|
+
closePopover();
|
|
9569
|
+
const event = new CustomEvent("import-click", {
|
|
9570
|
+
detail: { type: "word" },
|
|
9571
|
+
bubbles: true,
|
|
9572
|
+
composed: true
|
|
9573
|
+
});
|
|
9574
|
+
root.dispatchEvent(event);
|
|
9575
|
+
});
|
|
9576
|
+
(_c = popover.querySelector("#import-pdf-btn")) == null ? void 0 : _c.addEventListener("click", (e) => {
|
|
9577
|
+
e.stopPropagation();
|
|
9578
|
+
closePopover();
|
|
9579
|
+
const event = new CustomEvent("import-click", {
|
|
9580
|
+
detail: { type: "pdf" },
|
|
9581
|
+
bubbles: true,
|
|
9582
|
+
composed: true
|
|
9583
|
+
});
|
|
9584
|
+
root.dispatchEvent(event);
|
|
9585
|
+
});
|
|
9586
|
+
}
|
|
9173
9587
|
|
|
9174
9588
|
keepAlive(vue.h);
|
|
9175
9589
|
const DocumentHeader = vue.defineComponent({
|