@mikedown/core 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +63 -2
- package/dist/index.d.ts +67 -2
- package/dist/index.js +410 -39
- package/dist/index.js.map +1 -1
- package/dist/styles.css +96 -5
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -8,6 +8,10 @@ import { TaskList } from "@tiptap/extension-task-list";
|
|
|
8
8
|
// src/taskitem-drag.ts
|
|
9
9
|
import { TaskItem } from "@tiptap/extension-task-item";
|
|
10
10
|
import { NodeSelection } from "@tiptap/pm/state";
|
|
11
|
+
function taskCheckboxLabel(node) {
|
|
12
|
+
const text = (node.firstChild?.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
13
|
+
return text || "Task";
|
|
14
|
+
}
|
|
11
15
|
var DraggableTaskItem = TaskItem.extend({
|
|
12
16
|
draggable: true,
|
|
13
17
|
addNodeView() {
|
|
@@ -27,6 +31,7 @@ var DraggableTaskItem = TaskItem.extend({
|
|
|
27
31
|
const checkbox = document.createElement("input");
|
|
28
32
|
checkbox.type = "checkbox";
|
|
29
33
|
checkbox.checked = !!node.attrs.checked;
|
|
34
|
+
checkbox.setAttribute("aria-label", taskCheckboxLabel(node));
|
|
30
35
|
const bullet = document.createElement("span");
|
|
31
36
|
label.append(checkbox, bullet);
|
|
32
37
|
const content = document.createElement("div");
|
|
@@ -67,6 +72,10 @@ var DraggableTaskItem = TaskItem.extend({
|
|
|
67
72
|
if (checkbox.checked !== checked) {
|
|
68
73
|
checkbox.checked = checked;
|
|
69
74
|
}
|
|
75
|
+
const name = taskCheckboxLabel(updated);
|
|
76
|
+
if (checkbox.getAttribute("aria-label") !== name) {
|
|
77
|
+
checkbox.setAttribute("aria-label", name);
|
|
78
|
+
}
|
|
70
79
|
return true;
|
|
71
80
|
},
|
|
72
81
|
// Let the checkbox change event and the handle dragstart run without
|
|
@@ -1237,6 +1246,7 @@ function buildDecorations(doc, _view) {
|
|
|
1237
1246
|
checkbox.type = "checkbox";
|
|
1238
1247
|
checkbox.checked = checked;
|
|
1239
1248
|
checkbox.classList.add("table-checkbox");
|
|
1249
|
+
checkbox.setAttribute("aria-label", "Task done");
|
|
1240
1250
|
checkbox.addEventListener("mousedown", (e) => {
|
|
1241
1251
|
e.preventDefault();
|
|
1242
1252
|
const newText = checked ? "[ ]" : "[x]";
|
|
@@ -4415,7 +4425,8 @@ function refreshTableToolbarStates(_editor) {
|
|
|
4415
4425
|
}
|
|
4416
4426
|
function updateTableToolbar(editor) {
|
|
4417
4427
|
const isInTable = editor.isActive("table");
|
|
4418
|
-
|
|
4428
|
+
const focusedHere = editor.view.hasFocus() || !!document.activeElement?.closest("#mikedown-table-toolbar");
|
|
4429
|
+
if (!isInTable || !focusedHere) {
|
|
4419
4430
|
hideTableToolbar();
|
|
4420
4431
|
return;
|
|
4421
4432
|
}
|
|
@@ -9774,9 +9785,17 @@ function buildActionItem(item) {
|
|
|
9774
9785
|
el.classList.add("tdd-active");
|
|
9775
9786
|
}
|
|
9776
9787
|
}
|
|
9788
|
+
const disabled = item.isDisabled?.() ?? false;
|
|
9789
|
+
if (disabled) {
|
|
9790
|
+
el.classList.add("tdd-disabled");
|
|
9791
|
+
el.setAttribute("aria-disabled", "true");
|
|
9792
|
+
}
|
|
9777
9793
|
el.addEventListener("mousedown", (e) => {
|
|
9778
9794
|
e.preventDefault();
|
|
9779
9795
|
e.stopPropagation();
|
|
9796
|
+
if (disabled) {
|
|
9797
|
+
return;
|
|
9798
|
+
}
|
|
9780
9799
|
hideToolbarDropdown();
|
|
9781
9800
|
item.action();
|
|
9782
9801
|
});
|
|
@@ -9908,6 +9927,54 @@ function handleClickOutside(e) {
|
|
|
9908
9927
|
}
|
|
9909
9928
|
}
|
|
9910
9929
|
|
|
9930
|
+
// src/toolbar-overflow.ts
|
|
9931
|
+
var OVERFLOWED = "toolbar-overflowed";
|
|
9932
|
+
function isLaidOut(el) {
|
|
9933
|
+
return !el.hidden && !el.classList.contains(OVERFLOWED) && el.style.display !== "none";
|
|
9934
|
+
}
|
|
9935
|
+
function rowFits(toolbar) {
|
|
9936
|
+
const children = Array.from(toolbar.children).filter(isLaidOut);
|
|
9937
|
+
const last = children[children.length - 1];
|
|
9938
|
+
if (!last) {
|
|
9939
|
+
return true;
|
|
9940
|
+
}
|
|
9941
|
+
const padRight = parseFloat(getComputedStyle(toolbar).paddingRight) || 0;
|
|
9942
|
+
return last.getBoundingClientRect().right <= toolbar.getBoundingClientRect().right - padRight + 0.5;
|
|
9943
|
+
}
|
|
9944
|
+
function layoutToolbarOverflow(toolbar) {
|
|
9945
|
+
const more = toolbar.querySelector(":scope > .toolbar-more");
|
|
9946
|
+
if (!more) {
|
|
9947
|
+
return;
|
|
9948
|
+
}
|
|
9949
|
+
const items = Array.from(toolbar.children).filter((el) => el !== more);
|
|
9950
|
+
items.forEach((el) => el.classList.remove(OVERFLOWED));
|
|
9951
|
+
more.hidden = true;
|
|
9952
|
+
if (rowFits(toolbar)) {
|
|
9953
|
+
return;
|
|
9954
|
+
}
|
|
9955
|
+
more.hidden = false;
|
|
9956
|
+
for (let i = items.length - 1; i >= 1; i--) {
|
|
9957
|
+
items[i].classList.add(OVERFLOWED);
|
|
9958
|
+
if (rowFits(toolbar)) {
|
|
9959
|
+
break;
|
|
9960
|
+
}
|
|
9961
|
+
}
|
|
9962
|
+
for (let i = items.length - 1; i >= 1; i--) {
|
|
9963
|
+
const el = items[i];
|
|
9964
|
+
if (!isLaidOut(el)) {
|
|
9965
|
+
continue;
|
|
9966
|
+
}
|
|
9967
|
+
if (!el.classList.contains("toolbar-separator")) {
|
|
9968
|
+
break;
|
|
9969
|
+
}
|
|
9970
|
+
el.classList.add(OVERFLOWED);
|
|
9971
|
+
}
|
|
9972
|
+
const listed = items.some((el) => el.classList.contains(OVERFLOWED) && el.tagName === "BUTTON" && el.style.display !== "none");
|
|
9973
|
+
if (!listed) {
|
|
9974
|
+
more.hidden = true;
|
|
9975
|
+
}
|
|
9976
|
+
}
|
|
9977
|
+
|
|
9911
9978
|
// src/imageSrcPolicy.ts
|
|
9912
9979
|
var FULLY_QUALIFIED = /^(https?|data|blob):/i;
|
|
9913
9980
|
function resolveImageRenderSrc(src, host) {
|
|
@@ -10231,7 +10298,7 @@ function installWheelZoom(target, opts) {
|
|
|
10231
10298
|
function resolveFeatures(partial) {
|
|
10232
10299
|
return { ...DEFAULT_FEATURES, ...partial ?? {} };
|
|
10233
10300
|
}
|
|
10234
|
-
function buildEditorShell(container, features) {
|
|
10301
|
+
function buildEditorShell(container, features, landmark = true) {
|
|
10235
10302
|
const root = document.createElement("div");
|
|
10236
10303
|
root.className = "mikedown-root";
|
|
10237
10304
|
root.setAttribute("data-mikedown-root", "");
|
|
@@ -10262,8 +10329,10 @@ function buildEditorShell(container, features) {
|
|
|
10262
10329
|
}
|
|
10263
10330
|
const editorContainer = document.createElement("div");
|
|
10264
10331
|
editorContainer.className = "mikedown-editor-container";
|
|
10265
|
-
|
|
10266
|
-
|
|
10332
|
+
if (landmark) {
|
|
10333
|
+
editorContainer.setAttribute("role", "main");
|
|
10334
|
+
editorContainer.setAttribute("aria-label", "Markdown editor");
|
|
10335
|
+
}
|
|
10267
10336
|
const sourceContainer = document.createElement("div");
|
|
10268
10337
|
sourceContainer.className = "mikedown-source-container";
|
|
10269
10338
|
sourceContainer.style.display = "none";
|
|
@@ -10321,7 +10390,7 @@ ${body}`;
|
|
|
10321
10390
|
function formatHotkeyChord(chord) {
|
|
10322
10391
|
return chord.split("+").map((part) => part.length === 1 ? part.toUpperCase() : part.charAt(0).toUpperCase() + part.slice(1)).join("+");
|
|
10323
10392
|
}
|
|
10324
|
-
var toolbarSvg = (d, sw = 1.8) => `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="${sw}" stroke-linecap="round" stroke-linejoin="round">${d}</svg>`;
|
|
10393
|
+
var toolbarSvg = (d, sw = 1.8) => `<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="${sw}" stroke-linecap="round" stroke-linejoin="round">${d}</svg>`;
|
|
10325
10394
|
var toolbarIcons = {
|
|
10326
10395
|
bold: toolbarSvg('<path d="M4 2.5h5a3 3 0 0 1 0 6H4zM4 8.5h6a3 3 0 0 1 0 6H4z" fill="none"/>', 2),
|
|
10327
10396
|
italic: toolbarSvg('<line x1="10" y1="2" x2="6" y2="14"/><line x1="7" y1="2" x2="12" y2="2"/><line x1="4" y1="14" x2="9" y2="14"/>'),
|
|
@@ -10341,7 +10410,7 @@ var toolbarIcons = {
|
|
|
10341
10410
|
undo: toolbarSvg('<polyline points="4 7 2 5 4 3"/><path d="M2 5h8a4 4 0 0 1 0 8H7"/>'),
|
|
10342
10411
|
redo: toolbarSvg('<polyline points="12 7 14 5 12 3"/><path d="M14 5H6a4 4 0 0 0 0 8h3"/>'),
|
|
10343
10412
|
source: toolbarSvg('<polyline points="5 4 2 8 5 12"/><polyline points="11 4 14 8 11 12"/><line x1="9" y1="3" x2="7" y2="13"/>'),
|
|
10344
|
-
gear: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
|
10413
|
+
gear: `<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
|
10345
10414
|
diff: toolbarSvg('<path d="M4 3v10"/><path d="M12 3v10"/><path d="M7 5h2" stroke-opacity="0.5"/><path d="M7 8h2"/><path d="M7 11h2" stroke-opacity="0.5"/>'),
|
|
10346
10415
|
sun: toolbarSvg('<circle cx="8" cy="8" r="3"/><path d="M8 1.5v1.5M8 13v1.5M1.5 8H3M13 8h1.5M3.4 3.4l1.06 1.06M11.54 11.54l1.06 1.06M3.4 12.6l1.06-1.06M11.54 4.46l1.06-1.06"/>'),
|
|
10347
10416
|
moon: toolbarSvg('<path d="M13.5 8a5.5 5.5 0 0 1-8.38 4.68A5.5 5.5 0 0 1 8 2.5c0 .5.05 1 .16 1.47A4.5 4.5 0 0 0 13.5 8z"/>'),
|
|
@@ -10353,6 +10422,7 @@ var toolbarIcons = {
|
|
|
10353
10422
|
headingNumbers: toolbarSvg('<text x="8" y="11.5" text-anchor="middle" font-size="8" font-weight="700" fill="currentColor" stroke="none" font-family="sans-serif">1.2</text>', 0),
|
|
10354
10423
|
zoomIn: toolbarSvg('<circle cx="7" cy="7" r="4.5"/><line x1="10.2" y1="10.2" x2="14" y2="14"/><line x1="5" y1="7" x2="9" y2="7"/><line x1="7" y1="5" x2="7" y2="9"/>'),
|
|
10355
10424
|
zoomOut: toolbarSvg('<circle cx="7" cy="7" r="4.5"/><line x1="10.2" y1="10.2" x2="14" y2="14"/><line x1="5" y1="7" x2="9" y2="7"/>'),
|
|
10425
|
+
more: toolbarSvg('<circle cx="3.5" cy="8" r="1.2" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r="1.2" fill="currentColor" stroke="none"/><circle cx="12.5" cy="8" r="1.2" fill="currentColor" stroke="none"/>'),
|
|
10356
10426
|
emoji: toolbarSvg('<circle cx="8" cy="8" r="6"/><circle cx="6" cy="6.5" r="0.6" fill="currentColor" stroke="none"/><circle cx="10" cy="6.5" r="0.6" fill="currentColor" stroke="none"/><path d="M5.5 9.5c.7 1.2 1.7 1.8 2.5 1.8s1.8-.6 2.5-1.8"/>')
|
|
10357
10427
|
};
|
|
10358
10428
|
var CALLOUT_KIND_LABEL = {
|
|
@@ -10413,7 +10483,18 @@ function createMikeDownEditor(container, options) {
|
|
|
10413
10483
|
const host = options.host;
|
|
10414
10484
|
const hostOwnsShortcuts = options.hostOwnsShortcuts === true;
|
|
10415
10485
|
const features = resolveFeatures(options.features);
|
|
10416
|
-
const shell = buildEditorShell(container, features);
|
|
10486
|
+
const shell = buildEditorShell(container, features, options.landmark !== false);
|
|
10487
|
+
const surfaceAttrs = {};
|
|
10488
|
+
if (options.id) {
|
|
10489
|
+
surfaceAttrs.id = options.id;
|
|
10490
|
+
}
|
|
10491
|
+
if (options.ariaLabelledBy) {
|
|
10492
|
+
surfaceAttrs["aria-labelledby"] = options.ariaLabelledBy;
|
|
10493
|
+
}
|
|
10494
|
+
surfaceAttrs["aria-label"] = options.ariaLabel || (options.ariaLabelledBy ? "" : "Document text");
|
|
10495
|
+
if (!surfaceAttrs["aria-label"]) {
|
|
10496
|
+
delete surfaceAttrs["aria-label"];
|
|
10497
|
+
}
|
|
10417
10498
|
const { root, editorContainer, sourceContainer } = shell;
|
|
10418
10499
|
const disposers = [];
|
|
10419
10500
|
function listen(target, type, fn, opts) {
|
|
@@ -11721,6 +11802,9 @@ function createMikeDownEditor(container, options) {
|
|
|
11721
11802
|
if (btn) {
|
|
11722
11803
|
btn.style.display = mode === "off" ? "none" : "";
|
|
11723
11804
|
}
|
|
11805
|
+
if (shell.toolbar) {
|
|
11806
|
+
layoutToolbarOverflow(shell.toolbar);
|
|
11807
|
+
}
|
|
11724
11808
|
}
|
|
11725
11809
|
let sidebarFooterLink = null;
|
|
11726
11810
|
let outlineSidebar = null;
|
|
@@ -11930,13 +12014,21 @@ function createMikeDownEditor(container, options) {
|
|
|
11930
12014
|
sep.setAttribute("role", "separator");
|
|
11931
12015
|
return sep;
|
|
11932
12016
|
}
|
|
12017
|
+
const overflowOpeners = /* @__PURE__ */ new Map();
|
|
12018
|
+
function wireDropdown(btn, open) {
|
|
12019
|
+
overflowOpeners.set(btn, open);
|
|
12020
|
+
btn.addEventListener("click", () => {
|
|
12021
|
+
if (isToolbarDropdownOpen()) {
|
|
12022
|
+
hideToolbarDropdown();
|
|
12023
|
+
return;
|
|
12024
|
+
}
|
|
12025
|
+
open(btn);
|
|
12026
|
+
});
|
|
12027
|
+
}
|
|
11933
12028
|
const textFormatBtn = makeDropdownTrigger("textFormat", "Text Format", getBlockLabel());
|
|
11934
|
-
textFormatBtn.
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
return;
|
|
11938
|
-
}
|
|
11939
|
-
showToolbarDropdown(textFormatBtn, [
|
|
12029
|
+
textFormatBtn.setAttribute("aria-label", `${getBlockLabel()} Text Format`);
|
|
12030
|
+
wireDropdown(textFormatBtn, (anchor) => {
|
|
12031
|
+
showToolbarDropdown(anchor, [
|
|
11940
12032
|
{ type: "action", id: "h1", label: "Heading 1", icon: '<span style="font-weight:700;font-size:14px">H1</span>', isActive: () => editor2.isActive("heading", { level: 1 }), action: () => editor2.chain().focus().toggleHeading({ level: 1 }).run() },
|
|
11941
12033
|
{ type: "action", id: "h2", label: "Heading 2", icon: '<span style="font-weight:600;font-size:13px">H2</span>', isActive: () => editor2.isActive("heading", { level: 2 }), action: () => editor2.chain().focus().toggleHeading({ level: 2 }).run() },
|
|
11942
12034
|
{ type: "action", id: "h3", label: "Heading 3", icon: '<span style="font-weight:500;font-size:12px">H3</span>', isActive: () => editor2.isActive("heading", { level: 3 }), action: () => editor2.chain().focus().toggleHeading({ level: 3 }).run() },
|
|
@@ -11955,12 +12047,8 @@ function createMikeDownEditor(container, options) {
|
|
|
11955
12047
|
]);
|
|
11956
12048
|
});
|
|
11957
12049
|
const listBlockBtn = makeDropdownTrigger("listBlock", "Lists & Blocks", icons.ul);
|
|
11958
|
-
listBlockBtn
|
|
11959
|
-
|
|
11960
|
-
hideToolbarDropdown();
|
|
11961
|
-
return;
|
|
11962
|
-
}
|
|
11963
|
-
showToolbarDropdown(listBlockBtn, [
|
|
12050
|
+
wireDropdown(listBlockBtn, (anchor) => {
|
|
12051
|
+
showToolbarDropdown(anchor, [
|
|
11964
12052
|
{ type: "action", id: "bulletList", label: "Bullet List", icon: icons.ul, isActive: () => editor2.isActive("bulletList"), action: () => editor2.chain().focus().toggleBulletList().run() },
|
|
11965
12053
|
{ type: "action", id: "orderedList", label: "Ordered List", icon: icons.ol, isActive: () => editor2.isActive("orderedList"), action: () => editor2.chain().focus().toggleOrderedList().run() },
|
|
11966
12054
|
{ type: "action", id: "taskList", label: "Task List", icon: icons.task, isActive: () => editor2.isActive("taskList"), action: () => editor2.chain().focus().toggleTaskList().run() },
|
|
@@ -11984,14 +12072,10 @@ function createMikeDownEditor(container, options) {
|
|
|
11984
12072
|
const linkBtn = makeBtn("link", "Insert Link (Cmd+K)", icons.link);
|
|
11985
12073
|
linkBtn.addEventListener("click", () => showLinkDialog(editor2));
|
|
11986
12074
|
const insertBtn = makeDropdownTrigger("insert", "Insert", icons.image);
|
|
11987
|
-
insertBtn
|
|
11988
|
-
|
|
11989
|
-
hideToolbarDropdown();
|
|
11990
|
-
return;
|
|
11991
|
-
}
|
|
11992
|
-
showToolbarDropdown(insertBtn, [
|
|
12075
|
+
wireDropdown(insertBtn, (anchor) => {
|
|
12076
|
+
showToolbarDropdown(anchor, [
|
|
11993
12077
|
{ type: "action", id: "image", label: "Image", icon: icons.image, action: () => showImageInsertDialog(editor2) },
|
|
11994
|
-
{ type: "action", id: "table", label: "Table", icon: icons.table, isActive: () => editor2.isActive("table"), action: () => showTableGridPicker(editor2,
|
|
12078
|
+
{ type: "action", id: "table", label: "Table", icon: icons.table, isActive: () => editor2.isActive("table"), action: () => showTableGridPicker(editor2, anchor) },
|
|
11995
12079
|
{ type: "action", id: "hr", label: "Horizontal Rule", icon: icons.hr, action: () => editor2.chain().focus().setHorizontalRule().run() }
|
|
11996
12080
|
]);
|
|
11997
12081
|
});
|
|
@@ -12002,12 +12086,8 @@ function createMikeDownEditor(container, options) {
|
|
|
12002
12086
|
const sourceBtn = makeBtn("sourceToggle", "Toggle Source Mode (Cmd+/)", icons.source);
|
|
12003
12087
|
sourceBtn.addEventListener("click", () => toggleSourceMode());
|
|
12004
12088
|
const shareBtn = makeDropdownTrigger("share", "Share", icons.share);
|
|
12005
|
-
shareBtn
|
|
12006
|
-
|
|
12007
|
-
hideToolbarDropdown();
|
|
12008
|
-
return;
|
|
12009
|
-
}
|
|
12010
|
-
showToolbarDropdown(shareBtn, [
|
|
12089
|
+
wireDropdown(shareBtn, (anchor) => {
|
|
12090
|
+
showToolbarDropdown(anchor, [
|
|
12011
12091
|
...host.viewInBrowser ? [{ type: "action", id: "viewInBrowser", label: "View in Browser", icon: icons.browser, action: () => {
|
|
12012
12092
|
host.viewInBrowser?.(getHtml());
|
|
12013
12093
|
} }] : [],
|
|
@@ -12183,12 +12263,65 @@ function createMikeDownEditor(container, options) {
|
|
|
12183
12263
|
headingNumbersBtn.style.display = currentHeadingNumbering === "off" ? "none" : "";
|
|
12184
12264
|
const emojiBtn = makeBtn("emoji", "Insert Emoji (Cmd+;)", icons.emoji);
|
|
12185
12265
|
emojiBtn.addEventListener("mousedown", (e) => e.preventDefault());
|
|
12186
|
-
|
|
12266
|
+
const openEmoji = (anchor) => {
|
|
12187
12267
|
if (isEmojiPickerOpen()) {
|
|
12188
12268
|
hideEmojiPicker();
|
|
12189
12269
|
return;
|
|
12190
12270
|
}
|
|
12191
|
-
showEmojiPicker(editor2, { anchorRect:
|
|
12271
|
+
showEmojiPicker(editor2, { anchorRect: anchor.getBoundingClientRect() });
|
|
12272
|
+
};
|
|
12273
|
+
overflowOpeners.set(emojiBtn, openEmoji);
|
|
12274
|
+
emojiBtn.addEventListener("click", () => openEmoji(emojiBtn));
|
|
12275
|
+
const moreBtn = makeBtn("more", "More", icons.more);
|
|
12276
|
+
moreBtn.classList.add("toolbar-more");
|
|
12277
|
+
moreBtn.setAttribute("aria-haspopup", "menu");
|
|
12278
|
+
moreBtn.hidden = true;
|
|
12279
|
+
moreBtn.addEventListener("mousedown", (e) => e.preventDefault());
|
|
12280
|
+
moreBtn.addEventListener("click", () => {
|
|
12281
|
+
if (isToolbarDropdownOpen()) {
|
|
12282
|
+
hideToolbarDropdown();
|
|
12283
|
+
return;
|
|
12284
|
+
}
|
|
12285
|
+
const entries = [];
|
|
12286
|
+
for (const el of Array.from(toolbar.children)) {
|
|
12287
|
+
if (!el.classList.contains("toolbar-overflowed")) {
|
|
12288
|
+
continue;
|
|
12289
|
+
}
|
|
12290
|
+
if (el.classList.contains("toolbar-separator")) {
|
|
12291
|
+
if (entries.length && entries[entries.length - 1].type !== "separator") {
|
|
12292
|
+
entries.push({ type: "separator" });
|
|
12293
|
+
}
|
|
12294
|
+
continue;
|
|
12295
|
+
}
|
|
12296
|
+
if (!(el instanceof HTMLButtonElement) || el.style.display === "none") {
|
|
12297
|
+
continue;
|
|
12298
|
+
}
|
|
12299
|
+
const btn = el;
|
|
12300
|
+
const svg2 = btn.querySelector("svg");
|
|
12301
|
+
const opener = overflowOpeners.get(btn);
|
|
12302
|
+
entries.push({
|
|
12303
|
+
type: "action",
|
|
12304
|
+
id: `more-${btn.dataset.action ?? ""}`,
|
|
12305
|
+
label: btn.dataset.menuLabel ?? btn.dataset.tip ?? btn.getAttribute("aria-label") ?? "",
|
|
12306
|
+
// An empty icon slot keeps text-only entries (the size readout) aligned.
|
|
12307
|
+
icon: svg2 ? svg2.outerHTML : '<span aria-hidden="true"></span>',
|
|
12308
|
+
isActive: () => btn.classList.contains("active"),
|
|
12309
|
+
isDisabled: () => btn.disabled,
|
|
12310
|
+
action: () => {
|
|
12311
|
+
if (opener) {
|
|
12312
|
+
opener(moreBtn);
|
|
12313
|
+
} else {
|
|
12314
|
+
btn.click();
|
|
12315
|
+
}
|
|
12316
|
+
}
|
|
12317
|
+
});
|
|
12318
|
+
}
|
|
12319
|
+
while (entries.length && entries[entries.length - 1].type === "separator") {
|
|
12320
|
+
entries.pop();
|
|
12321
|
+
}
|
|
12322
|
+
if (entries.length) {
|
|
12323
|
+
showToolbarDropdown(moreBtn, entries);
|
|
12324
|
+
}
|
|
12192
12325
|
});
|
|
12193
12326
|
toolbar.appendChild(textFormatBtn);
|
|
12194
12327
|
toolbar.appendChild(listBlockBtn);
|
|
@@ -12216,11 +12349,27 @@ function createMikeDownEditor(container, options) {
|
|
|
12216
12349
|
toolbar.appendChild(makeSeparator());
|
|
12217
12350
|
toolbar.appendChild(themeBtn);
|
|
12218
12351
|
toolbar.appendChild(settingsBtn);
|
|
12352
|
+
toolbar.appendChild(moreBtn);
|
|
12353
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
12354
|
+
let frame = 0;
|
|
12355
|
+
const ro = new ResizeObserver(() => {
|
|
12356
|
+
cancelAnimationFrame(frame);
|
|
12357
|
+
frame = requestAnimationFrame(() => layoutToolbarOverflow(toolbar));
|
|
12358
|
+
});
|
|
12359
|
+
ro.observe(toolbar);
|
|
12360
|
+
disposers.push(() => {
|
|
12361
|
+
cancelAnimationFrame(frame);
|
|
12362
|
+
ro.disconnect();
|
|
12363
|
+
});
|
|
12364
|
+
}
|
|
12365
|
+
layoutToolbarOverflow(toolbar);
|
|
12219
12366
|
toolbar.__condensedUpdate = () => {
|
|
12220
12367
|
const labelEl = textFormatBtn.querySelector(".condensed-btn-label");
|
|
12221
|
-
|
|
12222
|
-
|
|
12368
|
+
const blockLabel = getBlockLabel();
|
|
12369
|
+
if (labelEl && labelEl.innerHTML !== blockLabel) {
|
|
12370
|
+
labelEl.innerHTML = blockLabel;
|
|
12223
12371
|
}
|
|
12372
|
+
textFormatBtn.setAttribute("aria-label", `${blockLabel} Text Format`);
|
|
12224
12373
|
textFormatBtn.classList.toggle("active", isTextFormatActive());
|
|
12225
12374
|
listBlockBtn.classList.toggle("active", isBlockActive());
|
|
12226
12375
|
linkBtn.classList.toggle("active", editor2.isActive("link"));
|
|
@@ -12239,10 +12388,15 @@ function createMikeDownEditor(container, options) {
|
|
|
12239
12388
|
const size = currentFontSize();
|
|
12240
12389
|
const resetBtn = toolbar.querySelector('button[data-action="zoomReset"]');
|
|
12241
12390
|
if (resetBtn) {
|
|
12391
|
+
const sizeChanged = resetBtn.textContent !== String(size);
|
|
12242
12392
|
resetBtn.textContent = String(size);
|
|
12393
|
+
resetBtn.dataset.menuLabel = `Reset Font Size (${size}px)`;
|
|
12243
12394
|
const tip = `Font size ${size}px (click to reset to ${DEFAULT_FONT_SIZE}px)`;
|
|
12244
12395
|
resetBtn.dataset.tip = tip;
|
|
12245
|
-
resetBtn.setAttribute("aria-label",
|
|
12396
|
+
resetBtn.setAttribute("aria-label", `${size} px font size (click to reset to ${DEFAULT_FONT_SIZE}px)`);
|
|
12397
|
+
if (sizeChanged && resetBtn.isConnected) {
|
|
12398
|
+
layoutToolbarOverflow(toolbar);
|
|
12399
|
+
}
|
|
12246
12400
|
}
|
|
12247
12401
|
const outBtn = toolbar.querySelector('button[data-action="zoomOut"]');
|
|
12248
12402
|
if (outBtn) {
|
|
@@ -12624,7 +12778,7 @@ function createMikeDownEditor(container, options) {
|
|
|
12624
12778
|
// dispatching a no-op transaction (tr.setMeta('slashPlaceholder', true))
|
|
12625
12779
|
// rather than touching editor.view.dom directly.
|
|
12626
12780
|
Placeholder.configure({
|
|
12627
|
-
placeholder: () => features.slashCommands && currentSlashCommandsEnabled ? "Type / for commands\u2026" : "Start writing\u2026"
|
|
12781
|
+
placeholder: () => options.placeholder ?? (features.slashCommands && currentSlashCommandsEnabled ? "Type / for commands\u2026" : "Start writing\u2026")
|
|
12628
12782
|
}),
|
|
12629
12783
|
// ── Markdown serialiser / input rules (M2b / M2c) ─────────────────────────
|
|
12630
12784
|
// tiptap-markdown provides:
|
|
@@ -12724,7 +12878,7 @@ function createMikeDownEditor(container, options) {
|
|
|
12724
12878
|
// ── Keyboard shortcuts ──────────────────────────────────────────────────────
|
|
12725
12879
|
editorProps: {
|
|
12726
12880
|
// axe aria-input-field-name: the contenteditable textbox needs an accessible name.
|
|
12727
|
-
attributes: {
|
|
12881
|
+
attributes: { ...surfaceAttrs, role: "textbox", "aria-multiline": "true" },
|
|
12728
12882
|
handleKeyDown(view, event) {
|
|
12729
12883
|
if (features.findReplace && (event.metaKey || event.ctrlKey) && event.key === "f") {
|
|
12730
12884
|
event.preventDefault();
|
|
@@ -12964,6 +13118,7 @@ function createMikeDownEditor(container, options) {
|
|
|
12964
13118
|
const { from, to } = editor.state.selection;
|
|
12965
13119
|
postStats({ selection: from === to ? null : editor.state.doc.textBetween(from, to, "\n") });
|
|
12966
13120
|
});
|
|
13121
|
+
editor.on("focus", () => updateTableToolbar(editor));
|
|
12967
13122
|
editor.on("blur", () => {
|
|
12968
13123
|
setTimeout(() => {
|
|
12969
13124
|
if (!document.activeElement?.closest("#mikedown-table-toolbar")) {
|
|
@@ -14106,6 +14261,7 @@ function createMikeDownEditor(container, options) {
|
|
|
14106
14261
|
buildCmTheme(),
|
|
14107
14262
|
cmReadOnly.of(EditorState3.readOnly.of(readOnly)),
|
|
14108
14263
|
EditorView2.lineWrapping,
|
|
14264
|
+
EditorView2.contentAttributes.of(options.id || options.ariaLabel || options.ariaLabelledBy ? { ...surfaceAttrs, "aria-multiline": "true" } : {}),
|
|
14109
14265
|
EditorView2.updateListener.of((update2) => {
|
|
14110
14266
|
if (update2.docChanged && !cmLoading) {
|
|
14111
14267
|
const md = update2.state.doc.toString();
|
|
@@ -15047,9 +15203,224 @@ var NoopHost = class {
|
|
|
15047
15203
|
onChange(_markdown, _meta) {
|
|
15048
15204
|
}
|
|
15049
15205
|
};
|
|
15206
|
+
|
|
15207
|
+
// src/binding.ts
|
|
15208
|
+
function selectorAttributes(selector) {
|
|
15209
|
+
const names = /* @__PURE__ */ new Set();
|
|
15210
|
+
if (/\.[\w-]+/.test(selector)) {
|
|
15211
|
+
names.add("class");
|
|
15212
|
+
}
|
|
15213
|
+
if (/#[\w-]+/.test(selector)) {
|
|
15214
|
+
names.add("id");
|
|
15215
|
+
}
|
|
15216
|
+
for (const m of selector.matchAll(/\[\s*([\w:-]+)/g)) {
|
|
15217
|
+
if (m[1]) {
|
|
15218
|
+
names.add(m[1]);
|
|
15219
|
+
}
|
|
15220
|
+
}
|
|
15221
|
+
return names.size ? [...names] : void 0;
|
|
15222
|
+
}
|
|
15223
|
+
function bindMikeDownValue(container, options = {}) {
|
|
15224
|
+
const {
|
|
15225
|
+
initialValue = "",
|
|
15226
|
+
debounceMs = 150,
|
|
15227
|
+
onValue,
|
|
15228
|
+
onTouched,
|
|
15229
|
+
disabled: initialDisabled = false,
|
|
15230
|
+
theme: initialTheme = "auto",
|
|
15231
|
+
darkSelector,
|
|
15232
|
+
outputTransform,
|
|
15233
|
+
host: hostOverrides,
|
|
15234
|
+
...editorOptions
|
|
15235
|
+
} = options;
|
|
15236
|
+
const out = (md) => outputTransform ? outputTransform(md) : md;
|
|
15237
|
+
let destroyed = false;
|
|
15238
|
+
let timer;
|
|
15239
|
+
let pending = null;
|
|
15240
|
+
let lastValue = out(initialValue);
|
|
15241
|
+
let theme = initialTheme;
|
|
15242
|
+
let readOnly = editorOptions.readOnly === true;
|
|
15243
|
+
let disabled = initialDisabled;
|
|
15244
|
+
const flush = () => {
|
|
15245
|
+
if (timer !== void 0) {
|
|
15246
|
+
clearTimeout(timer);
|
|
15247
|
+
timer = void 0;
|
|
15248
|
+
}
|
|
15249
|
+
if (pending === null) {
|
|
15250
|
+
return;
|
|
15251
|
+
}
|
|
15252
|
+
const value = out(pending);
|
|
15253
|
+
pending = null;
|
|
15254
|
+
if (value === lastValue) {
|
|
15255
|
+
return;
|
|
15256
|
+
}
|
|
15257
|
+
lastValue = value;
|
|
15258
|
+
onValue?.(value);
|
|
15259
|
+
};
|
|
15260
|
+
let labelEl = null;
|
|
15261
|
+
let ariaLabelledBy = editorOptions.ariaLabelledBy;
|
|
15262
|
+
if (editorOptions.id && !ariaLabelledBy) {
|
|
15263
|
+
const root = container.getRootNode();
|
|
15264
|
+
const escaped = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(editorOptions.id) : editorOptions.id;
|
|
15265
|
+
labelEl = root.querySelector?.(`label[for="${escaped}"]`) ?? null;
|
|
15266
|
+
if (labelEl) {
|
|
15267
|
+
if (!labelEl.id) {
|
|
15268
|
+
labelEl.id = `${editorOptions.id}-label`;
|
|
15269
|
+
}
|
|
15270
|
+
ariaLabelledBy = labelEl.id;
|
|
15271
|
+
}
|
|
15272
|
+
}
|
|
15273
|
+
const isDarkNow = () => {
|
|
15274
|
+
if (darkSelector) {
|
|
15275
|
+
try {
|
|
15276
|
+
return !!container.closest(darkSelector);
|
|
15277
|
+
} catch {
|
|
15278
|
+
return false;
|
|
15279
|
+
}
|
|
15280
|
+
}
|
|
15281
|
+
return window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
|
|
15282
|
+
};
|
|
15283
|
+
const resolve = (t) => t === "auto" ? isDarkNow() ? "dark" : "light" : t;
|
|
15284
|
+
const handle = createMikeDownEditor(container, {
|
|
15285
|
+
...editorOptions,
|
|
15286
|
+
ariaLabelledBy,
|
|
15287
|
+
landmark: editorOptions.landmark ?? false,
|
|
15288
|
+
readOnly: readOnly || disabled,
|
|
15289
|
+
initialMarkdown: initialValue,
|
|
15290
|
+
theme: resolve(theme),
|
|
15291
|
+
host: {
|
|
15292
|
+
...hostOverrides,
|
|
15293
|
+
onChange: (md, meta) => {
|
|
15294
|
+
hostOverrides?.onChange?.(md, meta);
|
|
15295
|
+
if (destroyed) {
|
|
15296
|
+
return;
|
|
15297
|
+
}
|
|
15298
|
+
pending = md;
|
|
15299
|
+
if (debounceMs <= 0) {
|
|
15300
|
+
flush();
|
|
15301
|
+
return;
|
|
15302
|
+
}
|
|
15303
|
+
if (timer !== void 0) {
|
|
15304
|
+
clearTimeout(timer);
|
|
15305
|
+
}
|
|
15306
|
+
timer = setTimeout(flush, debounceMs);
|
|
15307
|
+
}
|
|
15308
|
+
}
|
|
15309
|
+
});
|
|
15310
|
+
const unBlur = handle.on("blur", flush);
|
|
15311
|
+
let observer = null;
|
|
15312
|
+
let mql = null;
|
|
15313
|
+
let applied = resolve(theme);
|
|
15314
|
+
const applyTheme = () => {
|
|
15315
|
+
if (destroyed) {
|
|
15316
|
+
return;
|
|
15317
|
+
}
|
|
15318
|
+
const next = resolve(theme);
|
|
15319
|
+
if (next === applied) {
|
|
15320
|
+
return;
|
|
15321
|
+
}
|
|
15322
|
+
applied = next;
|
|
15323
|
+
handle.setTheme(next);
|
|
15324
|
+
};
|
|
15325
|
+
const stopFollowing = () => {
|
|
15326
|
+
observer?.disconnect();
|
|
15327
|
+
observer = null;
|
|
15328
|
+
mql?.removeEventListener?.("change", applyTheme);
|
|
15329
|
+
mql = null;
|
|
15330
|
+
};
|
|
15331
|
+
const startFollowing = () => {
|
|
15332
|
+
stopFollowing();
|
|
15333
|
+
if (theme !== "auto") {
|
|
15334
|
+
return;
|
|
15335
|
+
}
|
|
15336
|
+
if (darkSelector) {
|
|
15337
|
+
if (typeof MutationObserver === "undefined") {
|
|
15338
|
+
return;
|
|
15339
|
+
}
|
|
15340
|
+
const attributeFilter = selectorAttributes(darkSelector);
|
|
15341
|
+
observer = new MutationObserver(applyTheme);
|
|
15342
|
+
observer.observe(container.ownerDocument.documentElement, {
|
|
15343
|
+
attributes: true,
|
|
15344
|
+
subtree: true,
|
|
15345
|
+
...attributeFilter ? { attributeFilter } : {}
|
|
15346
|
+
});
|
|
15347
|
+
} else if (window.matchMedia) {
|
|
15348
|
+
mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
15349
|
+
mql.addEventListener?.("change", applyTheme);
|
|
15350
|
+
}
|
|
15351
|
+
};
|
|
15352
|
+
startFollowing();
|
|
15353
|
+
const onFocusOut = (event) => {
|
|
15354
|
+
const next = event.relatedTarget;
|
|
15355
|
+
if (next && container.contains(next)) {
|
|
15356
|
+
return;
|
|
15357
|
+
}
|
|
15358
|
+
if (next instanceof Element && next.closest(".mikedown-portal")) {
|
|
15359
|
+
return;
|
|
15360
|
+
}
|
|
15361
|
+
flush();
|
|
15362
|
+
onTouched?.();
|
|
15363
|
+
};
|
|
15364
|
+
container.addEventListener("focusout", onFocusOut);
|
|
15365
|
+
const onLabelClick = () => handle.focus();
|
|
15366
|
+
labelEl?.addEventListener("click", onLabelClick);
|
|
15367
|
+
return {
|
|
15368
|
+
handle,
|
|
15369
|
+
setValue(markdown) {
|
|
15370
|
+
if (destroyed) {
|
|
15371
|
+
return;
|
|
15372
|
+
}
|
|
15373
|
+
if (timer !== void 0) {
|
|
15374
|
+
clearTimeout(timer);
|
|
15375
|
+
timer = void 0;
|
|
15376
|
+
}
|
|
15377
|
+
pending = null;
|
|
15378
|
+
lastValue = markdown;
|
|
15379
|
+
if (markdown === out(handle.getMarkdown())) {
|
|
15380
|
+
return;
|
|
15381
|
+
}
|
|
15382
|
+
handle.setMarkdown(markdown, { pristine: true });
|
|
15383
|
+
},
|
|
15384
|
+
flush,
|
|
15385
|
+
setTheme(next) {
|
|
15386
|
+
theme = next;
|
|
15387
|
+
if (!destroyed) {
|
|
15388
|
+
applied = resolve(theme);
|
|
15389
|
+
handle.setTheme(applied);
|
|
15390
|
+
}
|
|
15391
|
+
startFollowing();
|
|
15392
|
+
},
|
|
15393
|
+
setReadOnly(next) {
|
|
15394
|
+
readOnly = next;
|
|
15395
|
+
if (!destroyed) {
|
|
15396
|
+
handle.setReadOnly(readOnly || disabled);
|
|
15397
|
+
}
|
|
15398
|
+
},
|
|
15399
|
+
setDisabled(next) {
|
|
15400
|
+
disabled = next;
|
|
15401
|
+
if (!destroyed) {
|
|
15402
|
+
handle.setReadOnly(readOnly || disabled);
|
|
15403
|
+
}
|
|
15404
|
+
},
|
|
15405
|
+
focus: () => handle.focus(),
|
|
15406
|
+
destroy() {
|
|
15407
|
+
if (destroyed) {
|
|
15408
|
+
return;
|
|
15409
|
+
}
|
|
15410
|
+
flush();
|
|
15411
|
+
destroyed = true;
|
|
15412
|
+
stopFollowing();
|
|
15413
|
+
unBlur();
|
|
15414
|
+
container.removeEventListener("focusout", onFocusOut);
|
|
15415
|
+
labelEl?.removeEventListener("click", onLabelClick);
|
|
15416
|
+
handle.destroy();
|
|
15417
|
+
}
|
|
15418
|
+
};
|
|
15419
|
+
}
|
|
15050
15420
|
export {
|
|
15051
15421
|
DEFAULT_FEATURES,
|
|
15052
15422
|
NoopHost,
|
|
15423
|
+
bindMikeDownValue,
|
|
15053
15424
|
createMikeDownEditor
|
|
15054
15425
|
};
|
|
15055
15426
|
//# sourceMappingURL=index.js.map
|