@threadlabs/looma 0.15.4 → 0.15.6

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.
@@ -6,7 +6,7 @@ import { history, redo, undo } from "@tiptap/pm/history";
6
6
  import { dropCursor } from "@tiptap/pm/dropcursor";
7
7
  import { gapCursor } from "@tiptap/pm/gapcursor";
8
8
  import { common, createLowlight } from "lowlight";
9
- import { DOMParser, Node as Node$2 } from "@tiptap/pm/model";
9
+ import { DOMParser, Node as Node$2, Slice } from "@tiptap/pm/model";
10
10
  import MarkdownIt from "markdown-it";
11
11
  import { CellSelection, TableMap, addColumn, addColumnAfter, addColumnBefore, addRow, addRowAfter, addRowBefore, cellAround, columnResizing, deleteCellSelection, deleteColumn, deleteRow, deleteTable, fixTables, goToNextCell, mergeCells, moveTableColumn, moveTableRow, setCellAttr, splitCell, tableEditing, toggleHeader, toggleHeaderCell } from "@tiptap/pm/tables";
12
12
  //#region src/editor/extensions/active-block.ts
@@ -8514,6 +8514,8 @@ function looksLikeMarkdown(value) {
8514
8514
  }
8515
8515
  function parseHtmlSlice(schema, value) {
8516
8516
  const parsed = new globalThis.DOMParser().parseFromString(value, "text/html");
8517
+ if (parsed.body.style.display === "none") return Slice.empty;
8518
+ for (const element of parsed.body.querySelectorAll("[style]")) if (element.style.display === "none") element.remove();
8517
8519
  const container = document.createElement("div");
8518
8520
  container.append(purify.sanitize(parsed.body.innerHTML, {
8519
8521
  USE_PROFILES: { html: true },
@@ -8528,7 +8530,7 @@ function parseHtmlSlice(schema, value) {
8528
8530
  FORBID_ATTR: ["style"],
8529
8531
  RETURN_DOM_FRAGMENT: true
8530
8532
  }));
8531
- if (!container.textContent?.trim() && !container.querySelector("img, hr")) return null;
8533
+ if (!container.textContent?.trim() && !container.querySelector("img, hr")) return Slice.empty;
8532
8534
  return DOMParser.fromSchema(schema).parseSlice(container, { preserveWhitespace: false });
8533
8535
  }
8534
8536
  function documentSlice(schema, plainText) {
@@ -8558,6 +8560,7 @@ var LoomaSmartPaste = Extension.create({
8558
8560
  if (!plainText.trim()) return false;
8559
8561
  const slice = documentSlice(view.state.schema, plainText);
8560
8562
  if (!slice) return false;
8563
+ if (slice.size === 0) return true;
8561
8564
  const transaction = view.state.tr.replaceSelection(slice).scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste");
8562
8565
  view.dispatch(transaction);
8563
8566
  return true;
@@ -9062,6 +9065,12 @@ function setActiveTableCellBackground(editor, backgroundColor) {
9062
9065
  * Default Tiptap extension preset for Looma editor.
9063
9066
  * Uses the Vanilla JS Tiptap API; apps provide @tiptap/core and Looma ships the preset extensions.
9064
9067
  */
9068
+ var StoredOnlyHighlight = Highlight.extend({
9069
+ parseHTML: () => [],
9070
+ addKeyboardShortcuts: () => ({}),
9071
+ addInputRules: () => [],
9072
+ addPasteRules: () => []
9073
+ });
9065
9074
  var lowlight = createLowlight(common);
9066
9075
  /**
9067
9076
  * Complete Looma table schema as one Tiptap extension.
@@ -9102,7 +9111,7 @@ function getLoomaTableExtensions() {
9102
9111
  * framework's Tiptap editor hook.
9103
9112
  */
9104
9113
  function getDefaultEditorExtensions(options = {}) {
9105
- const { placeholder = "Type “/” for commands, or start writing…", linkOpenOnClick = false, imageInline = false, mention = createLoomaMentionExtension() } = options;
9114
+ const { placeholder = "Type “/” for commands, or start writing…", linkOpenOnClick = false, imageInline = false, mention = createLoomaMentionExtension(), disableHighlight = false } = options;
9106
9115
  return [
9107
9116
  Document,
9108
9117
  Paragraph,
@@ -9136,7 +9145,7 @@ function getDefaultEditorExtensions(options = {}) {
9136
9145
  }
9137
9146
  }),
9138
9147
  Image.configure({ inline: imageInline }),
9139
- Highlight.configure({ multicolor: false }),
9148
+ (disableHighlight ? StoredOnlyHighlight : Highlight).configure({ multicolor: false }),
9140
9149
  Code,
9141
9150
  LoomaSmartPaste,
9142
9151
  CodeBlockLowlight.configure({ lowlight }),
@@ -17,6 +17,13 @@ export interface DefaultEditorExtensionsOptions {
17
17
  imageInline?: boolean;
18
18
  /** Custom mention extension, the Looma default, or false to omit mentions. */
19
19
  mention?: AnyExtension | false;
20
+ /**
21
+ * Removes every way for authors to apply the highlight mark: the Mod-Shift-H
22
+ * shortcut, `==text==` typing and paste rules, and `<mark>` parsing from
23
+ * pasted or HTML content. Highlights already stored in a document still load
24
+ * and render. Use it when the application reserves highlighting for itself.
25
+ */
26
+ disableHighlight?: boolean;
20
27
  }
21
28
  /**
22
29
  * Complete Looma table schema as one Tiptap extension.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.15.4",
3
+ "version": "0.15.6",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -94,6 +94,14 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
94
94
  type: PropType<LoomaEditorToolbarMode>;
95
95
  default: string;
96
96
  };
97
+ /**
98
+ * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
99
+ * Highlights already in the document still show. Read once, when the editor is created.
100
+ */
101
+ disableHighlight: {
102
+ type: BooleanConstructor;
103
+ default: boolean;
104
+ };
97
105
  }>, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
98
106
  [key: string]: any;
99
107
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
@@ -160,6 +168,14 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
160
168
  type: PropType<LoomaEditorToolbarMode>;
161
169
  default: string;
162
170
  };
171
+ /**
172
+ * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
173
+ * Highlights already in the document still show. Read once, when the editor is created.
174
+ */
175
+ disableHighlight: {
176
+ type: BooleanConstructor;
177
+ default: boolean;
178
+ };
163
179
  }>> & Readonly<{
164
180
  "onUpdate:modelValue"?: ((_value: JSONContent) => any) | undefined;
165
181
  onUpdate?: ((_value: JSONContent) => any) | undefined;
@@ -170,6 +186,7 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
170
186
  }>, {
171
187
  label: string;
172
188
  placeholder: string;
189
+ disableHighlight: boolean;
173
190
  modelValue: JSONContent;
174
191
  editable: boolean;
175
192
  extensions: AnyExtension[];
@@ -322,6 +322,14 @@ var LoomaEditor = defineComponent({
322
322
  toolbarMode: {
323
323
  type: String,
324
324
  default: "bubble"
325
+ },
326
+ /**
327
+ * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
328
+ * Highlights already in the document still show. Read once, when the editor is created.
329
+ */
330
+ disableHighlight: {
331
+ type: Boolean,
332
+ default: false
325
333
  }
326
334
  },
327
335
  emits: {
@@ -457,11 +465,13 @@ var LoomaEditor = defineComponent({
457
465
  text: selection instanceof TextSelection
458
466
  };
459
467
  };
468
+ const authorHighlight = !props.disableHighlight;
460
469
  const editor = useEditor({
461
470
  extensions: [
462
471
  ...getDefaultEditorExtensions({
463
472
  placeholder: props.placeholder,
464
- mention: mentionExtension ?? false
473
+ mention: mentionExtension ?? false,
474
+ disableHighlight: props.disableHighlight
465
475
  }),
466
476
  imageDelivery.extension,
467
477
  slashExtension,
@@ -997,7 +1007,7 @@ var LoomaEditor = defineComponent({
997
1007
  commandButton("Italic", "italic", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run()),
998
1008
  commandButton("Underline", "underline", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run()),
999
1009
  commandButton("Strike", "strikethrough", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run()),
1000
- commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run()),
1010
+ ...authorHighlight ? [commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run())] : [],
1001
1011
  commandButton("Inline code", "code-xml", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run()),
1002
1012
  h(IconButton, {
1003
1013
  id: linkAnchorId,