@threadlabs/looma 0.29.6 → 0.29.7
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.
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Editor } from "@tiptap/core";
|
|
2
|
+
/** The code block the selection lies in: its position, saved language (`auto` when none), text, and element. */
|
|
3
|
+
export interface LoomaCodeBlockAtSelection {
|
|
4
|
+
readonly pos: number;
|
|
5
|
+
readonly language: string;
|
|
6
|
+
readonly text: string;
|
|
7
|
+
readonly element: HTMLElement;
|
|
8
|
+
}
|
|
9
|
+
/** The code block holding the whole selection, or null when the selection is elsewhere or spans blocks. */
|
|
10
|
+
export declare function codeBlockAtSelection(editor: Editor): LoomaCodeBlockAtSelection | null;
|
|
11
|
+
/**
|
|
12
|
+
* The picker's choices: Auto, naming the detected language when there is one; a saved language the
|
|
13
|
+
* catalog lacks, marked unavailable, so it stays selected; then every catalog language.
|
|
14
|
+
*/
|
|
15
|
+
export declare function codeLanguageChoices(language: string, detected: string | null, names: readonly string[]): Array<{
|
|
16
|
+
value: string;
|
|
17
|
+
label: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** Centers the picker over the code block, above it when there is room and below it otherwise. */
|
|
20
|
+
export declare function codeLanguagePickerPlacement(block: DOMRect): {
|
|
21
|
+
top: string;
|
|
22
|
+
left: string;
|
|
23
|
+
transform: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Saves `value` as the language of the code block at `pos`, as its own undo step; `auto` clears it.
|
|
27
|
+
* @failure Returns false, and changes nothing, for a language outside `names` or no code block at `pos`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function setCodeBlockLanguage(editor: Editor, pos: number, value: string, names: readonly string[]): boolean;
|
|
@@ -53,6 +53,7 @@ export interface ActiveTableUiState {
|
|
|
53
53
|
headerColumn: boolean;
|
|
54
54
|
capabilities: TableActionCapabilities;
|
|
55
55
|
}
|
|
56
|
+
export declare const NO_TABLE_CAPABILITIES: TableActionCapabilities;
|
|
56
57
|
/**
|
|
57
58
|
* Text formatting belongs to actual text selections, not table CellSelections.
|
|
58
59
|
*
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ActiveTableUiState, type TableActionCapabilities } from "./extensions/table-commands.js";
|
|
2
|
+
import type { TableCellAlignment, TableCellBackground } from "./extensions/table-formatting.js";
|
|
3
|
+
/** What the table's controls show: the toolbar and overlay, and the selected cells' formatting and actions. */
|
|
4
|
+
export interface LoomaTableControls {
|
|
5
|
+
readonly toolbarOpen: boolean;
|
|
6
|
+
readonly overlayOpen: boolean;
|
|
7
|
+
readonly alignment: TableCellAlignment;
|
|
8
|
+
readonly background: TableCellBackground;
|
|
9
|
+
readonly headerRow: boolean;
|
|
10
|
+
readonly headerColumn: boolean;
|
|
11
|
+
readonly capabilities: TableActionCapabilities;
|
|
12
|
+
}
|
|
13
|
+
export declare const LOOMA_TABLE_CONTROLS_CLOSED: LoomaTableControls;
|
|
14
|
+
/**
|
|
15
|
+
* The controls for the table shown: its overlay on wider screens, and the toolbar and the selection's
|
|
16
|
+
* formatting only while the selection is in that table. A table that is only hovered shows its overlay
|
|
17
|
+
* with nothing selected; narrow screens use the editing dock instead of the toolbar and overlay.
|
|
18
|
+
*/
|
|
19
|
+
export declare function tableControls(state: ActiveTableUiState, selectionInTable: boolean, narrow: boolean): LoomaTableControls;
|
|
20
|
+
/**
|
|
21
|
+
* Centers the table toolbar on the table, at most 420px wide and 12px inside the viewport's sides,
|
|
22
|
+
* above the table when there is room and below it otherwise.
|
|
23
|
+
*/
|
|
24
|
+
export declare function tableToolbarPlacement(table: DOMRect, viewportWidth: number): {
|
|
25
|
+
top: string;
|
|
26
|
+
left: string;
|
|
27
|
+
maxWidth: string;
|
|
28
|
+
};
|
|
29
|
+
/** The overlay covers the table exactly. */
|
|
30
|
+
export declare const tableOverlayPlacement: (table: DOMRect) => {
|
|
31
|
+
top: string;
|
|
32
|
+
left: string;
|
|
33
|
+
width: string;
|
|
34
|
+
height: string;
|
|
35
|
+
};
|
package/package.json
CHANGED
|
@@ -384,6 +384,7 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
|
|
|
384
384
|
linkBaseUrl: string;
|
|
385
385
|
disableHighlight: boolean;
|
|
386
386
|
codeLanguages: Readonly<Record<string, import("highlight.js").LanguageFn>> | null;
|
|
387
|
+
toolbarOpen: boolean;
|
|
387
388
|
modelValue: JSONContent;
|
|
388
389
|
slashCommands: LoomaEditorSlashCommands | undefined;
|
|
389
390
|
mentionQuery: LoomaMentionQuery | undefined;
|
|
@@ -401,5 +402,4 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
|
|
|
401
402
|
selectionActions: LoomaEditorSelectionAction[];
|
|
402
403
|
rangeActions: LoomaEditorRangeAction[];
|
|
403
404
|
toolbarTriggerId: string;
|
|
404
|
-
toolbarOpen: boolean;
|
|
405
405
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defineComponent, h, onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
2
2
|
import { Extension, Mark, Node, markInputRule, markPasteRule, mergeAttributes } from "@tiptap/core";
|
|
3
3
|
import { Editor as Editor$1, EditorContent } from "@tiptap/vue-3";
|
|
4
|
-
import { closeHistory, history, redo, undo } from "@tiptap/pm/history";
|
|
5
4
|
import { Plugin } from "@tiptap/pm/state";
|
|
5
|
+
import { closeHistory, history, redo, undo } from "@tiptap/pm/history";
|
|
6
6
|
//#region ../../node_modules/.pnpm/@tiptap+extension-document@2.27.2_@tiptap+core@2.27.2_@tiptap+pm@2.27.2_/node_modules/@tiptap/extension-document/dist/index.js
|
|
7
7
|
/**
|
|
8
8
|
* The default document node which represents the top level node of the editor.
|
package/vue/editor/index.js
CHANGED
|
@@ -3,12 +3,12 @@ import { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ICONS, createLoomaMentionExtension,
|
|
|
3
3
|
import { Button, Callout, Card, Checkbox, Cluster, Disclosure, EditorBlockActions, EditorChipEditor, EditorCodeLanguage, EditorImageToolbar, EditorInsertTableGrid, EditorLinkCard, EditorLinkForm, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorSurface, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, FormField, Icon, IconButton, Image, Input, List, Menu, MenuItem, Popover, Separator, Stack, StatusMessage, Text, Tooltip } from "@threadlabs/looma/vue";
|
|
4
4
|
import { Editor, Extension, Node as Node$1, getText, getTextSerializersFromSchema, isNodeSelection, mergeAttributes, nodeInputRule, posToDOMRect } from "@tiptap/core";
|
|
5
5
|
import { Editor as Editor$1 } from "@tiptap/vue-3";
|
|
6
|
-
import { closeHistory } from "@tiptap/pm/history";
|
|
7
6
|
import { AllSelection, NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
|
|
8
7
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
9
8
|
import { createLowlight } from "lowlight";
|
|
10
9
|
import "@tiptap/pm/tables";
|
|
11
10
|
import "@tiptap/pm/transform";
|
|
11
|
+
import { closeHistory } from "@tiptap/pm/history";
|
|
12
12
|
import { DOMParser, DOMSerializer, Fragment as Fragment$1 } from "@tiptap/pm/model";
|
|
13
13
|
export * from "@threadlabs/looma/editor";
|
|
14
14
|
//#region src/vue/editor/primitives.ts
|
|
@@ -1562,6 +1562,23 @@ function selectedTableCellElement(editor) {
|
|
|
1562
1562
|
}
|
|
1563
1563
|
//#endregion
|
|
1564
1564
|
//#region src/editor/extensions/table-commands.ts
|
|
1565
|
+
var NO_TABLE_CAPABILITIES = {
|
|
1566
|
+
canToggleHeaderRow: false,
|
|
1567
|
+
canToggleHeaderColumn: false,
|
|
1568
|
+
canMoveRowUp: false,
|
|
1569
|
+
canMoveRowDown: false,
|
|
1570
|
+
canMoveColumnLeft: false,
|
|
1571
|
+
canMoveColumnRight: false,
|
|
1572
|
+
canAddRowBefore: false,
|
|
1573
|
+
canAddRowAfter: false,
|
|
1574
|
+
canAddColumnBefore: false,
|
|
1575
|
+
canAddColumnAfter: false,
|
|
1576
|
+
canDeleteRow: false,
|
|
1577
|
+
canDeleteColumn: false,
|
|
1578
|
+
canDeleteTable: false,
|
|
1579
|
+
canMergeCells: false,
|
|
1580
|
+
canSplitCell: false
|
|
1581
|
+
};
|
|
1565
1582
|
/**
|
|
1566
1583
|
* Moves the caret to the cell an overlay action names when the action comes from a table other
|
|
1567
1584
|
* than the selected one, so table commands act on that table. A cell menu also selects its cell,
|
|
@@ -1879,6 +1896,59 @@ function selectionActionDetail(state, id) {
|
|
|
1879
1896
|
after: doc.textBetween(to, Math.min(doc.content.size, to + CONTEXT), "\n")
|
|
1880
1897
|
};
|
|
1881
1898
|
}
|
|
1899
|
+
//#endregion
|
|
1900
|
+
//#region src/editor/table-ui.ts
|
|
1901
|
+
var LOOMA_TABLE_CONTROLS_CLOSED = Object.freeze({
|
|
1902
|
+
toolbarOpen: false,
|
|
1903
|
+
overlayOpen: false,
|
|
1904
|
+
alignment: "left",
|
|
1905
|
+
background: null,
|
|
1906
|
+
headerRow: false,
|
|
1907
|
+
headerColumn: false,
|
|
1908
|
+
capabilities: Object.freeze({ ...NO_TABLE_CAPABILITIES })
|
|
1909
|
+
});
|
|
1910
|
+
/**
|
|
1911
|
+
* The controls for the table shown: its overlay on wider screens, and the toolbar and the selection's
|
|
1912
|
+
* formatting only while the selection is in that table. A table that is only hovered shows its overlay
|
|
1913
|
+
* with nothing selected; narrow screens use the editing dock instead of the toolbar and overlay.
|
|
1914
|
+
*/
|
|
1915
|
+
function tableControls(state, selectionInTable, narrow) {
|
|
1916
|
+
if (!selectionInTable) return {
|
|
1917
|
+
...LOOMA_TABLE_CONTROLS_CLOSED,
|
|
1918
|
+
overlayOpen: !narrow
|
|
1919
|
+
};
|
|
1920
|
+
return {
|
|
1921
|
+
toolbarOpen: state.showToolbar && !narrow,
|
|
1922
|
+
overlayOpen: !narrow,
|
|
1923
|
+
alignment: state.cellAlignment,
|
|
1924
|
+
background: state.cellBackground,
|
|
1925
|
+
headerRow: state.headerRow,
|
|
1926
|
+
headerColumn: state.headerColumn,
|
|
1927
|
+
capabilities: state.capabilities
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
/** Space, in pixels, the toolbar needs above a table; with less it sits below. */
|
|
1931
|
+
var ROOM_ABOVE$1 = 76;
|
|
1932
|
+
/**
|
|
1933
|
+
* Centers the table toolbar on the table, at most 420px wide and 12px inside the viewport's sides,
|
|
1934
|
+
* above the table when there is room and below it otherwise.
|
|
1935
|
+
*/
|
|
1936
|
+
function tableToolbarPlacement(table, viewportWidth) {
|
|
1937
|
+
const width = Math.min(420, viewportWidth - 24);
|
|
1938
|
+
const left = Math.min(Math.max(12, table.left + (table.width - width) / 2), Math.max(12, viewportWidth - width - 12));
|
|
1939
|
+
return {
|
|
1940
|
+
top: `${table.top > ROOM_ABOVE$1 ? table.top - 52 : table.bottom + 12}px`,
|
|
1941
|
+
left: `${left}px`,
|
|
1942
|
+
maxWidth: `${width}px`
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
/** The overlay covers the table exactly. */
|
|
1946
|
+
var tableOverlayPlacement = (table) => ({
|
|
1947
|
+
top: `${table.top}px`,
|
|
1948
|
+
left: `${table.left}px`,
|
|
1949
|
+
width: `${table.width}px`,
|
|
1950
|
+
height: `${table.height}px`
|
|
1951
|
+
});
|
|
1882
1952
|
/** Whether a viewport this wide gets the editing dock rather than floating tools. */
|
|
1883
1953
|
var usesMobileDock = (viewportWidth) => viewportWidth <= 767;
|
|
1884
1954
|
/**
|
|
@@ -2485,6 +2555,71 @@ function createToolbarTooltip(onChange) {
|
|
|
2485
2555
|
};
|
|
2486
2556
|
}
|
|
2487
2557
|
//#endregion
|
|
2558
|
+
//#region src/editor/code-language-picker.ts
|
|
2559
|
+
/** The code block holding the whole selection, or null when the selection is elsewhere or spans blocks. */
|
|
2560
|
+
function codeBlockAtSelection(editor) {
|
|
2561
|
+
const { $from, $to } = editor.state.selection;
|
|
2562
|
+
const block = $from.parent;
|
|
2563
|
+
if (block.type.name !== "codeBlock" || !$from.sameParent($to)) return null;
|
|
2564
|
+
const pos = $from.before();
|
|
2565
|
+
const element = editor.view.nodeDOM(pos);
|
|
2566
|
+
if (!(element instanceof HTMLElement)) return null;
|
|
2567
|
+
return {
|
|
2568
|
+
pos,
|
|
2569
|
+
language: typeof block.attrs.language === "string" && block.attrs.language ? block.attrs.language : "auto",
|
|
2570
|
+
text: block.textContent,
|
|
2571
|
+
element
|
|
2572
|
+
};
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* The picker's choices: Auto, naming the detected language when there is one; a saved language the
|
|
2576
|
+
* catalog lacks, marked unavailable, so it stays selected; then every catalog language.
|
|
2577
|
+
*/
|
|
2578
|
+
function codeLanguageChoices(language, detected, names) {
|
|
2579
|
+
return [
|
|
2580
|
+
{
|
|
2581
|
+
value: "auto",
|
|
2582
|
+
label: detected ? `Auto (${detected.toUpperCase()})` : "Auto"
|
|
2583
|
+
},
|
|
2584
|
+
...language !== "auto" && !names.includes(language) ? [{
|
|
2585
|
+
value: language,
|
|
2586
|
+
label: `${language.toUpperCase()} (unavailable)`
|
|
2587
|
+
}] : [],
|
|
2588
|
+
...names.map((name) => ({
|
|
2589
|
+
value: name,
|
|
2590
|
+
label: name.toUpperCase()
|
|
2591
|
+
}))
|
|
2592
|
+
];
|
|
2593
|
+
}
|
|
2594
|
+
/** Space, in pixels, the picker needs above a code block; with less it sits below. */
|
|
2595
|
+
var ROOM_ABOVE = 76;
|
|
2596
|
+
/** Centers the picker over the code block, above it when there is room and below it otherwise. */
|
|
2597
|
+
function codeLanguagePickerPlacement(block) {
|
|
2598
|
+
const above = block.top > ROOM_ABOVE;
|
|
2599
|
+
return {
|
|
2600
|
+
top: `${above ? block.top - 8 : block.bottom + 8}px`,
|
|
2601
|
+
left: `${block.left + block.width / 2}px`,
|
|
2602
|
+
transform: `translate(-50%, ${above ? "-100%" : "0"})`
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2605
|
+
/**
|
|
2606
|
+
* Saves `value` as the language of the code block at `pos`, as its own undo step; `auto` clears it.
|
|
2607
|
+
* @failure Returns false, and changes nothing, for a language outside `names` or no code block at `pos`.
|
|
2608
|
+
*/
|
|
2609
|
+
function setCodeBlockLanguage(editor, pos, value, names) {
|
|
2610
|
+
const language = value === "auto" ? null : value;
|
|
2611
|
+
if (language !== null && !names.includes(language)) return false;
|
|
2612
|
+
const node = editor.state.doc.nodeAt(pos);
|
|
2613
|
+
if (node?.type.name !== "codeBlock") return false;
|
|
2614
|
+
editor.view.dispatch(closeHistory(editor.state.tr));
|
|
2615
|
+
editor.view.dispatch(editor.state.tr.setNodeMarkup(pos, void 0, {
|
|
2616
|
+
...node.attrs,
|
|
2617
|
+
language
|
|
2618
|
+
}));
|
|
2619
|
+
editor.view.dispatch(closeHistory(editor.state.tr));
|
|
2620
|
+
return true;
|
|
2621
|
+
}
|
|
2622
|
+
//#endregion
|
|
2488
2623
|
//#region src/editor/extensions/expand.ts
|
|
2489
2624
|
/**
|
|
2490
2625
|
* Reveals collapsed ancestors before a host navigates to a document position.
|
|
@@ -3389,23 +3524,6 @@ var EMPTY_DOCUMENT = {
|
|
|
3389
3524
|
};
|
|
3390
3525
|
var uploadProgressText = (progress) => progress && progress.total > 0 ? `Uploading image… ${Math.round(Math.min(1, progress.loaded / progress.total) * 100)}%` : "Uploading image…";
|
|
3391
3526
|
var editorInstanceSequence = 0;
|
|
3392
|
-
var EMPTY_CAPABILITIES = {
|
|
3393
|
-
canToggleHeaderRow: false,
|
|
3394
|
-
canToggleHeaderColumn: false,
|
|
3395
|
-
canMoveRowUp: false,
|
|
3396
|
-
canMoveRowDown: false,
|
|
3397
|
-
canMoveColumnLeft: false,
|
|
3398
|
-
canMoveColumnRight: false,
|
|
3399
|
-
canAddRowBefore: false,
|
|
3400
|
-
canAddRowAfter: false,
|
|
3401
|
-
canAddColumnBefore: false,
|
|
3402
|
-
canAddColumnAfter: false,
|
|
3403
|
-
canDeleteRow: false,
|
|
3404
|
-
canDeleteColumn: false,
|
|
3405
|
-
canDeleteTable: false,
|
|
3406
|
-
canMergeCells: false,
|
|
3407
|
-
canSplitCell: false
|
|
3408
|
-
};
|
|
3409
3527
|
function slashMenuRows(items) {
|
|
3410
3528
|
const groups = [];
|
|
3411
3529
|
for (const [index, item] of items.entries()) {
|
|
@@ -3695,7 +3813,7 @@ var LoomaEditor = defineComponent({
|
|
|
3695
3813
|
toolbarStyle: {},
|
|
3696
3814
|
overlayStyle: {},
|
|
3697
3815
|
menuStyle: {},
|
|
3698
|
-
capabilities:
|
|
3816
|
+
capabilities: LOOMA_TABLE_CONTROLS_CLOSED.capabilities
|
|
3699
3817
|
});
|
|
3700
3818
|
const openChipEditor = (_instance, position) => {
|
|
3701
3819
|
if (!chipEditing?.open(position)) return;
|
|
@@ -4114,16 +4232,10 @@ var LoomaEditor = defineComponent({
|
|
|
4114
4232
|
if (session.setContent(value, lastFocusedSelection) && wasFocused) rememberSelection(instance);
|
|
4115
4233
|
}, { deep: true });
|
|
4116
4234
|
const closeTableUi = () => {
|
|
4117
|
-
tableUi
|
|
4118
|
-
tableUi.overlayOpen = false;
|
|
4235
|
+
Object.assign(tableUi, LOOMA_TABLE_CONTROLS_CLOSED);
|
|
4119
4236
|
tableUi.menuOpen = false;
|
|
4120
4237
|
tableUi.menuScope = "cell";
|
|
4121
|
-
tableUi.alignment = "left";
|
|
4122
|
-
tableUi.background = null;
|
|
4123
|
-
tableUi.headerRow = false;
|
|
4124
|
-
tableUi.headerColumn = false;
|
|
4125
4238
|
tableUi.geometry = null;
|
|
4126
|
-
tableUi.capabilities = { ...EMPTY_CAPABILITIES };
|
|
4127
4239
|
overlayTableElement = null;
|
|
4128
4240
|
mobileDock.tableInactive();
|
|
4129
4241
|
};
|
|
@@ -4145,63 +4257,31 @@ var LoomaEditor = defineComponent({
|
|
|
4145
4257
|
let codeBlurTimer;
|
|
4146
4258
|
const updateCodeUi = (focusSettled = false) => {
|
|
4147
4259
|
const instance = editor.value?.isDestroyed ? void 0 : editor.value;
|
|
4148
|
-
const
|
|
4149
|
-
|
|
4150
|
-
const dom = instance && block?.type.name === "codeBlock" && selection.$from.sameParent(selection.$to) ? instance.view.nodeDOM(selection.$from.before()) : null;
|
|
4151
|
-
if (!instance || !props.editable || !codeLanguageNames.length || !(dom instanceof HTMLElement)) {
|
|
4260
|
+
const block = instance ? codeBlockAtSelection(instance) : null;
|
|
4261
|
+
if (!instance || !props.editable || !codeLanguageNames.length || !block) {
|
|
4152
4262
|
codeUi.open = false;
|
|
4153
4263
|
return;
|
|
4154
4264
|
}
|
|
4155
|
-
loadForCodeBlock(instance, block.
|
|
4265
|
+
loadForCodeBlock(instance, block.language === "auto" ? null : block.language, block.text);
|
|
4156
4266
|
if (!instance.isFocused && !codeLanguageShell.value?.contains(document.activeElement)) {
|
|
4157
4267
|
clearTimeout(codeBlurTimer);
|
|
4158
4268
|
if (codeUi.open && !focusSettled) codeBlurTimer = setTimeout(() => updateCodeUi(true), 0);
|
|
4159
4269
|
else codeUi.open = false;
|
|
4160
4270
|
return;
|
|
4161
4271
|
}
|
|
4162
|
-
const rect = dom.getBoundingClientRect();
|
|
4163
|
-
const above = rect.top > 76;
|
|
4164
4272
|
codeUi.open = true;
|
|
4165
|
-
codeUi.pos =
|
|
4166
|
-
codeUi.language =
|
|
4167
|
-
codeUi.text = block.
|
|
4168
|
-
codeUi.style =
|
|
4169
|
-
top: `${above ? rect.top - 8 : rect.bottom + 8}px`,
|
|
4170
|
-
left: `${rect.left + rect.width / 2}px`,
|
|
4171
|
-
transform: `translate(-50%, ${above ? "-100%" : "0"})`
|
|
4172
|
-
};
|
|
4273
|
+
codeUi.pos = block.pos;
|
|
4274
|
+
codeUi.language = block.language;
|
|
4275
|
+
codeUi.text = block.text;
|
|
4276
|
+
codeUi.style = codeLanguagePickerPlacement(block.element.getBoundingClientRect());
|
|
4173
4277
|
};
|
|
4174
4278
|
const codeLanguageOptions = computed(() => {
|
|
4175
4279
|
codeUi.grammarVersion;
|
|
4176
4280
|
const detected = codeUi.open && codeUi.text.trim() ? codeHighlighting.lowlight.highlightAuto(codeUi.text).data?.language : null;
|
|
4177
|
-
return
|
|
4178
|
-
{
|
|
4179
|
-
value: "auto",
|
|
4180
|
-
label: typeof detected === "string" ? `Auto (${detected.toUpperCase()})` : "Auto"
|
|
4181
|
-
},
|
|
4182
|
-
...codeUi.language !== "auto" && !codeLanguageNames.includes(codeUi.language) ? [{
|
|
4183
|
-
value: codeUi.language,
|
|
4184
|
-
label: `${codeUi.language.toUpperCase()} (unavailable)`
|
|
4185
|
-
}] : [],
|
|
4186
|
-
...codeLanguageNames.map((name) => ({
|
|
4187
|
-
value: name,
|
|
4188
|
-
label: name.toUpperCase()
|
|
4189
|
-
}))
|
|
4190
|
-
];
|
|
4281
|
+
return codeLanguageChoices(codeUi.language, typeof detected === "string" ? detected : null, codeLanguageNames);
|
|
4191
4282
|
});
|
|
4192
4283
|
const chooseCodeLanguage = (value) => {
|
|
4193
|
-
|
|
4194
|
-
if (!instance) return;
|
|
4195
|
-
const language = value === "auto" ? null : value;
|
|
4196
|
-
if (language !== null && !codeLanguageNames.includes(language)) return;
|
|
4197
|
-
const node = instance.state.doc.nodeAt(codeUi.pos);
|
|
4198
|
-
if (node?.type.name !== "codeBlock") return;
|
|
4199
|
-
instance.view.dispatch(closeHistory(instance.state.tr));
|
|
4200
|
-
instance.view.dispatch(instance.state.tr.setNodeMarkup(codeUi.pos, void 0, {
|
|
4201
|
-
...node.attrs,
|
|
4202
|
-
language
|
|
4203
|
-
}));
|
|
4204
|
-
instance.view.dispatch(closeHistory(instance.state.tr));
|
|
4284
|
+
if (editor.value) setCodeBlockLanguage(editor.value, codeUi.pos, value, codeLanguageNames);
|
|
4205
4285
|
};
|
|
4206
4286
|
const onCodeTransaction = () => updateCodeUi();
|
|
4207
4287
|
watch(() => props.editable, () => nextTick(onCodeTransaction));
|
|
@@ -4230,31 +4310,14 @@ var LoomaEditor = defineComponent({
|
|
|
4230
4310
|
overlayTableElement = table;
|
|
4231
4311
|
if (selectedTableIsActive) mobileDock.tableActive();
|
|
4232
4312
|
const rect = table.getBoundingClientRect();
|
|
4233
|
-
|
|
4234
|
-
const toolbarLeft = Math.min(Math.max(12, rect.left + (rect.width - maxToolbarWidth) / 2), Math.max(12, window.innerWidth - maxToolbarWidth - 12));
|
|
4235
|
-
tableUi.toolbarOpen = selectedTableIsActive && state.showToolbar && !mobile.value;
|
|
4236
|
-
tableUi.overlayOpen = !mobile.value;
|
|
4237
|
-
tableUi.alignment = selectedTableIsActive ? state.cellAlignment : "left";
|
|
4238
|
-
tableUi.background = selectedTableIsActive ? state.cellBackground : null;
|
|
4239
|
-
tableUi.headerRow = selectedTableIsActive && state.headerRow;
|
|
4240
|
-
tableUi.headerColumn = selectedTableIsActive && state.headerColumn;
|
|
4241
|
-
tableUi.capabilities = selectedTableIsActive ? state.capabilities : { ...EMPTY_CAPABILITIES };
|
|
4313
|
+
Object.assign(tableUi, tableControls(state, selectedTableIsActive, mobile.value));
|
|
4242
4314
|
const selectedCell = selectedTableIsActive ? selectedTableCellElement(instance) : null;
|
|
4243
4315
|
const geometry = measureTableOverlayGeometry(table, selectedCell, hoveredTableCell && table.contains(hoveredTableCell) ? hoveredTableCell : null);
|
|
4244
4316
|
tableUi.rows = Math.max(0, geometry.rowBoundaries.length - 1);
|
|
4245
4317
|
tableUi.cols = Math.max(0, geometry.columnBoundaries.length - 1);
|
|
4246
4318
|
tableUi.geometry = geometry;
|
|
4247
|
-
tableUi.toolbarStyle =
|
|
4248
|
-
|
|
4249
|
-
left: `${toolbarLeft}px`,
|
|
4250
|
-
maxWidth: `${maxToolbarWidth}px`
|
|
4251
|
-
};
|
|
4252
|
-
tableUi.overlayStyle = {
|
|
4253
|
-
top: `${rect.top}px`,
|
|
4254
|
-
left: `${rect.left}px`,
|
|
4255
|
-
width: `${rect.width}px`,
|
|
4256
|
-
height: `${rect.height}px`
|
|
4257
|
-
};
|
|
4319
|
+
tableUi.toolbarStyle = tableToolbarPlacement(rect, window.innerWidth);
|
|
4320
|
+
tableUi.overlayStyle = tableOverlayPlacement(rect);
|
|
4258
4321
|
};
|
|
4259
4322
|
const onEditorFocus = () => {
|
|
4260
4323
|
editorFocused.value = true;
|