@threadlabs/looma 0.16.4 → 0.17.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.
@@ -5,7 +5,7 @@ import { Decoration, DecorationSet } from "@tiptap/pm/view";
5
5
  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
- import { common, createLowlight } from "lowlight";
8
+ import { createLowlight } from "lowlight";
9
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";
@@ -8631,6 +8631,13 @@ function parseHtmlSlice(schema, value) {
8631
8631
  const parsed = new globalThis.DOMParser().parseFromString(value, "text/html");
8632
8632
  if (parsed.body.style.display === "none") return Slice.empty;
8633
8633
  for (const element of parsed.body.querySelectorAll("[style]")) if (element.style.display === "none") element.remove();
8634
+ for (const wrapper of parsed.body.querySelectorAll("div")) for (const child of wrapper.children) {
8635
+ const next = child.nextSibling;
8636
+ if (child.localName !== "span" || next?.nodeType !== 1 || next.localName !== "span") continue;
8637
+ if (!child.textContent?.trim() || !next.textContent?.trim()) continue;
8638
+ if (/\s$/.test(child.textContent) || /^\s/.test(next.textContent)) continue;
8639
+ wrapper.insertBefore(parsed.createTextNode(" "), next);
8640
+ }
8634
8641
  const container = document.createElement("div");
8635
8642
  container.append(purify.sanitize(parsed.body.innerHTML, {
8636
8643
  USE_PROFILES: { html: true },
@@ -9199,7 +9206,6 @@ var StoredOnlyHighlight = Highlight.extend({
9199
9206
  addInputRules: () => [],
9200
9207
  addPasteRules: () => []
9201
9208
  });
9202
- var lowlight = createLowlight(common);
9203
9209
  /**
9204
9210
  * Complete Looma table schema as one Tiptap extension.
9205
9211
  * Use this in presets that want table, row, header, and cell nodes to remain an
@@ -9239,7 +9245,7 @@ function getLoomaTableExtensions() {
9239
9245
  * framework's Tiptap editor hook.
9240
9246
  */
9241
9247
  function getDefaultEditorExtensions(options = {}) {
9242
- const { placeholder = "Type “/” for commands, or start writing…", linkOpenOnClick = false, imageInline = false, mention = createLoomaMentionExtension(), disableHighlight = false } = options;
9248
+ const { placeholder = "Type “/” for commands, or start writing…", linkOpenOnClick = false, imageInline = false, mention = createLoomaMentionExtension(), disableHighlight = false, codeLanguages } = options;
9243
9249
  return [
9244
9250
  Document,
9245
9251
  Paragraph,
@@ -9277,7 +9283,7 @@ function getDefaultEditorExtensions(options = {}) {
9277
9283
  (disableHighlight ? StoredOnlyHighlight : Highlight).configure({ multicolor: false }),
9278
9284
  Code,
9279
9285
  LoomaSmartPaste,
9280
- CodeBlockLowlight.configure({ lowlight }),
9286
+ CodeBlockLowlight.configure({ lowlight: createLowlight(codeLanguages) }),
9281
9287
  Typography,
9282
9288
  Placeholder.configure({
9283
9289
  placeholder: ({ node }) => node.type.name === "paragraph" ? placeholder : "",
@@ -9,7 +9,7 @@
9
9
  export { LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LoomaActiveBlock, LoomaActiveBlockPluginKey, } from "./active-block.js";
10
10
  export { LoomaCallout, LOOMA_CALLOUT_TONES, type LoomaCalloutTone, } from "./callout.js";
11
11
  export { LoomaChip, LOOMA_CHIP_COLORS, normalizeLoomaChipColor, type LoomaChipColor } from "./chip.js";
12
- export { getDefaultEditorExtensions, getLoomaTableExtensions, LoomaTableKit, type DefaultEditorExtensionsOptions, } from "./preset.js";
12
+ export { getDefaultEditorExtensions, getLoomaTableExtensions, LoomaTableKit, type DefaultEditorExtensionsOptions, type LoomaCodeLanguages, } from "./preset.js";
13
13
  export { LoomaSmartPaste } from "./smart-paste.js";
14
14
  export { getActiveTableUiState, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, shouldShowTextFormattingToolbar, type ActiveTableUiState, type InsertTableAtRangeOptions, type TableActionCapabilities, } from "./table-commands.js";
15
15
  export { LoomaTable, getActiveTableCellAlignment, getActiveTableCellBackground, LoomaTableCell, LoomaTableHeader, setActiveTableCellAlignment, setActiveTableCellBackground, TABLE_CELL_BACKGROUND_PRESETS, type TableCellAlignment, type TableCellBackground, } from "./table-formatting.js";
@@ -3,6 +3,9 @@
3
3
  * Uses the Vanilla JS Tiptap API; apps provide @tiptap/core and Looma ships the preset extensions.
4
4
  */
5
5
  import { type AnyExtension } from "@tiptap/core";
6
+ import { createLowlight } from "lowlight";
7
+ /** Grammars supplied by the host; importing a language remains the host's choice. */
8
+ export type LoomaCodeLanguages = NonNullable<Parameters<typeof createLowlight>[0]>;
6
9
  /**
7
10
  * Deliberate policy knobs in Looma's default extension set.
8
11
  * Consumers needing different schemas should compose an explicit Tiptap list
@@ -24,6 +27,8 @@ export interface DefaultEditorExtensionsOptions {
24
27
  * and render. Use it when the application reserves highlighting for itself.
25
28
  */
26
29
  disableHighlight?: boolean;
30
+ /** Code block grammars to register. None are loaded by default. */
31
+ codeLanguages?: LoomaCodeLanguages;
27
32
  }
28
33
  /**
29
34
  * 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.16.4",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -8489,6 +8489,27 @@ html[data-ui-input-modality="touch"]
8489
8489
  background: none;
8490
8490
  }
8491
8491
 
8492
+ .looma-editor .ProseMirror pre :is(.hljs-keyword, .hljs-literal, .hljs-selector-tag) {
8493
+ color: var(--ui-editor-code-keyword, var(--ui-accent-solid));
8494
+ }
8495
+
8496
+ .looma-editor .ProseMirror pre :is(.hljs-string, .hljs-attr, .hljs-addition) {
8497
+ color: var(--ui-editor-code-string, var(--ui-success-subtle-text));
8498
+ }
8499
+
8500
+ .looma-editor .ProseMirror pre :is(.hljs-number, .hljs-type, .hljs-built_in) {
8501
+ color: var(--ui-editor-code-number, var(--ui-warning-subtle-text));
8502
+ }
8503
+
8504
+ .looma-editor .ProseMirror pre :is(.hljs-title, .hljs-function, .hljs-variable) {
8505
+ color: var(--ui-editor-code-name, var(--ui-info-subtle-text));
8506
+ }
8507
+
8508
+ .looma-editor .ProseMirror pre .hljs-comment {
8509
+ color: var(--ui-editor-code-comment, var(--ui-text-secondary));
8510
+ font-style: italic;
8511
+ }
8512
+
8492
8513
  .looma-editor .ProseMirror hr {
8493
8514
  margin: var(--ui-space-6) 0;
8494
8515
  border: 0;
@@ -1,7 +1,7 @@
1
1
  import "./looma-editor.css";
2
2
  import type { AnyExtension, Editor, JSONContent } from "@tiptap/core";
3
3
  import { type PropType, type VNode } from "vue";
4
- import { type LoomaMentionItem, type LoomaMentionProvider } from "@threadlabs/looma/editor";
4
+ import { type LoomaMentionItem, type LoomaMentionProvider, type LoomaCodeLanguages } from "@threadlabs/looma/editor";
5
5
  import { type LoomaImageActivationDetail, type LoomaImageAttributeResolver, type LoomaImageDescriptor, type LoomaImageRenditionErrorDetail } from "./image-delivery.js";
6
6
  /**
7
7
  * Host upload result normalized into the editor's durable image descriptor.
@@ -70,6 +70,11 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
70
70
  type: PropType<AnyExtension[]>;
71
71
  default: () => never[];
72
72
  };
73
+ /** Code block grammars to register when this editor is created. */
74
+ codeLanguages: {
75
+ type: PropType<LoomaCodeLanguages>;
76
+ default: () => {};
77
+ };
73
78
  mentionItems: {
74
79
  type: PropType<LoomaMentionItem[]>;
75
80
  default: () => never[];
@@ -144,6 +149,11 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
144
149
  type: PropType<AnyExtension[]>;
145
150
  default: () => never[];
146
151
  };
152
+ /** Code block grammars to register when this editor is created. */
153
+ codeLanguages: {
154
+ type: PropType<LoomaCodeLanguages>;
155
+ default: () => {};
156
+ };
147
157
  mentionItems: {
148
158
  type: PropType<LoomaMentionItem[]>;
149
159
  default: () => never[];
@@ -187,6 +197,7 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
187
197
  label: string;
188
198
  placeholder: string;
189
199
  disableHighlight: boolean;
200
+ codeLanguages: Readonly<Record<string, import("highlight.js").LanguageFn>>;
190
201
  modelValue: JSONContent;
191
202
  editable: boolean;
192
203
  extensions: AnyExtension[];
@@ -299,6 +299,11 @@ var LoomaEditor = defineComponent({
299
299
  type: Array,
300
300
  default: () => []
301
301
  },
302
+ /** Code block grammars to register when this editor is created. */
303
+ codeLanguages: {
304
+ type: Object,
305
+ default: () => ({})
306
+ },
302
307
  mentionItems: {
303
308
  type: Array,
304
309
  default: () => []
@@ -512,7 +517,8 @@ var LoomaEditor = defineComponent({
512
517
  ...getDefaultEditorExtensions({
513
518
  placeholder: props.placeholder,
514
519
  mention: mentionExtension ?? false,
515
- disableHighlight: props.disableHighlight
520
+ disableHighlight: props.disableHighlight,
521
+ codeLanguages: props.codeLanguages
516
522
  }),
517
523
  imageDelivery.extension,
518
524
  slashExtension,