@threadlabs/looma 0.29.15 → 0.29.17
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/components/ui-icon-button/ui-icon-button.html +5 -3
- package/dist/index.js +1 -1
- package/editor/chunks/extensions.js +50 -12
- package/editor/chunks/{markdown.js → reference-display.js} +207 -1
- package/editor/expressmark.d.ts +13 -3
- package/editor/expressmark.js +61 -6
- package/editor/extensions/index.d.ts +1 -0
- package/editor/extensions/index.js +2 -2
- package/editor/extensions/preset.d.ts +3 -0
- package/editor/extensions/table-of-contents.d.ts +2 -1
- package/editor/index.js +2 -2
- package/editor/link-editing.d.ts +5 -0
- package/editor/reference-display.d.ts +37 -0
- package/package.json +1 -1
- package/styles/ui-icon-button.css +3 -3
- package/vanilla/UiIconButton.d.ts +1 -0
- package/vanilla/UiIconButton.js +4 -4
- package/vue/UiIconButton.d.ts +9 -0
- package/vue/UiIconButton.vue +23 -3
- package/vue/chunks/UiIconButton.js +24 -1
- package/vue/components.css +60 -7
- package/vue/editor/LoomaEditor.d.ts +12 -0
- package/vue/editor/index.js +3276 -2792
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS } from "./table-backgrounds.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as parseLoomaAttributes, b as splitLoomaFrontmatter, c as LOOMA_CONTAINER_NAMES, d as formatLoomaAttributes, f as loomaCodeFence, g as normalizeLoomaChipTone, h as normalizeLoomaCalloutTone, i as referenceDisplay, l as applyLoomaCodeNotation, m as loomaHeadingSlug, n as LoomaReferencePresentation, p as loomaContainerMarker, r as getReferenceDisplay, s as LOOMA_CHIP_TONES, t as LoomaReference, u as assignLoomaHeadingIds, v as parseLoomaFenceInfo, y as readLoomaAttributes } from "./reference-display.js";
|
|
3
3
|
import { Extension, Mark, Node as Node$1, callOrReturn, canInsertNode, combineTransactionSteps, escapeForRegEx, findChildren, findChildrenInRange, findParentNodeClosestToPos, getAttributes, getChangedRanges, getExtensionField, getMarksBetween, getText, getTextSerializersFromSchema, isNodeEmpty, isNodeSelection, markInputRule, markPasteRule, mergeAttributes, nodeInputRule, textInputRule, textblockTypeInputRule, wrappingInputRule } from "@tiptap/core";
|
|
4
4
|
import { NodeSelection, Plugin, PluginKey, Selection, TextSelection } from "@tiptap/pm/state";
|
|
5
5
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
@@ -614,17 +614,19 @@ function normalizeTableOfContentsConfig(attributes) {
|
|
|
614
614
|
* @contract Depth is a maximum heading level. Relative nesting follows existing
|
|
615
615
|
* ancestors rather than inserting artificial entries for skipped levels.
|
|
616
616
|
*/
|
|
617
|
-
function getTableOfContentsEntries(doc, depth = 3) {
|
|
617
|
+
function getTableOfContentsEntries(doc, depth = 3, references = {}) {
|
|
618
618
|
const entries = [];
|
|
619
619
|
const ancestors = [];
|
|
620
620
|
doc.descendants((node, position) => {
|
|
621
621
|
if (node.type.name === "loomaTableOfContents") return false;
|
|
622
|
-
if (node.type.name !== "heading" || node.attrs.level > depth
|
|
622
|
+
if (node.type.name !== "heading" || node.attrs.level > depth) return;
|
|
623
|
+
const text = node.textBetween(0, node.content.size, "", (leaf) => leaf.type.name === "loomaReference" || leaf.type.name === "mention" ? `${leaf.type.name === "mention" ? "@" : ""}${referenceDisplay(leaf, references).label}` : String(leaf.attrs.label ?? "")).trim();
|
|
624
|
+
if (!text) return;
|
|
623
625
|
const level = Number(node.attrs.level);
|
|
624
626
|
while (ancestors.length && ancestors[ancestors.length - 1] >= level) ancestors.pop();
|
|
625
627
|
entries.push({
|
|
626
628
|
id: String(node.attrs.id ?? ""),
|
|
627
|
-
text
|
|
629
|
+
text,
|
|
628
630
|
level,
|
|
629
631
|
depth: ancestors.length,
|
|
630
632
|
position
|
|
@@ -712,8 +714,8 @@ var LoomaHeadingAnchors = Extension.create({
|
|
|
712
714
|
return [new Plugin({ appendTransaction: (transactions, oldState, state) => transactions.some((transaction) => transaction.docChanged) ? anchorTransaction(state, oldState.doc) : null })];
|
|
713
715
|
}
|
|
714
716
|
});
|
|
715
|
-
function contentsHtml(doc, config) {
|
|
716
|
-
const branches = tableOfContentsTree(getTableOfContentsEntries(doc, config.depth));
|
|
717
|
+
function contentsHtml(doc, config, references = {}) {
|
|
718
|
+
const branches = tableOfContentsTree(getTableOfContentsEntries(doc, config.depth, references));
|
|
717
719
|
const list = (items) => [
|
|
718
720
|
config.format === "plain" ? "div" : config.format === "numbered" ? "ol" : "ul",
|
|
719
721
|
{ role: "list" },
|
|
@@ -755,7 +757,7 @@ function contentsHtml(doc, config) {
|
|
|
755
757
|
async function navigateTableOfContents(editor, id) {
|
|
756
758
|
const target = [...editor.view.dom.querySelectorAll("h1[id], h2[id], h3[id]")].find((heading) => heading.id === id);
|
|
757
759
|
if (!target) return;
|
|
758
|
-
const entry = getTableOfContentsEntries(editor.state.doc).find((heading) => heading.id === id);
|
|
760
|
+
const entry = getTableOfContentsEntries(editor.state.doc, 3, getReferenceDisplay(editor)).find((heading) => heading.id === id);
|
|
759
761
|
if (entry) await revealLoomaExpandAt(editor, entry.position + 1);
|
|
760
762
|
if (!target.isConnected || editor.isDestroyed) return;
|
|
761
763
|
target.scrollIntoView({
|
|
@@ -836,7 +838,7 @@ var LoomaTableOfContents = Node$1.create({
|
|
|
836
838
|
nav.append(DOMSerializer.fromSchema(editor.schema).serializeFragment(current.content));
|
|
837
839
|
dom.replaceChildren(nav);
|
|
838
840
|
} else {
|
|
839
|
-
const { dom: content } = DOMSerializer.renderSpec(document, contentsHtml(editor.state.doc, normalizeTableOfContentsConfig(current.attrs)));
|
|
841
|
+
const { dom: content } = DOMSerializer.renderSpec(document, contentsHtml(editor.state.doc, normalizeTableOfContentsConfig(current.attrs), getReferenceDisplay(editor)));
|
|
840
842
|
dom.replaceChildren(content);
|
|
841
843
|
}
|
|
842
844
|
};
|
|
@@ -6764,10 +6766,36 @@ var EMPTY_STATE$1 = {
|
|
|
6764
6766
|
* than document data.
|
|
6765
6767
|
*/
|
|
6766
6768
|
var LoomaMentionSuggestionPluginKey = new PluginKey("loomaMentionSuggestion");
|
|
6767
|
-
var LoomaMentionNode = Mention.extend({
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6769
|
+
var LoomaMentionNode = Mention.extend({
|
|
6770
|
+
renderText(props) {
|
|
6771
|
+
const { node } = props;
|
|
6772
|
+
const label = this.editor && getReferenceDisplay(this.editor)[`mention:${node.attrs.id}`]?.label;
|
|
6773
|
+
return this.parent({
|
|
6774
|
+
...props,
|
|
6775
|
+
node: typeof label === "string" ? node.type.create({
|
|
6776
|
+
...node.attrs,
|
|
6777
|
+
label
|
|
6778
|
+
}, node.content, node.marks) : node
|
|
6779
|
+
});
|
|
6780
|
+
},
|
|
6781
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
6782
|
+
const label = this.editor && getReferenceDisplay(this.editor)[`mention:${node.attrs.id}`]?.label;
|
|
6783
|
+
return this.parent({
|
|
6784
|
+
node: typeof label === "string" ? node.type.create({
|
|
6785
|
+
...node.attrs,
|
|
6786
|
+
label
|
|
6787
|
+
}, node.content, node.marks) : node,
|
|
6788
|
+
HTMLAttributes: typeof label === "string" ? {
|
|
6789
|
+
...HTMLAttributes,
|
|
6790
|
+
"data-label": label
|
|
6791
|
+
} : HTMLAttributes
|
|
6792
|
+
});
|
|
6793
|
+
},
|
|
6794
|
+
addAttributes() {
|
|
6795
|
+
const { mentionSuggestionChar: _trigger, ...durableAttributes } = this.parent?.() ?? {};
|
|
6796
|
+
return durableAttributes;
|
|
6797
|
+
}
|
|
6798
|
+
});
|
|
6771
6799
|
async function resolveMentionItems(source, query, limit) {
|
|
6772
6800
|
try {
|
|
6773
6801
|
return filterLoomaMentionItems(typeof source === "function" ? await source(query, { limit }) : source ?? [], query, limit);
|
|
@@ -9934,6 +9962,11 @@ var NODES = {
|
|
|
9934
9962
|
mention: (state, node) => {
|
|
9935
9963
|
const id = String(node.attrs.id ?? "");
|
|
9936
9964
|
state.write(`:mention[${label(String(node.attrs.label ?? id))}]${formatLoomaAttributes({ id }, { hashId: false })}`);
|
|
9965
|
+
},
|
|
9966
|
+
loomaReference: (state, node) => {
|
|
9967
|
+
const wrapper = document.createElement("span");
|
|
9968
|
+
wrapper.append(DOMSerializer.fromSchema(node.type.schema).serializeNode(node));
|
|
9969
|
+
state.write(wrapper.innerHTML);
|
|
9937
9970
|
}
|
|
9938
9971
|
};
|
|
9939
9972
|
var MARKS = {
|
|
@@ -10775,6 +10808,11 @@ function getDefaultEditorExtensions(options = {}) {
|
|
|
10775
10808
|
Document,
|
|
10776
10809
|
Paragraph,
|
|
10777
10810
|
Text$1,
|
|
10811
|
+
LoomaReference,
|
|
10812
|
+
LoomaReferencePresentation.configure({
|
|
10813
|
+
references: options.references ?? {},
|
|
10814
|
+
mentions: options.references !== void 0
|
|
10815
|
+
}),
|
|
10778
10816
|
Bold,
|
|
10779
10817
|
Italic,
|
|
10780
10818
|
Strike,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Extension, Node, mergeAttributes } from "@tiptap/core";
|
|
2
|
+
import { NodeSelection, Plugin, PluginKey } from "@tiptap/pm/state";
|
|
1
3
|
//#region src/markdown/index.ts
|
|
2
4
|
/**
|
|
3
5
|
* Callout tones a document stores, in the order the editor offers them. The Callout component also
|
|
@@ -239,4 +241,208 @@ function loomaCodeFence(code) {
|
|
|
239
241
|
return "`".repeat(Math.max(3, longest + 1));
|
|
240
242
|
}
|
|
241
243
|
//#endregion
|
|
242
|
-
|
|
244
|
+
//#region src/editor/content.ts
|
|
245
|
+
/**
|
|
246
|
+
* A link destination the editor may store: a site-relative path, fragment, or query, or an
|
|
247
|
+
* absolute http, https, mailto, or tel URL.
|
|
248
|
+
*
|
|
249
|
+
* @failure Returns null for empty input, control characters, other schemes, and unparseable URLs.
|
|
250
|
+
*/
|
|
251
|
+
function validLinkHref(value) {
|
|
252
|
+
const href = value.trim();
|
|
253
|
+
if (!href || /[\u0000-\u001f\u007f]/.test(href)) return null;
|
|
254
|
+
if (/^(\/|#|\?)/.test(href)) return href;
|
|
255
|
+
try {
|
|
256
|
+
const url = new URL(href);
|
|
257
|
+
return [
|
|
258
|
+
"http:",
|
|
259
|
+
"https:",
|
|
260
|
+
"mailto:",
|
|
261
|
+
"tel:"
|
|
262
|
+
].includes(url.protocol) ? href : null;
|
|
263
|
+
} catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region src/editor/reference-display.ts
|
|
269
|
+
var referenceDisplayKey = new PluginKey("loomaReferenceDisplay");
|
|
270
|
+
var referenceDisplayMeta = "loomaReferenceDisplay";
|
|
271
|
+
/**
|
|
272
|
+
* Replaces presentation without editing the document or adding an undo/history entry.
|
|
273
|
+
* @lifecycle Values last until the next replacement or editor destruction; hosts own persistence.
|
|
274
|
+
*/
|
|
275
|
+
function setReferenceDisplay(editor, references) {
|
|
276
|
+
if (editor.isDestroyed) return;
|
|
277
|
+
editor.storage.loomaReferencePresentation?.enableMentions?.();
|
|
278
|
+
editor.view.dispatch(editor.state.tr.setMeta(referenceDisplayMeta, references).setMeta("addToHistory", false));
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The current replaceable presentation; absent entries use the saved fallback.
|
|
282
|
+
* @ownership The returned map belongs to the host; replace it rather than mutating it.
|
|
283
|
+
*/
|
|
284
|
+
function getReferenceDisplay(editor) {
|
|
285
|
+
return editor.storage.loomaReferencePresentation?.references ?? {};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Reads current host presentation, with a durable insertion-time fallback for offline copies.
|
|
289
|
+
* @failure Unsafe cached destinations fall back to the saved safe URL or no destination.
|
|
290
|
+
*/
|
|
291
|
+
function referenceDisplay(node, references = {}) {
|
|
292
|
+
const kind = node.type.name === "mention" ? "mention" : node.attrs.kind;
|
|
293
|
+
const display = references[`${kind}:${node.attrs.id}`];
|
|
294
|
+
const label = typeof display?.label === "string" ? display.label : typeof node.attrs.label === "string" ? node.attrs.label : String(node.attrs.id ?? "Reference");
|
|
295
|
+
const href = typeof display?.href === "string" ? validLinkHref(display.href) : null;
|
|
296
|
+
return {
|
|
297
|
+
label,
|
|
298
|
+
...kind === "link" ? { href: href ?? (typeof node.attrs.href === "string" ? validLinkHref(node.attrs.href) : null) ?? void 0 } : {}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* An automatically labelled link; custom wording remains an ordinary text link.
|
|
303
|
+
* @contract Identity and insertion-time fallback stay in JSON; cached presentation stays outside it.
|
|
304
|
+
*/
|
|
305
|
+
var LoomaReference = Node.create({
|
|
306
|
+
name: "loomaReference",
|
|
307
|
+
inline: true,
|
|
308
|
+
group: "inline",
|
|
309
|
+
atom: true,
|
|
310
|
+
addAttributes: () => ({
|
|
311
|
+
id: {
|
|
312
|
+
default: null,
|
|
313
|
+
renderHTML: () => ({})
|
|
314
|
+
},
|
|
315
|
+
kind: {
|
|
316
|
+
default: "link",
|
|
317
|
+
renderHTML: () => ({})
|
|
318
|
+
},
|
|
319
|
+
href: {
|
|
320
|
+
default: null,
|
|
321
|
+
renderHTML: () => ({})
|
|
322
|
+
},
|
|
323
|
+
label: {
|
|
324
|
+
default: null,
|
|
325
|
+
renderHTML: () => ({})
|
|
326
|
+
},
|
|
327
|
+
target: {
|
|
328
|
+
default: "_self",
|
|
329
|
+
renderHTML: () => ({})
|
|
330
|
+
}
|
|
331
|
+
}),
|
|
332
|
+
parseHTML: () => [{
|
|
333
|
+
tag: "a[data-looma-reference]",
|
|
334
|
+
priority: 1001,
|
|
335
|
+
getAttrs: (element) => ({
|
|
336
|
+
id: element.getAttribute("data-looma-reference"),
|
|
337
|
+
kind: "link",
|
|
338
|
+
href: element.getAttribute("href"),
|
|
339
|
+
label: element.textContent,
|
|
340
|
+
target: element.getAttribute("target") ?? "_self"
|
|
341
|
+
})
|
|
342
|
+
}],
|
|
343
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
344
|
+
const display = referenceDisplay(node, this.editor ? getReferenceDisplay(this.editor) : {});
|
|
345
|
+
return [
|
|
346
|
+
"a",
|
|
347
|
+
mergeAttributes(HTMLAttributes, {
|
|
348
|
+
"data-looma-reference": node.attrs.id,
|
|
349
|
+
href: display.href,
|
|
350
|
+
target: node.attrs.target === "_blank" ? "_blank" : "_self",
|
|
351
|
+
rel: "noopener noreferrer"
|
|
352
|
+
}),
|
|
353
|
+
display.label
|
|
354
|
+
];
|
|
355
|
+
},
|
|
356
|
+
renderText({ node }) {
|
|
357
|
+
return referenceDisplay(node, this.editor ? getReferenceDisplay(this.editor) : {}).label;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
/**
|
|
361
|
+
* Installs metadata-backed node views for references and existing stable-id mentions.
|
|
362
|
+
* @lifecycle Node views register until destroyed, including across editor reattachment.
|
|
363
|
+
*/
|
|
364
|
+
var LoomaReferencePresentation = Extension.create({
|
|
365
|
+
name: "loomaReferencePresentation",
|
|
366
|
+
addOptions: () => ({
|
|
367
|
+
references: {},
|
|
368
|
+
mentions: false
|
|
369
|
+
}),
|
|
370
|
+
addStorage() {
|
|
371
|
+
return { references: this.options.references };
|
|
372
|
+
},
|
|
373
|
+
addProseMirrorPlugins() {
|
|
374
|
+
const initial = this.options.references;
|
|
375
|
+
const refresh = /* @__PURE__ */ new Set();
|
|
376
|
+
const nodeView = (node, view, getPosition) => {
|
|
377
|
+
let current = node;
|
|
378
|
+
const mention = node.type.name === "mention";
|
|
379
|
+
const dom = document.createElement(mention ? "span" : "a");
|
|
380
|
+
if (mention) {
|
|
381
|
+
dom.className = "looma-mention";
|
|
382
|
+
dom.setAttribute("data-type", "mention");
|
|
383
|
+
} else dom.addEventListener("click", (event) => {
|
|
384
|
+
if (!(event instanceof MouseEvent) || !view.editable || event.metaKey || event.ctrlKey) return;
|
|
385
|
+
const position = getPosition();
|
|
386
|
+
if (position === void 0) return;
|
|
387
|
+
event.preventDefault();
|
|
388
|
+
view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, position)));
|
|
389
|
+
view.focus();
|
|
390
|
+
});
|
|
391
|
+
const render = () => {
|
|
392
|
+
const display = referenceDisplay(current, referenceDisplayKey.getState(view.state));
|
|
393
|
+
dom.textContent = `${mention ? "@" : ""}${display.label}`;
|
|
394
|
+
if (mention) {
|
|
395
|
+
dom.setAttribute("data-id", current.attrs.id ?? "");
|
|
396
|
+
dom.setAttribute("data-label", display.label);
|
|
397
|
+
}
|
|
398
|
+
if (!mention) {
|
|
399
|
+
dom.setAttribute("data-looma-reference", current.attrs.id ?? "");
|
|
400
|
+
if (display.href) dom.setAttribute("href", display.href);
|
|
401
|
+
else dom.removeAttribute("href");
|
|
402
|
+
dom.setAttribute("target", current.attrs.target === "_blank" ? "_blank" : "_self");
|
|
403
|
+
dom.setAttribute("rel", "noopener noreferrer");
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
refresh.add(render);
|
|
407
|
+
render();
|
|
408
|
+
return {
|
|
409
|
+
dom,
|
|
410
|
+
update(next) {
|
|
411
|
+
if (next.type !== current.type) return false;
|
|
412
|
+
current = next;
|
|
413
|
+
render();
|
|
414
|
+
return true;
|
|
415
|
+
},
|
|
416
|
+
destroy: () => {
|
|
417
|
+
refresh.delete(render);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
};
|
|
421
|
+
const nodeViews = {
|
|
422
|
+
loomaReference: nodeView,
|
|
423
|
+
...this.options.mentions && this.editor.schema.nodes.mention ? { mention: nodeView } : {}
|
|
424
|
+
};
|
|
425
|
+
this.storage.enableMentions = () => {
|
|
426
|
+
if (nodeViews.mention || !this.editor.schema.nodes.mention) return;
|
|
427
|
+
nodeViews.mention = nodeView;
|
|
428
|
+
this.editor.view.setProps({ nodeViews: { ...this.editor.view.props.nodeViews } });
|
|
429
|
+
};
|
|
430
|
+
return [new Plugin({
|
|
431
|
+
key: referenceDisplayKey,
|
|
432
|
+
state: {
|
|
433
|
+
init: () => initial,
|
|
434
|
+
apply: (transaction, previous) => {
|
|
435
|
+
const next = transaction.getMeta(referenceDisplayMeta) ?? previous;
|
|
436
|
+
this.storage.references = next;
|
|
437
|
+
return next;
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
props: { nodeViews },
|
|
441
|
+
view: () => ({ update: (view, previous) => {
|
|
442
|
+
if (referenceDisplayKey.getState(view.state) !== referenceDisplayKey.getState(previous)) refresh.forEach((render) => render());
|
|
443
|
+
} })
|
|
444
|
+
})];
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
//#endregion
|
|
448
|
+
export { parseLoomaAttributes as _, setReferenceDisplay as a, splitLoomaFrontmatter as b, LOOMA_CONTAINER_NAMES as c, formatLoomaAttributes as d, loomaCodeFence as f, normalizeLoomaChipTone as g, normalizeLoomaCalloutTone as h, referenceDisplay as i, applyLoomaCodeNotation as l, loomaHeadingSlug as m, LoomaReferencePresentation as n, LOOMA_CALLOUT_TONES as o, loomaContainerMarker as p, getReferenceDisplay as r, LOOMA_CHIP_TONES as s, LoomaReference as t, assignLoomaHeadingIds as u, parseLoomaFenceInfo as v, readLoomaAttributes as y };
|
package/editor/expressmark.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import type { JSONContent } from "@tiptap/core";
|
|
1
|
+
import type { Editor, JSONContent } from "@tiptap/core";
|
|
2
2
|
import { type ConversionOptions, type Document } from "expressmark";
|
|
3
|
+
import { type LoomaReferenceMap } from "./reference-display.js";
|
|
4
|
+
/** Conversion-time display snapshot, independent from the authored editor document. */
|
|
5
|
+
export interface EditorMarkdownConversionOptions extends ConversionOptions {
|
|
6
|
+
references?: LoomaReferenceMap;
|
|
7
|
+
}
|
|
3
8
|
/**
|
|
4
9
|
* A conversion cannot faithfully represent the named input at this document location.
|
|
5
10
|
* @failure Callers retain the original document and can report the unsupported feature and path.
|
|
@@ -13,7 +18,7 @@ export declare class EditorMarkdownConversionError extends Error {
|
|
|
13
18
|
* Maps an editor's saved JSON to the independent Expressive Markdown AST without DOM access.
|
|
14
19
|
* @contract Unsupported nodes, marks and durable attributes throw with their location; input is never mutated.
|
|
15
20
|
*/
|
|
16
|
-
export declare function editorDocumentToExpressmark(document: JSONContent, options?:
|
|
21
|
+
export declare function editorDocumentToExpressmark(document: JSONContent, options?: EditorMarkdownConversionOptions): Document;
|
|
17
22
|
/**
|
|
18
23
|
* Maps supported Expressive Markdown content into the Looma editor's saved JSON shape.
|
|
19
24
|
* @contract The editor schema cannot represent arbitrary format extensions; unsupported meanings fail explicitly.
|
|
@@ -23,7 +28,12 @@ export declare function expressmarkToEditorDocument(document: Document): JSONCon
|
|
|
23
28
|
* Writes an editor document using Expressmark's shared parser/writer and safe HTML policy.
|
|
24
29
|
* @failure Unsupported editor data raises EditorMarkdownConversionError before any input is changed.
|
|
25
30
|
*/
|
|
26
|
-
export declare function editorDocumentToMarkdown(document: JSONContent, options?:
|
|
31
|
+
export declare function editorDocumentToMarkdown(document: JSONContent, options?: EditorMarkdownConversionOptions): string;
|
|
32
|
+
/**
|
|
33
|
+
* Serializes the current editor, including its current display cache and concrete TOC entries.
|
|
34
|
+
* @failure Unsupported content throws EditorMarkdownConversionError without changing the document.
|
|
35
|
+
*/
|
|
36
|
+
export declare function editorToMarkdown(editor: Editor, options?: ConversionOptions): string;
|
|
27
37
|
/**
|
|
28
38
|
* Parses Expressive Markdown into editable JSON for the supported editor schema.
|
|
29
39
|
* @failure Unsupported content or root metadata stops conversion instead of being silently flattened.
|
package/editor/expressmark.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { m as loomaHeadingSlug, o as LOOMA_CALLOUT_TONES, r as getReferenceDisplay, s as LOOMA_CHIP_TONES } from "./chunks/reference-display.js";
|
|
2
2
|
import { parse, stringify } from "expressmark";
|
|
3
3
|
//#region src/editor/expressmark.ts
|
|
4
4
|
/**
|
|
@@ -179,6 +179,11 @@ function legacyCodePresentation(code, path) {
|
|
|
179
179
|
return result;
|
|
180
180
|
}
|
|
181
181
|
var REVERSE_MARKS = Object.fromEntries(Object.entries(MARKS).map(([left, right]) => [right, left]));
|
|
182
|
+
var displayText = (node, references) => {
|
|
183
|
+
if (node.type === "loomaReference") return references[`link:${node.attrs?.id}`]?.label ?? string(node.attrs?.label, string(node.attrs?.id));
|
|
184
|
+
if (node.type === "mention") return `@${references[`mention:${node.attrs?.id}`]?.label ?? string(node.attrs?.label, string(node.attrs?.id))}`;
|
|
185
|
+
return node.text ?? (node.content ?? []).map((child) => displayText(child, references)).join("");
|
|
186
|
+
};
|
|
182
187
|
function tocBody(headings, depth, ordered) {
|
|
183
188
|
const roots = [];
|
|
184
189
|
const stack = [];
|
|
@@ -225,6 +230,7 @@ function toNode(node, path, context) {
|
|
|
225
230
|
if (![
|
|
226
231
|
"text",
|
|
227
232
|
"mention",
|
|
233
|
+
"loomaReference",
|
|
228
234
|
"loomaChip",
|
|
229
235
|
"hardBreak"
|
|
230
236
|
].includes(node.type ?? "")) fail(path, "marks on a block node");
|
|
@@ -281,6 +287,29 @@ function toBareNode(node, path, context) {
|
|
|
281
287
|
};
|
|
282
288
|
};
|
|
283
289
|
switch (node.type) {
|
|
290
|
+
case "loomaReference": {
|
|
291
|
+
fields(node, [
|
|
292
|
+
"id",
|
|
293
|
+
"kind",
|
|
294
|
+
"href",
|
|
295
|
+
"label",
|
|
296
|
+
"target"
|
|
297
|
+
], path);
|
|
298
|
+
if (!attrs.id || attrs.kind !== "link") fail(path, "invalid link reference identity");
|
|
299
|
+
const display = context.references[`link:${attrs.id}`];
|
|
300
|
+
const href = display?.href ?? string(attrs.href);
|
|
301
|
+
safeNavigation(href, false, path);
|
|
302
|
+
return {
|
|
303
|
+
type: "link",
|
|
304
|
+
url: href,
|
|
305
|
+
value: display?.label ?? string(attrs.label, string(attrs.id)),
|
|
306
|
+
attributes: {
|
|
307
|
+
ref: string(attrs.id),
|
|
308
|
+
target: string(attrs.target, "_self"),
|
|
309
|
+
rel: "noopener noreferrer"
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
284
313
|
case "text":
|
|
285
314
|
fields(node, [], path);
|
|
286
315
|
return {
|
|
@@ -355,7 +384,7 @@ function toBareNode(node, path, context) {
|
|
|
355
384
|
return {
|
|
356
385
|
type: "inline",
|
|
357
386
|
subType: "mention",
|
|
358
|
-
value: string(attrs.label, string(attrs.id)),
|
|
387
|
+
value: context.references[`mention:${attrs.id}`]?.label ?? string(attrs.label, string(attrs.id)),
|
|
359
388
|
...attrs.id ? { ref: string(attrs.id) } : {}
|
|
360
389
|
};
|
|
361
390
|
case "loomaChip":
|
|
@@ -523,7 +552,7 @@ function editorDocumentToExpressmark(document, options = {}) {
|
|
|
523
552
|
if (!insideToc && node.type === "loomaTableOfContents" && !node.content?.length) automaticToc = true;
|
|
524
553
|
if (!insideToc && node.type === "heading") headings.push({
|
|
525
554
|
node,
|
|
526
|
-
text: (node
|
|
555
|
+
text: displayText(node, options.references ?? {}),
|
|
527
556
|
id: string(node.attrs?.id),
|
|
528
557
|
level: Number(node.attrs?.level ?? 1)
|
|
529
558
|
});
|
|
@@ -553,7 +582,8 @@ function editorDocumentToExpressmark(document, options = {}) {
|
|
|
553
582
|
}
|
|
554
583
|
const context = {
|
|
555
584
|
headings,
|
|
556
|
-
headingIds
|
|
585
|
+
headingIds,
|
|
586
|
+
references: options.references ?? {}
|
|
557
587
|
};
|
|
558
588
|
return {
|
|
559
589
|
type: "document",
|
|
@@ -601,8 +631,23 @@ function fromNode(node, path, marks = []) {
|
|
|
601
631
|
check(node.type === "link" ? [
|
|
602
632
|
"target",
|
|
603
633
|
"rel",
|
|
604
|
-
"class"
|
|
634
|
+
"class",
|
|
635
|
+
"ref"
|
|
605
636
|
] : []);
|
|
637
|
+
if (node.type === "link" && attrs.ref !== void 0) {
|
|
638
|
+
if (typeof attrs.ref !== "string" || !attrs.ref || node.title || attrs.class || content(node).some((child) => child.type !== "text" || child.attributes || child.id)) fail(path, "formatted or invalid link reference");
|
|
639
|
+
return [{
|
|
640
|
+
type: "loomaReference",
|
|
641
|
+
attrs: {
|
|
642
|
+
id: attrs.ref,
|
|
643
|
+
kind: "link",
|
|
644
|
+
href: node.url ?? "",
|
|
645
|
+
label: text(node),
|
|
646
|
+
target: attrs.target ?? "_self"
|
|
647
|
+
},
|
|
648
|
+
...marks.length ? { marks } : {}
|
|
649
|
+
}];
|
|
650
|
+
}
|
|
606
651
|
const mark = { type: REVERSE_MARKS[node.type] };
|
|
607
652
|
if (node.type === "link") mark.attrs = {
|
|
608
653
|
href: node.url ?? "",
|
|
@@ -932,6 +977,16 @@ function editorDocumentToMarkdown(document, options = {}) {
|
|
|
932
977
|
return stringify(editorDocumentToExpressmark(document, options), options);
|
|
933
978
|
}
|
|
934
979
|
/**
|
|
980
|
+
* Serializes the current editor, including its current display cache and concrete TOC entries.
|
|
981
|
+
* @failure Unsupported content throws EditorMarkdownConversionError without changing the document.
|
|
982
|
+
*/
|
|
983
|
+
function editorToMarkdown(editor, options = {}) {
|
|
984
|
+
return editorDocumentToMarkdown(editor.getJSON(), {
|
|
985
|
+
...options,
|
|
986
|
+
references: getReferenceDisplay(editor)
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
935
990
|
* Parses Expressive Markdown into editable JSON for the supported editor schema.
|
|
936
991
|
* @failure Unsupported content or root metadata stops conversion instead of being silently flattened.
|
|
937
992
|
*/
|
|
@@ -939,4 +994,4 @@ function markdownToEditorDocument(markdown, options = {}) {
|
|
|
939
994
|
return expressmarkToEditorDocument(parse(markdown, options));
|
|
940
995
|
}
|
|
941
996
|
//#endregion
|
|
942
|
-
export { EditorMarkdownConversionError, editorDocumentToExpressmark, editorDocumentToMarkdown, expressmarkToEditorDocument, markdownToEditorDocument };
|
|
997
|
+
export { EditorMarkdownConversionError, editorDocumentToExpressmark, editorDocumentToMarkdown, editorToMarkdown, expressmarkToEditorDocument, markdownToEditorDocument };
|
|
@@ -15,6 +15,7 @@ export { LoomaTab, LoomaTabs } from "./tabs.js";
|
|
|
15
15
|
export { LoomaTableOfContents, getTableOfContentsEntries, normalizeTableOfContentsConfig, type LoomaTableOfContentsConfig, type LoomaTableOfContentsEntry, type LoomaTableOfContentsFormat, } from "./table-of-contents.js";
|
|
16
16
|
export { getDefaultEditorExtensions, getLoomaTableExtensions, LoomaTableKit, type DefaultEditorExtensionsOptions, type LoomaCodeLanguages, } from "./preset.js";
|
|
17
17
|
export { LoomaSmartPaste } from "./smart-paste.js";
|
|
18
|
+
export { LoomaReference, LoomaReferencePresentation, setReferenceDisplay, getReferenceDisplay, referenceDisplay, type LoomaReferenceDisplay, type LoomaReferenceMap } from "../reference-display.js";
|
|
18
19
|
export { loomaMarkdownFromDoc, loomaMarkdownToHtml } from "./markdown.js";
|
|
19
20
|
export { getActiveTableUiState, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, shouldShowTextFormattingToolbar, type ActiveTableUiState, type InsertTableAtRangeOptions, type TableActionCapabilities, } from "./table-commands.js";
|
|
20
21
|
export { LoomaTable, getActiveTableCellAlignment, getActiveTableCellBackground, LoomaTableCell, LoomaTableHeader, setActiveTableCellAlignment, setActiveTableCellBackground, TABLE_CELL_BACKGROUND_PRESETS, type TableCellAlignment, type TableCellBackground, } from "./table-formatting.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS } from "../chunks/table-backgrounds.js";
|
|
2
2
|
import { A as filterLoomaMentionItems, B as LoomaFigcaption, C as loomaMarkdownToHtml, D as createLoomaMentionExtension, E as LoomaMentionSuggestionPluginKey, F as LoomaTableOfContents, G as LoomaChip, H as LoomaExpand, I as getTableOfContentsEntries, J as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, K as normalizeLoomaChipColor, L as normalizeTableOfContentsConfig, M as LoomaImage, N as normalizeImageDimension, O as DEFAULT_MENTION_RESULT_LIMIT, P as normalizeImagePlacement, Q as LoomaActiveBlockPluginKey, R as LoomaTab, S as loomaMarkdownFromDoc, T as siteRelativeHref, U as revealLoomaExpandAt, V as LoomaFigure, W as LOOMA_CHIP_COLORS, X as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, Y as LOOMA_ACTIVE_BLOCK_CLASS, Z as LoomaActiveBlock, _ as getActiveTableCellAlignment, a as getActiveTableUiState, b as setActiveTableCellBackground, c as insertTableAtRange, d as LoomaTableKit, f as getDefaultEditorExtensions, g as LoomaTableHeader, h as LoomaTableCell, i as getDefaultSlashCommands, j as normalizeMentionResultLimit, k as MAX_MENTION_RESULT_LIMIT, l as normalizeActiveTableColumnWidths, m as LoomaTable, n as createLoomaSlashCommandExtension, o as handleTableAction, p as getLoomaTableExtensions, q as LoomaCallout, r as filterLoomaSlashCommands, s as handleTableOverlayAction, t as LoomaSlashCommand, u as shouldShowTextFormattingToolbar, v as getActiveTableCellBackground, w as createSiteRelativeLinks, x as LoomaSmartPaste, y as setActiveTableCellAlignment, z as LoomaTabs } from "../chunks/extensions.js";
|
|
3
|
-
import {
|
|
4
|
-
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaExpand, LoomaFigcaption, LoomaFigure, LoomaImage, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTab, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, LoomaTableOfContents, LoomaTabs, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, createSiteRelativeLinks, filterLoomaMentionItems, filterLoomaSlashCommands, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getTableOfContentsEntries, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaMarkdownFromDoc, loomaMarkdownToHtml, normalizeActiveTableColumnWidths, normalizeImageDimension, normalizeImagePlacement, normalizeLoomaChipColor, normalizeMentionResultLimit, normalizeTableOfContentsConfig, revealLoomaExpandAt, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar, siteRelativeHref };
|
|
3
|
+
import { a as setReferenceDisplay, i as referenceDisplay, n as LoomaReferencePresentation, o as LOOMA_CALLOUT_TONES, r as getReferenceDisplay, t as LoomaReference } from "../chunks/reference-display.js";
|
|
4
|
+
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaExpand, LoomaFigcaption, LoomaFigure, LoomaImage, LoomaMentionSuggestionPluginKey, LoomaReference, LoomaReferencePresentation, LoomaSlashCommand, LoomaSmartPaste, LoomaTab, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, LoomaTableOfContents, LoomaTabs, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, createSiteRelativeLinks, filterLoomaMentionItems, filterLoomaSlashCommands, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getReferenceDisplay, getTableOfContentsEntries, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaMarkdownFromDoc, loomaMarkdownToHtml, normalizeActiveTableColumnWidths, normalizeImageDimension, normalizeImagePlacement, normalizeLoomaChipColor, normalizeMentionResultLimit, normalizeTableOfContentsConfig, referenceDisplay, revealLoomaExpandAt, setActiveTableCellAlignment, setActiveTableCellBackground, setReferenceDisplay, shouldShowTextFormattingToolbar, siteRelativeHref };
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { type AnyExtension, type NodeViewRenderer } from "@tiptap/core";
|
|
6
6
|
import { createLowlight } from "lowlight";
|
|
7
|
+
import { type LoomaReferenceMap } from "../reference-display.js";
|
|
7
8
|
/** Grammars supplied by the host; importing a language remains the host's choice. */
|
|
8
9
|
export type LoomaCodeLanguages = NonNullable<Parameters<typeof createLowlight>[0]>;
|
|
9
10
|
/**
|
|
@@ -12,6 +13,8 @@ export type LoomaCodeLanguages = NonNullable<Parameters<typeof createLowlight>[0
|
|
|
12
13
|
* rather than relying on undocumented mutation of the returned extensions.
|
|
13
14
|
*/
|
|
14
15
|
export interface DefaultEditorExtensionsOptions {
|
|
16
|
+
/** Replaceable display data; updating it must use setReferenceDisplay, never setContent. */
|
|
17
|
+
references?: LoomaReferenceMap;
|
|
15
18
|
/** Placeholder shown only for empty paragraphs, not every empty node type. */
|
|
16
19
|
placeholder?: string;
|
|
17
20
|
/** Passed to Tiptap Link; defaults false to keep editing clicks in the editor. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Node, type NodeViewRenderer } from "@tiptap/core";
|
|
2
2
|
import { type Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|
3
|
+
import { type LoomaReferenceMap } from "../reference-display.js";
|
|
3
4
|
/** Formatting affects presentation only; heading order remains document order. */
|
|
4
5
|
export type LoomaTableOfContentsFormat = "plain" | "bulleted" | "numbered";
|
|
5
6
|
/** Persisted TOC choices; entries themselves are always derived from headings. */
|
|
@@ -26,7 +27,7 @@ export declare function normalizeTableOfContentsConfig(attributes: Record<string
|
|
|
26
27
|
* @contract Depth is a maximum heading level. Relative nesting follows existing
|
|
27
28
|
* ancestors rather than inserting artificial entries for skipped levels.
|
|
28
29
|
*/
|
|
29
|
-
export declare function getTableOfContentsEntries(doc: ProseMirrorNode, depth?: number): LoomaTableOfContentsEntry[];
|
|
30
|
+
export declare function getTableOfContentsEntries(doc: ProseMirrorNode, depth?: number, references?: LoomaReferenceMap): LoomaTableOfContentsEntry[];
|
|
30
31
|
interface Branch {
|
|
31
32
|
entry: LoomaTableOfContentsEntry;
|
|
32
33
|
children: Branch[];
|
package/editor/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS, t as TABLE_CELL_BACKGROUND_OPTIONS } from "./chunks/table-backgrounds.js";
|
|
2
2
|
import { n as resolveTableCellAt, t as measureTableOverlayGeometry } from "./chunks/ui.js";
|
|
3
3
|
import { A as filterLoomaMentionItems, B as LoomaFigcaption, C as loomaMarkdownToHtml, D as createLoomaMentionExtension, E as LoomaMentionSuggestionPluginKey, F as LoomaTableOfContents, G as LoomaChip, H as LoomaExpand, I as getTableOfContentsEntries, J as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, K as normalizeLoomaChipColor, L as normalizeTableOfContentsConfig, M as LoomaImage, N as normalizeImageDimension, O as DEFAULT_MENTION_RESULT_LIMIT, P as normalizeImagePlacement, Q as LoomaActiveBlockPluginKey, R as LoomaTab, S as loomaMarkdownFromDoc, T as siteRelativeHref, U as revealLoomaExpandAt, V as LoomaFigure, W as LOOMA_CHIP_COLORS, X as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, Y as LOOMA_ACTIVE_BLOCK_CLASS, Z as LoomaActiveBlock, _ as getActiveTableCellAlignment, a as getActiveTableUiState, b as setActiveTableCellBackground, c as insertTableAtRange, d as LoomaTableKit, f as getDefaultEditorExtensions, g as LoomaTableHeader, h as LoomaTableCell, i as getDefaultSlashCommands, j as normalizeMentionResultLimit, k as MAX_MENTION_RESULT_LIMIT, l as normalizeActiveTableColumnWidths, m as LoomaTable, n as createLoomaSlashCommandExtension, o as handleTableAction, p as getLoomaTableExtensions, q as LoomaCallout, r as filterLoomaSlashCommands, s as handleTableOverlayAction, t as LoomaSlashCommand, u as shouldShowTextFormattingToolbar, v as getActiveTableCellBackground, w as createSiteRelativeLinks, x as LoomaSmartPaste, y as setActiveTableCellAlignment, z as LoomaTabs } from "./chunks/extensions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { a as setReferenceDisplay, i as referenceDisplay, n as LoomaReferencePresentation, o as LOOMA_CALLOUT_TONES, r as getReferenceDisplay, t as LoomaReference } from "./chunks/reference-display.js";
|
|
5
5
|
import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bell, Bold, BookUser, Braces, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleDot, CircleQuestionMark, CircleX, CodeXml, Columns3, Compass, CreditCard, Ellipsis, Eraser, ExternalLink, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, History, Image, Info, Italic, LayoutDashboard, Lightbulb, Link, List, ListOrdered, ListTodo, LoaderCircle, Merge, MessageSquareWarning, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Pencil, Pilcrow, Plus, Quote, Receipt, Redo2, Rows3, Search, Settings, Split, Strikethrough, Table2, Tag, Trash2, TriangleAlert, Truck, Underline, Undo2, Unlink, UserRound, Users, X } from "lucide";
|
|
6
6
|
//#region src/editor/icons.ts
|
|
7
7
|
/** The opinionated Lucide set used by Looma's shipped interaction surfaces. */
|
|
@@ -124,4 +124,4 @@ function getVisualViewportRect(owner = window) {
|
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
//#endregion
|
|
127
|
-
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LOOMA_ICONS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaExpand, LoomaFigcaption, LoomaFigure, LoomaImage, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTab, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, LoomaTableOfContents, LoomaTabs, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_OPTIONS, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, createSiteRelativeLinks, filterLoomaMentionItems, filterLoomaSlashCommands, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getTableOfContentsEntries, getVisualViewportRect, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaIconMarkup, loomaMarkdownFromDoc, loomaMarkdownToHtml, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeImageDimension, normalizeImagePlacement, normalizeLoomaChipColor, normalizeMentionResultLimit, normalizeTableOfContentsConfig, resolveTableCellAt, revealLoomaExpandAt, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar, siteRelativeHref };
|
|
127
|
+
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LOOMA_ICONS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaExpand, LoomaFigcaption, LoomaFigure, LoomaImage, LoomaMentionSuggestionPluginKey, LoomaReference, LoomaReferencePresentation, LoomaSlashCommand, LoomaSmartPaste, LoomaTab, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, LoomaTableOfContents, LoomaTabs, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_OPTIONS, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, createSiteRelativeLinks, filterLoomaMentionItems, filterLoomaSlashCommands, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getReferenceDisplay, getTableOfContentsEntries, getVisualViewportRect, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaIconMarkup, loomaMarkdownFromDoc, loomaMarkdownToHtml, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeImageDimension, normalizeImagePlacement, normalizeLoomaChipColor, normalizeMentionResultLimit, normalizeTableOfContentsConfig, referenceDisplay, resolveTableCellAt, revealLoomaExpandAt, setActiveTableCellAlignment, setActiveTableCellBackground, setReferenceDisplay, shouldShowTextFormattingToolbar, siteRelativeHref };
|
package/editor/link-editing.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { Editor } from "@tiptap/core";
|
|
2
|
+
/** Whether the current selection identifies an automatically labelled link. */
|
|
3
|
+
export declare function selectedLinkReference(editor: Editor): import("@tiptap/pm/model").Node | null;
|
|
4
|
+
export declare const isLinkActive: (editor: Editor) => boolean;
|
|
2
5
|
/** A destination supplied by the host application, such as a page or record. */
|
|
3
6
|
export interface LoomaLinkTarget {
|
|
4
7
|
id: string;
|
|
@@ -47,6 +50,8 @@ export interface LoomaLinkEditingOptions {
|
|
|
47
50
|
search: () => LinkSearch | null | undefined;
|
|
48
51
|
resolve: () => LinkResolve | null | undefined;
|
|
49
52
|
baseUrl: () => string;
|
|
53
|
+
/** Enables automatically labelled references for newly inserted host targets. */
|
|
54
|
+
references?: () => boolean;
|
|
50
55
|
}
|
|
51
56
|
/**
|
|
52
57
|
* The editor's link form as a state machine: what the form holds, how it applies to the
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Extension, Node, type Editor } from "@tiptap/core";
|
|
2
|
+
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|
3
|
+
/** Replaceable host-owned presentation, keyed by `link:<id>` or `mention:<id>`. */
|
|
4
|
+
export interface LoomaReferenceDisplay {
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly href?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Display values indexed by stable target kind and identity, outside authored document data. */
|
|
9
|
+
export type LoomaReferenceMap = Readonly<Record<string, LoomaReferenceDisplay>>;
|
|
10
|
+
/**
|
|
11
|
+
* Replaces presentation without editing the document or adding an undo/history entry.
|
|
12
|
+
* @lifecycle Values last until the next replacement or editor destruction; hosts own persistence.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setReferenceDisplay(editor: Editor, references: LoomaReferenceMap): void;
|
|
15
|
+
/**
|
|
16
|
+
* The current replaceable presentation; absent entries use the saved fallback.
|
|
17
|
+
* @ownership The returned map belongs to the host; replace it rather than mutating it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getReferenceDisplay(editor: Editor): LoomaReferenceMap;
|
|
20
|
+
/**
|
|
21
|
+
* Reads current host presentation, with a durable insertion-time fallback for offline copies.
|
|
22
|
+
* @failure Unsafe cached destinations fall back to the saved safe URL or no destination.
|
|
23
|
+
*/
|
|
24
|
+
export declare function referenceDisplay(node: ProseMirrorNode, references?: LoomaReferenceMap): LoomaReferenceDisplay;
|
|
25
|
+
/**
|
|
26
|
+
* An automatically labelled link; custom wording remains an ordinary text link.
|
|
27
|
+
* @contract Identity and insertion-time fallback stay in JSON; cached presentation stays outside it.
|
|
28
|
+
*/
|
|
29
|
+
export declare const LoomaReference: Node<any, any>;
|
|
30
|
+
/**
|
|
31
|
+
* Installs metadata-backed node views for references and existing stable-id mentions.
|
|
32
|
+
* @lifecycle Node views register until destroyed, including across editor reattachment.
|
|
33
|
+
*/
|
|
34
|
+
export declare const LoomaReferencePresentation: Extension<{
|
|
35
|
+
references: LoomaReferenceMap;
|
|
36
|
+
mentions: boolean;
|
|
37
|
+
}, any>;
|