@flogeez/angular-tiptap-editor 3.5.5 → 3.6.1
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 +27 -1
- package/README.md +2 -2
- package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +93 -21
- package/esm2022/lib/config/ate-editor.config.mjs +3 -1
- package/esm2022/lib/config/ate-slash-commands.config.mjs +2 -1
- package/esm2022/lib/directives/ate-tooltip.directive.mjs +37 -2
- package/esm2022/lib/extensions/ate-block-shortcuts.extension.mjs +100 -0
- package/esm2022/lib/extensions/ate-pasted-image.extension.mjs +7 -3
- package/esm2022/lib/i18n/ateTranslationsModel.mjs +1 -1
- package/esm2022/lib/i18n/es_ateTranslations.mjs +230 -0
- package/esm2022/lib/i18n/pt_ateTranslations.mjs +220 -0
- package/esm2022/lib/models/ate-editor-config.model.mjs +1 -1
- package/esm2022/lib/models/ate-editor-ref.mjs +3 -3
- package/esm2022/lib/models/ate-image.model.mjs +12 -2
- package/esm2022/lib/services/ate-editor-commands.service.mjs +6 -3
- package/esm2022/lib/services/ate-i18n.service.mjs +19 -9
- package/esm2022/lib/services/ate-image.service.mjs +18 -11
- package/esm2022/lib/utils/ate-extensions.utils.mjs +79 -0
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +814 -47
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/lib/components/editor/angular-tiptap-editor.component.d.ts +12 -2
- package/lib/config/ate-slash-commands.config.d.ts +2 -0
- package/lib/extensions/ate-block-shortcuts.extension.d.ts +32 -0
- package/lib/i18n/ateTranslationsModel.d.ts +1 -1
- package/lib/i18n/es_ateTranslations.d.ts +2 -0
- package/lib/i18n/pt_ateTranslations.d.ts +2 -0
- package/lib/models/ate-editor-config.model.d.ts +8 -0
- package/lib/models/ate-image.model.d.ts +30 -2
- package/lib/services/ate-editor-commands.service.d.ts +2 -1
- package/lib/services/ate-i18n.service.d.ts +3 -1
- package/lib/services/ate-image.service.d.ts +5 -3
- package/lib/utils/ate-extensions.utils.d.ts +13 -0
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, signal, inject, Injectable, computed, Directive, ApplicationRef, EnvironmentInjector, createComponent, input, booleanAttribute, effect, untracked, Component, ChangeDetectionStrategy, HostListener, ElementRef, ViewEncapsulation, output, viewChild, DestroyRef, Injector, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
|
|
2
|
+
import { InjectionToken, signal, inject, Injectable, computed, Directive, ApplicationRef, EnvironmentInjector, createComponent, input, booleanAttribute, effect, untracked, Component, ChangeDetectionStrategy, HostListener, ElementRef, ViewEncapsulation, output, viewChild, DestroyRef, Injector, isDevMode, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { Node as Node$1, mergeAttributes, nodeInputRule, Extension, getAttributes, Editor } from '@tiptap/core';
|
|
5
5
|
import StarterKit from '@tiptap/starter-kit';
|
|
@@ -11,7 +11,7 @@ import { Highlight } from '@tiptap/extension-highlight';
|
|
|
11
11
|
import { TextStyle } from '@tiptap/extension-text-style';
|
|
12
12
|
import { Color } from '@tiptap/extension-color';
|
|
13
13
|
import OfficePaste from '@intevation/tiptap-extension-office-paste';
|
|
14
|
-
import { Plugin, PluginKey,
|
|
14
|
+
import { Plugin, PluginKey, NodeSelection, TextSelection } from '@tiptap/pm/state';
|
|
15
15
|
import { DecorationSet, Decoration } from '@tiptap/pm/view';
|
|
16
16
|
import { Fragment, Slice } from '@tiptap/pm/model';
|
|
17
17
|
import { Table, TableRow, TableHeader, TableCell } from '@tiptap/extension-table';
|
|
@@ -682,6 +682,18 @@ const AteUploadProgress = Extension.create({
|
|
|
682
682
|
},
|
|
683
683
|
});
|
|
684
684
|
|
|
685
|
+
/**
|
|
686
|
+
* Thrown when an image fails validation, before compression and before `imageUploadHandler` runs.
|
|
687
|
+
* `message` is the translated, user-facing text.
|
|
688
|
+
*/
|
|
689
|
+
class AteImageValidationError extends Error {
|
|
690
|
+
constructor(reason, message) {
|
|
691
|
+
super(message);
|
|
692
|
+
this.reason = reason;
|
|
693
|
+
this.name = "AteImageValidationError";
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
685
697
|
const IMAGE_NODE_NAMES = new Set(["resizableImage", "image"]);
|
|
686
698
|
const REMOTE_SRC = /^(https?:)?\/\//i;
|
|
687
699
|
const INLINE_SRC = /^data:(image\/[\w.+-]+);base64,(.*)$/is;
|
|
@@ -812,9 +824,12 @@ const AtePastedImage = Extension.create({
|
|
|
812
824
|
options
|
|
813
825
|
.rehost(file)
|
|
814
826
|
.then(url => replaceImageSrc(editor, src, url))
|
|
815
|
-
.catch(() => {
|
|
827
|
+
.catch((error) => {
|
|
816
828
|
replaceImageSrc(editor, src, null);
|
|
817
|
-
options.onRejected({
|
|
829
|
+
options.onRejected({
|
|
830
|
+
reason: error instanceof AteImageValidationError ? error.reason : "upload-failed",
|
|
831
|
+
src,
|
|
832
|
+
});
|
|
818
833
|
});
|
|
819
834
|
};
|
|
820
835
|
return [
|
|
@@ -883,6 +898,104 @@ const AteLinkShortcut = Extension.create({
|
|
|
883
898
|
},
|
|
884
899
|
});
|
|
885
900
|
|
|
901
|
+
const LIST_ITEM_NODE_NAMES = new Set(["listItem", "taskItem"]);
|
|
902
|
+
/**
|
|
903
|
+
* Resolves the block the shortcuts act on: a selected block node, the list or task item
|
|
904
|
+
* holding the cursor, or else the top-level block holding the cursor.
|
|
905
|
+
*/
|
|
906
|
+
function findBlockAtSelection(selection) {
|
|
907
|
+
const { $from } = selection;
|
|
908
|
+
if (selection instanceof NodeSelection && selection.node.isBlock) {
|
|
909
|
+
return {
|
|
910
|
+
node: selection.node,
|
|
911
|
+
pos: selection.from,
|
|
912
|
+
parent: $from.parent,
|
|
913
|
+
index: $from.index(),
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
if ($from.depth < 1) {
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
let depth = 1;
|
|
920
|
+
for (let current = $from.depth; current > 0; current--) {
|
|
921
|
+
if (LIST_ITEM_NODE_NAMES.has($from.node(current).type.name)) {
|
|
922
|
+
depth = current;
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return {
|
|
927
|
+
node: $from.node(depth),
|
|
928
|
+
pos: $from.before(depth),
|
|
929
|
+
parent: $from.node(depth - 1),
|
|
930
|
+
index: $from.index(depth - 1),
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
/** Inserts a copy of the current block right after it */
|
|
934
|
+
function duplicateBlock(state) {
|
|
935
|
+
const block = findBlockAtSelection(state.selection);
|
|
936
|
+
if (!block) {
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
return state.tr.insert(block.pos, block.node).scrollIntoView();
|
|
940
|
+
}
|
|
941
|
+
/** Swaps the current block with its previous sibling, or returns `null` at the first position */
|
|
942
|
+
function moveBlockUp(state) {
|
|
943
|
+
const block = findBlockAtSelection(state.selection);
|
|
944
|
+
if (!block || block.index === 0) {
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
const previous = block.parent.child(block.index - 1);
|
|
948
|
+
const end = block.pos + block.node.nodeSize;
|
|
949
|
+
return state.tr
|
|
950
|
+
.insert(end, previous)
|
|
951
|
+
.delete(block.pos - previous.nodeSize, block.pos)
|
|
952
|
+
.scrollIntoView();
|
|
953
|
+
}
|
|
954
|
+
/** Swaps the current block with its next sibling, or returns `null` at the last position */
|
|
955
|
+
function moveBlockDown(state) {
|
|
956
|
+
const block = findBlockAtSelection(state.selection);
|
|
957
|
+
if (!block || block.index >= block.parent.childCount - 1) {
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
const next = block.parent.child(block.index + 1);
|
|
961
|
+
const end = block.pos + block.node.nodeSize;
|
|
962
|
+
return state.tr
|
|
963
|
+
.delete(end, end + next.nodeSize)
|
|
964
|
+
.insert(block.pos, next)
|
|
965
|
+
.scrollIntoView();
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Notion-style block shortcuts: `Mod+D` duplicates the current block, `Mod+Shift+ArrowUp` and
|
|
969
|
+
* `Mod+Shift+ArrowDown` move it one sibling up or down. Inside a list the block is the list
|
|
970
|
+
* or task item, which moves within its list. At the edges the key event is left alone.
|
|
971
|
+
*/
|
|
972
|
+
const AteBlockShortcuts = Extension.create({
|
|
973
|
+
name: "ateBlockShortcuts",
|
|
974
|
+
addOptions() {
|
|
975
|
+
return {
|
|
976
|
+
enabled: () => true,
|
|
977
|
+
};
|
|
978
|
+
},
|
|
979
|
+
addKeyboardShortcuts() {
|
|
980
|
+
const run = (build) => () => {
|
|
981
|
+
if (!this.options.enabled() || !this.editor.isEditable) {
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
const transaction = build(this.editor.state);
|
|
985
|
+
if (!transaction) {
|
|
986
|
+
return false;
|
|
987
|
+
}
|
|
988
|
+
this.editor.view.dispatch(transaction);
|
|
989
|
+
return true;
|
|
990
|
+
};
|
|
991
|
+
return {
|
|
992
|
+
"Mod-d": run(duplicateBlock),
|
|
993
|
+
"Mod-Shift-ArrowUp": run(moveBlockUp),
|
|
994
|
+
"Mod-Shift-ArrowDown": run(moveBlockDown),
|
|
995
|
+
};
|
|
996
|
+
},
|
|
997
|
+
});
|
|
998
|
+
|
|
886
999
|
const AteTableExtension = Extension.create({
|
|
887
1000
|
name: "tableExtension",
|
|
888
1001
|
addExtensions() {
|
|
@@ -1471,13 +1584,13 @@ class AteEditorRef {
|
|
|
1471
1584
|
insertImage(options) {
|
|
1472
1585
|
const editor = this.editor;
|
|
1473
1586
|
if (editor) {
|
|
1474
|
-
this.commandsService.insertImage(editor, options);
|
|
1587
|
+
this.commandsService.insertImage(editor, options).catch(() => undefined);
|
|
1475
1588
|
}
|
|
1476
1589
|
}
|
|
1477
1590
|
uploadImage(file, options) {
|
|
1478
1591
|
const editor = this.editor;
|
|
1479
1592
|
if (editor) {
|
|
1480
|
-
this.commandsService.uploadImage(editor, file, options);
|
|
1593
|
+
this.commandsService.uploadImage(editor, file, options).catch(() => undefined);
|
|
1481
1594
|
}
|
|
1482
1595
|
}
|
|
1483
1596
|
toggleHighlight(color) {
|
|
@@ -2348,6 +2461,456 @@ const GERMAN_TRANSLATIONS = {
|
|
|
2348
2461
|
},
|
|
2349
2462
|
};
|
|
2350
2463
|
|
|
2464
|
+
const PORTUGUESE_TRANSLATIONS = {
|
|
2465
|
+
toolbar: {
|
|
2466
|
+
bold: "Negrito\nCtrl+B",
|
|
2467
|
+
italic: "Itálico\nCtrl+I",
|
|
2468
|
+
underline: "Sublinhado\nCtrl+U",
|
|
2469
|
+
strike: "Tachado\nCtrl+Shift+X",
|
|
2470
|
+
code: "Código em linha\nCtrl+E",
|
|
2471
|
+
codeBlock: "Bloco de código",
|
|
2472
|
+
superscript: "Sobrescrito",
|
|
2473
|
+
subscript: "Subscrito",
|
|
2474
|
+
highlight: "Destacar",
|
|
2475
|
+
highlightPicker: "Cor de destaque",
|
|
2476
|
+
heading1: "Título 1",
|
|
2477
|
+
heading2: "Título 2",
|
|
2478
|
+
heading3: "Título 3",
|
|
2479
|
+
bulletList: "Lista com marcadores",
|
|
2480
|
+
orderedList: "Lista numerada",
|
|
2481
|
+
blockquote: "Citação",
|
|
2482
|
+
alignLeft: "Alinhar à esquerda",
|
|
2483
|
+
alignCenter: "Centralizar",
|
|
2484
|
+
alignRight: "Alinhar à direita",
|
|
2485
|
+
alignJustify: "Justificar",
|
|
2486
|
+
link: "Inserir link",
|
|
2487
|
+
image: "Inserir imagem",
|
|
2488
|
+
horizontalRule: "Linha horizontal",
|
|
2489
|
+
table: "Inserir tabela",
|
|
2490
|
+
undo: "Desfazer\nCtrl+Z",
|
|
2491
|
+
redo: "Refazer\nCtrl+Shift+Z",
|
|
2492
|
+
clear: "Limpar",
|
|
2493
|
+
textColor: "Cor do texto",
|
|
2494
|
+
customColor: "Cor personalizada",
|
|
2495
|
+
presets: "Predefinições",
|
|
2496
|
+
},
|
|
2497
|
+
bubbleMenu: {
|
|
2498
|
+
bold: "Negrito\nCtrl+B",
|
|
2499
|
+
italic: "Itálico\nCtrl+I",
|
|
2500
|
+
underline: "Sublinhado\nCtrl+U",
|
|
2501
|
+
strike: "Tachado\nCtrl+Shift+X",
|
|
2502
|
+
code: "Código\nCtrl+E",
|
|
2503
|
+
superscript: "Sobrescrito",
|
|
2504
|
+
subscript: "Subscrito",
|
|
2505
|
+
highlight: "Destacar",
|
|
2506
|
+
highlightPicker: "Cor de destaque",
|
|
2507
|
+
textColor: "Cor do texto",
|
|
2508
|
+
link: "Link",
|
|
2509
|
+
addLink: "Inserir link",
|
|
2510
|
+
editLink: "Editar link",
|
|
2511
|
+
removeLink: "Remover link",
|
|
2512
|
+
linkUrl: "URL do link",
|
|
2513
|
+
linkText: "Texto do link",
|
|
2514
|
+
openLink: "Abrir link",
|
|
2515
|
+
customColor: "Cor personalizada",
|
|
2516
|
+
presets: "Predefinições",
|
|
2517
|
+
},
|
|
2518
|
+
slashCommands: {
|
|
2519
|
+
heading1: {
|
|
2520
|
+
title: "Título 1",
|
|
2521
|
+
description: "Título de seção grande",
|
|
2522
|
+
keywords: ["heading", "h1", "title", "1", "header", "título", "titulo", "cabeçalho"],
|
|
2523
|
+
},
|
|
2524
|
+
heading2: {
|
|
2525
|
+
title: "Título 2",
|
|
2526
|
+
description: "Título de seção médio",
|
|
2527
|
+
keywords: ["heading", "h2", "title", "2", "header", "título", "titulo", "subtítulo"],
|
|
2528
|
+
},
|
|
2529
|
+
heading3: {
|
|
2530
|
+
title: "Título 3",
|
|
2531
|
+
description: "Título de seção pequeno",
|
|
2532
|
+
keywords: ["heading", "h3", "title", "3", "header", "título", "titulo", "subtítulo"],
|
|
2533
|
+
},
|
|
2534
|
+
bulletList: {
|
|
2535
|
+
title: "Lista com marcadores",
|
|
2536
|
+
description: "Criar uma lista com marcadores",
|
|
2537
|
+
keywords: ["bullet", "list", "ul", "unordered", "lista", "marcadores", "tópicos"],
|
|
2538
|
+
},
|
|
2539
|
+
orderedList: {
|
|
2540
|
+
title: "Lista numerada",
|
|
2541
|
+
description: "Criar uma lista numerada",
|
|
2542
|
+
keywords: ["ordered", "list", "ol", "numbered", "lista", "numerada", "ordenada"],
|
|
2543
|
+
},
|
|
2544
|
+
blockquote: {
|
|
2545
|
+
title: "Citação",
|
|
2546
|
+
description: "Adicionar uma citação",
|
|
2547
|
+
keywords: ["quote", "blockquote", "citation", "citação", "citacao", "aspas"],
|
|
2548
|
+
},
|
|
2549
|
+
code: {
|
|
2550
|
+
title: "Bloco de código",
|
|
2551
|
+
description: "Adicionar um bloco de código",
|
|
2552
|
+
keywords: ["code", "codeblock", "pre", "programming", "código", "codigo", "programação"],
|
|
2553
|
+
},
|
|
2554
|
+
image: {
|
|
2555
|
+
title: "Imagem",
|
|
2556
|
+
description: "Inserir uma imagem",
|
|
2557
|
+
keywords: ["image", "photo", "picture", "img", "imagem", "foto"],
|
|
2558
|
+
},
|
|
2559
|
+
horizontalRule: {
|
|
2560
|
+
title: "Linha horizontal",
|
|
2561
|
+
description: "Adicionar uma linha divisória",
|
|
2562
|
+
keywords: ["hr", "horizontal", "rule", "line", "separator", "linha", "divisor", "separador"],
|
|
2563
|
+
},
|
|
2564
|
+
table: {
|
|
2565
|
+
title: "Tabela",
|
|
2566
|
+
description: "Inserir uma tabela",
|
|
2567
|
+
keywords: [
|
|
2568
|
+
"table",
|
|
2569
|
+
"grid",
|
|
2570
|
+
"data",
|
|
2571
|
+
"rows",
|
|
2572
|
+
"columns",
|
|
2573
|
+
"tabela",
|
|
2574
|
+
"grade",
|
|
2575
|
+
"dados",
|
|
2576
|
+
"linhas",
|
|
2577
|
+
"colunas",
|
|
2578
|
+
],
|
|
2579
|
+
},
|
|
2580
|
+
tableOfContents: {
|
|
2581
|
+
title: "Sumário",
|
|
2582
|
+
description: "Inserir um sumário",
|
|
2583
|
+
keywords: [
|
|
2584
|
+
"toc",
|
|
2585
|
+
"table",
|
|
2586
|
+
"contents",
|
|
2587
|
+
"summary",
|
|
2588
|
+
"index",
|
|
2589
|
+
"headings",
|
|
2590
|
+
"outline",
|
|
2591
|
+
"sumário",
|
|
2592
|
+
"sumario",
|
|
2593
|
+
"índice",
|
|
2594
|
+
"indice",
|
|
2595
|
+
"títulos",
|
|
2596
|
+
],
|
|
2597
|
+
},
|
|
2598
|
+
filterPlaceholder: "Filtrar...",
|
|
2599
|
+
},
|
|
2600
|
+
table: {
|
|
2601
|
+
addRowBefore: "Inserir linha acima",
|
|
2602
|
+
addRowAfter: "Inserir linha abaixo",
|
|
2603
|
+
deleteRow: "Excluir linha",
|
|
2604
|
+
addColumnBefore: "Inserir coluna à esquerda",
|
|
2605
|
+
addColumnAfter: "Inserir coluna à direita",
|
|
2606
|
+
deleteColumn: "Excluir coluna",
|
|
2607
|
+
deleteTable: "Excluir tabela",
|
|
2608
|
+
toggleHeaderRow: "Alternar linha de cabeçalho",
|
|
2609
|
+
toggleHeaderColumn: "Alternar coluna de cabeçalho",
|
|
2610
|
+
mergeCells: "Mesclar células",
|
|
2611
|
+
splitCell: "Dividir célula",
|
|
2612
|
+
},
|
|
2613
|
+
imageUpload: {
|
|
2614
|
+
selectImage: "Selecionar imagem",
|
|
2615
|
+
loadError: "Erro ao carregar a imagem",
|
|
2616
|
+
uploadingImage: "Enviando imagem...",
|
|
2617
|
+
uploadProgress: "Progresso do envio",
|
|
2618
|
+
uploadError: "Erro no envio",
|
|
2619
|
+
uploadSuccess: "Envio concluído",
|
|
2620
|
+
imageTooLarge: "Imagem muito grande",
|
|
2621
|
+
invalidFileType: "Tipo de arquivo inválido",
|
|
2622
|
+
dragDropText: "Arraste e solte imagens aqui",
|
|
2623
|
+
changeImage: "Trocar imagem",
|
|
2624
|
+
downloadImage: "Baixar imagem",
|
|
2625
|
+
deleteImage: "Excluir imagem",
|
|
2626
|
+
resizeSmall: "Pequena",
|
|
2627
|
+
resizeMedium: "Média",
|
|
2628
|
+
resizeLarge: "Grande",
|
|
2629
|
+
resizeOriginal: "Original",
|
|
2630
|
+
alignLeft: "Alinhar à esquerda",
|
|
2631
|
+
alignCenter: "Centralizar",
|
|
2632
|
+
alignRight: "Alinhar à direita",
|
|
2633
|
+
resizing: "Redimensionando...",
|
|
2634
|
+
compressing: "Comprimindo...",
|
|
2635
|
+
compressionError: "Erro ao comprimir a imagem",
|
|
2636
|
+
validating: "Validando arquivo...",
|
|
2637
|
+
uploadingToServer: "Enviando para o servidor...",
|
|
2638
|
+
replacingImage: "Substituindo imagem...",
|
|
2639
|
+
insertingImage: "Inserindo no editor...",
|
|
2640
|
+
noFileSelected: "Nenhum arquivo de imagem selecionado",
|
|
2641
|
+
selectionCancelled: "Seleção cancelada",
|
|
2642
|
+
},
|
|
2643
|
+
editor: {
|
|
2644
|
+
placeholder: "Comece a escrever...",
|
|
2645
|
+
character: "caractere",
|
|
2646
|
+
characterPlural: "caracteres",
|
|
2647
|
+
word: "palavra",
|
|
2648
|
+
wordPlural: "palavras",
|
|
2649
|
+
linkPrompt: "Digite a URL do link",
|
|
2650
|
+
linkUrlPrompt: "Digite a URL",
|
|
2651
|
+
confirmDelete: "Tem certeza de que deseja excluir?",
|
|
2652
|
+
toggleEdit: "Mudar para o modo de edição",
|
|
2653
|
+
viewMode: "Mudar para o modo de leitura",
|
|
2654
|
+
blockAdd: "Clique para adicionar um bloco",
|
|
2655
|
+
blockDrag: "Arraste para mover este bloco",
|
|
2656
|
+
tableOfContents: "Sumário",
|
|
2657
|
+
},
|
|
2658
|
+
common: {
|
|
2659
|
+
cancel: "Cancelar",
|
|
2660
|
+
confirm: "Confirmar",
|
|
2661
|
+
apply: "Aplicar",
|
|
2662
|
+
delete: "Excluir",
|
|
2663
|
+
save: "Salvar",
|
|
2664
|
+
close: "Fechar",
|
|
2665
|
+
loading: "Carregando",
|
|
2666
|
+
error: "Erro",
|
|
2667
|
+
success: "Sucesso",
|
|
2668
|
+
},
|
|
2669
|
+
export: {
|
|
2670
|
+
export: "Exportar",
|
|
2671
|
+
html: "HTML",
|
|
2672
|
+
markdown: "Markdown",
|
|
2673
|
+
text: "Texto simples",
|
|
2674
|
+
copyHtml: "Copiar como HTML",
|
|
2675
|
+
copyMarkdown: "Copiar como Markdown",
|
|
2676
|
+
copyText: "Copiar como texto simples",
|
|
2677
|
+
downloadHtml: "Baixar .html",
|
|
2678
|
+
downloadMarkdown: "Baixar .md",
|
|
2679
|
+
downloadText: "Baixar .txt",
|
|
2680
|
+
copiedSuccess: "Copiado para a área de transferência!",
|
|
2681
|
+
},
|
|
2682
|
+
};
|
|
2683
|
+
|
|
2684
|
+
const SPANISH_TRANSLATIONS = {
|
|
2685
|
+
toolbar: {
|
|
2686
|
+
bold: "Negrita\nCtrl+B",
|
|
2687
|
+
italic: "Cursiva\nCtrl+I",
|
|
2688
|
+
underline: "Subrayado\nCtrl+U",
|
|
2689
|
+
strike: "Tachado\nCtrl+Shift+X",
|
|
2690
|
+
code: "Código en línea\nCtrl+E",
|
|
2691
|
+
codeBlock: "Bloque de código",
|
|
2692
|
+
superscript: "Superíndice",
|
|
2693
|
+
subscript: "Subíndice",
|
|
2694
|
+
highlight: "Resaltar",
|
|
2695
|
+
highlightPicker: "Color de resaltado",
|
|
2696
|
+
heading1: "Título 1",
|
|
2697
|
+
heading2: "Título 2",
|
|
2698
|
+
heading3: "Título 3",
|
|
2699
|
+
bulletList: "Lista con viñetas",
|
|
2700
|
+
orderedList: "Lista numerada",
|
|
2701
|
+
blockquote: "Cita",
|
|
2702
|
+
alignLeft: "Alinear a la izquierda",
|
|
2703
|
+
alignCenter: "Centrar",
|
|
2704
|
+
alignRight: "Alinear a la derecha",
|
|
2705
|
+
alignJustify: "Justificar",
|
|
2706
|
+
link: "Insertar enlace",
|
|
2707
|
+
image: "Insertar imagen",
|
|
2708
|
+
horizontalRule: "Línea horizontal",
|
|
2709
|
+
table: "Insertar tabla",
|
|
2710
|
+
undo: "Deshacer\nCtrl+Z",
|
|
2711
|
+
redo: "Rehacer\nCtrl+Shift+Z",
|
|
2712
|
+
clear: "Limpiar",
|
|
2713
|
+
textColor: "Color del texto",
|
|
2714
|
+
customColor: "Color personalizado",
|
|
2715
|
+
presets: "Predefinidos",
|
|
2716
|
+
},
|
|
2717
|
+
bubbleMenu: {
|
|
2718
|
+
bold: "Negrita\nCtrl+B",
|
|
2719
|
+
italic: "Cursiva\nCtrl+I",
|
|
2720
|
+
underline: "Subrayado\nCtrl+U",
|
|
2721
|
+
strike: "Tachado\nCtrl+Shift+X",
|
|
2722
|
+
code: "Código\nCtrl+E",
|
|
2723
|
+
superscript: "Superíndice",
|
|
2724
|
+
subscript: "Subíndice",
|
|
2725
|
+
highlight: "Resaltar",
|
|
2726
|
+
highlightPicker: "Color de resaltado",
|
|
2727
|
+
textColor: "Color del texto",
|
|
2728
|
+
link: "Enlace",
|
|
2729
|
+
addLink: "Insertar enlace",
|
|
2730
|
+
editLink: "Editar enlace",
|
|
2731
|
+
removeLink: "Quitar enlace",
|
|
2732
|
+
linkUrl: "URL del enlace",
|
|
2733
|
+
linkText: "Texto del enlace",
|
|
2734
|
+
openLink: "Abrir enlace",
|
|
2735
|
+
customColor: "Color personalizado",
|
|
2736
|
+
presets: "Predefinidos",
|
|
2737
|
+
},
|
|
2738
|
+
slashCommands: {
|
|
2739
|
+
heading1: {
|
|
2740
|
+
title: "Título 1",
|
|
2741
|
+
description: "Título de sección grande",
|
|
2742
|
+
keywords: ["heading", "h1", "title", "1", "header", "título", "titulo", "encabezado"],
|
|
2743
|
+
},
|
|
2744
|
+
heading2: {
|
|
2745
|
+
title: "Título 2",
|
|
2746
|
+
description: "Título de sección mediano",
|
|
2747
|
+
keywords: ["heading", "h2", "title", "2", "header", "título", "titulo", "subtítulo"],
|
|
2748
|
+
},
|
|
2749
|
+
heading3: {
|
|
2750
|
+
title: "Título 3",
|
|
2751
|
+
description: "Título de sección pequeño",
|
|
2752
|
+
keywords: ["heading", "h3", "title", "3", "header", "título", "titulo", "subtítulo"],
|
|
2753
|
+
},
|
|
2754
|
+
bulletList: {
|
|
2755
|
+
title: "Lista con viñetas",
|
|
2756
|
+
description: "Crear una lista con viñetas",
|
|
2757
|
+
keywords: ["bullet", "list", "ul", "unordered", "lista", "viñetas", "puntos"],
|
|
2758
|
+
},
|
|
2759
|
+
orderedList: {
|
|
2760
|
+
title: "Lista numerada",
|
|
2761
|
+
description: "Crear una lista numerada",
|
|
2762
|
+
keywords: ["ordered", "list", "ol", "numbered", "lista", "numerada", "ordenada"],
|
|
2763
|
+
},
|
|
2764
|
+
blockquote: {
|
|
2765
|
+
title: "Cita",
|
|
2766
|
+
description: "Añadir una cita",
|
|
2767
|
+
keywords: ["quote", "blockquote", "citation", "cita", "citar", "comillas"],
|
|
2768
|
+
},
|
|
2769
|
+
code: {
|
|
2770
|
+
title: "Bloque de código",
|
|
2771
|
+
description: "Añadir un bloque de código",
|
|
2772
|
+
keywords: ["code", "codeblock", "pre", "programming", "código", "codigo", "programación"],
|
|
2773
|
+
},
|
|
2774
|
+
image: {
|
|
2775
|
+
title: "Imagen",
|
|
2776
|
+
description: "Insertar una imagen",
|
|
2777
|
+
keywords: ["image", "photo", "picture", "img", "imagen", "foto"],
|
|
2778
|
+
},
|
|
2779
|
+
horizontalRule: {
|
|
2780
|
+
title: "Línea horizontal",
|
|
2781
|
+
description: "Añadir una línea divisoria",
|
|
2782
|
+
keywords: [
|
|
2783
|
+
"hr",
|
|
2784
|
+
"horizontal",
|
|
2785
|
+
"rule",
|
|
2786
|
+
"line",
|
|
2787
|
+
"separator",
|
|
2788
|
+
"línea",
|
|
2789
|
+
"linea",
|
|
2790
|
+
"divisor",
|
|
2791
|
+
"separador",
|
|
2792
|
+
],
|
|
2793
|
+
},
|
|
2794
|
+
table: {
|
|
2795
|
+
title: "Tabla",
|
|
2796
|
+
description: "Insertar una tabla",
|
|
2797
|
+
keywords: [
|
|
2798
|
+
"table",
|
|
2799
|
+
"grid",
|
|
2800
|
+
"data",
|
|
2801
|
+
"rows",
|
|
2802
|
+
"columns",
|
|
2803
|
+
"tabla",
|
|
2804
|
+
"cuadrícula",
|
|
2805
|
+
"datos",
|
|
2806
|
+
"filas",
|
|
2807
|
+
"columnas",
|
|
2808
|
+
],
|
|
2809
|
+
},
|
|
2810
|
+
tableOfContents: {
|
|
2811
|
+
title: "Índice",
|
|
2812
|
+
description: "Insertar un índice",
|
|
2813
|
+
keywords: [
|
|
2814
|
+
"toc",
|
|
2815
|
+
"table",
|
|
2816
|
+
"contents",
|
|
2817
|
+
"summary",
|
|
2818
|
+
"index",
|
|
2819
|
+
"headings",
|
|
2820
|
+
"outline",
|
|
2821
|
+
"índice",
|
|
2822
|
+
"indice",
|
|
2823
|
+
"contenido",
|
|
2824
|
+
"sumario",
|
|
2825
|
+
"títulos",
|
|
2826
|
+
],
|
|
2827
|
+
},
|
|
2828
|
+
filterPlaceholder: "Filtrar...",
|
|
2829
|
+
},
|
|
2830
|
+
table: {
|
|
2831
|
+
addRowBefore: "Insertar fila arriba",
|
|
2832
|
+
addRowAfter: "Insertar fila abajo",
|
|
2833
|
+
deleteRow: "Eliminar fila",
|
|
2834
|
+
addColumnBefore: "Insertar columna a la izquierda",
|
|
2835
|
+
addColumnAfter: "Insertar columna a la derecha",
|
|
2836
|
+
deleteColumn: "Eliminar columna",
|
|
2837
|
+
deleteTable: "Eliminar tabla",
|
|
2838
|
+
toggleHeaderRow: "Alternar fila de encabezado",
|
|
2839
|
+
toggleHeaderColumn: "Alternar columna de encabezado",
|
|
2840
|
+
mergeCells: "Combinar celdas",
|
|
2841
|
+
splitCell: "Dividir celda",
|
|
2842
|
+
},
|
|
2843
|
+
imageUpload: {
|
|
2844
|
+
selectImage: "Seleccionar imagen",
|
|
2845
|
+
loadError: "Error al cargar la imagen",
|
|
2846
|
+
uploadingImage: "Subiendo imagen...",
|
|
2847
|
+
uploadProgress: "Progreso de la subida",
|
|
2848
|
+
uploadError: "Error al subir",
|
|
2849
|
+
uploadSuccess: "Subida completada",
|
|
2850
|
+
imageTooLarge: "Imagen demasiado grande",
|
|
2851
|
+
invalidFileType: "Tipo de archivo no válido",
|
|
2852
|
+
dragDropText: "Arrastra y suelta imágenes aquí",
|
|
2853
|
+
changeImage: "Cambiar imagen",
|
|
2854
|
+
downloadImage: "Descargar imagen",
|
|
2855
|
+
deleteImage: "Eliminar imagen",
|
|
2856
|
+
resizeSmall: "Pequeña",
|
|
2857
|
+
resizeMedium: "Mediana",
|
|
2858
|
+
resizeLarge: "Grande",
|
|
2859
|
+
resizeOriginal: "Original",
|
|
2860
|
+
alignLeft: "Alinear a la izquierda",
|
|
2861
|
+
alignCenter: "Centrar",
|
|
2862
|
+
alignRight: "Alinear a la derecha",
|
|
2863
|
+
resizing: "Redimensionando...",
|
|
2864
|
+
compressing: "Comprimiendo...",
|
|
2865
|
+
compressionError: "Error al comprimir la imagen",
|
|
2866
|
+
validating: "Validando archivo...",
|
|
2867
|
+
uploadingToServer: "Subiendo al servidor...",
|
|
2868
|
+
replacingImage: "Reemplazando imagen...",
|
|
2869
|
+
insertingImage: "Insertando en el editor...",
|
|
2870
|
+
noFileSelected: "Ningún archivo de imagen seleccionado",
|
|
2871
|
+
selectionCancelled: "Selección cancelada",
|
|
2872
|
+
},
|
|
2873
|
+
editor: {
|
|
2874
|
+
placeholder: "Empieza a escribir...",
|
|
2875
|
+
character: "carácter",
|
|
2876
|
+
characterPlural: "caracteres",
|
|
2877
|
+
word: "palabra",
|
|
2878
|
+
wordPlural: "palabras",
|
|
2879
|
+
linkPrompt: "Introduce la URL del enlace",
|
|
2880
|
+
linkUrlPrompt: "Introduce la URL",
|
|
2881
|
+
confirmDelete: "¿Seguro que quieres eliminar esto?",
|
|
2882
|
+
toggleEdit: "Cambiar al modo de edición",
|
|
2883
|
+
viewMode: "Cambiar al modo de lectura",
|
|
2884
|
+
blockAdd: "Haz clic para añadir un bloque",
|
|
2885
|
+
blockDrag: "Arrastra para mover este bloque",
|
|
2886
|
+
tableOfContents: "Índice",
|
|
2887
|
+
},
|
|
2888
|
+
common: {
|
|
2889
|
+
cancel: "Cancelar",
|
|
2890
|
+
confirm: "Confirmar",
|
|
2891
|
+
apply: "Aplicar",
|
|
2892
|
+
delete: "Eliminar",
|
|
2893
|
+
save: "Guardar",
|
|
2894
|
+
close: "Cerrar",
|
|
2895
|
+
loading: "Cargando",
|
|
2896
|
+
error: "Error",
|
|
2897
|
+
success: "Éxito",
|
|
2898
|
+
},
|
|
2899
|
+
export: {
|
|
2900
|
+
export: "Exportar",
|
|
2901
|
+
html: "HTML",
|
|
2902
|
+
markdown: "Markdown",
|
|
2903
|
+
text: "Texto sin formato",
|
|
2904
|
+
copyHtml: "Copiar como HTML",
|
|
2905
|
+
copyMarkdown: "Copiar como Markdown",
|
|
2906
|
+
copyText: "Copiar como texto sin formato",
|
|
2907
|
+
downloadHtml: "Descargar .html",
|
|
2908
|
+
downloadMarkdown: "Descargar .md",
|
|
2909
|
+
downloadText: "Descargar .txt",
|
|
2910
|
+
copiedSuccess: "¡Copiado al portapapeles!",
|
|
2911
|
+
},
|
|
2912
|
+
};
|
|
2913
|
+
|
|
2351
2914
|
class AteI18nService {
|
|
2352
2915
|
constructor() {
|
|
2353
2916
|
this._currentLocale = signal("en");
|
|
@@ -2355,12 +2918,14 @@ class AteI18nService {
|
|
|
2355
2918
|
en: ENGLISH_TRANSLATIONS,
|
|
2356
2919
|
fr: FRENCH_TRANSLATIONS,
|
|
2357
2920
|
de: GERMAN_TRANSLATIONS,
|
|
2921
|
+
pt: PORTUGUESE_TRANSLATIONS,
|
|
2922
|
+
es: SPANISH_TRANSLATIONS,
|
|
2358
2923
|
});
|
|
2359
2924
|
// Public signals
|
|
2360
2925
|
this.currentLocale = this._currentLocale.asReadonly();
|
|
2361
2926
|
/** All loaded translations (useful for dynamic key access) */
|
|
2362
2927
|
this.allTranslations = this._translations.asReadonly();
|
|
2363
|
-
this.translations = computed(() => this.
|
|
2928
|
+
this.translations = computed(() => this.getTranslations(this._currentLocale()) ?? this._translations().en);
|
|
2364
2929
|
// Fast translation methods
|
|
2365
2930
|
this.t = computed(() => this.translations());
|
|
2366
2931
|
this.toolbar = computed(() => this.translations().toolbar);
|
|
@@ -2395,14 +2960,20 @@ class AteI18nService {
|
|
|
2395
2960
|
};
|
|
2396
2961
|
});
|
|
2397
2962
|
}
|
|
2398
|
-
|
|
2399
|
-
const
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2963
|
+
getTranslations(locale) {
|
|
2964
|
+
const resolved = this.resolveLocale(locale);
|
|
2965
|
+
return resolved ? this._translations()[resolved] : undefined;
|
|
2966
|
+
}
|
|
2967
|
+
resolveLocale(locale) {
|
|
2968
|
+
const all = this._translations();
|
|
2969
|
+
if (all[locale]) {
|
|
2970
|
+
return locale;
|
|
2405
2971
|
}
|
|
2972
|
+
const language = locale.toLowerCase().split(/[-_]/)[0];
|
|
2973
|
+
return all[language] ? language : undefined;
|
|
2974
|
+
}
|
|
2975
|
+
detectBrowserLanguage() {
|
|
2976
|
+
this._currentLocale.set(this.resolveLocale(navigator.language) ?? "en");
|
|
2406
2977
|
}
|
|
2407
2978
|
// Utility methods for components
|
|
2408
2979
|
getToolbarTitle(key) {
|
|
@@ -3037,6 +3608,14 @@ const AteTiptapStateExtension = Extension.create({
|
|
|
3037
3608
|
|
|
3038
3609
|
// Pre-calculate platform once to avoid repeated checks
|
|
3039
3610
|
const IS_MAC = typeof window !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
3611
|
+
const DURATION = [100, 100];
|
|
3612
|
+
// After a tooltip closes, the next one still opens at once if hovered within this gap
|
|
3613
|
+
const WARM_GAP = 300;
|
|
3614
|
+
// Shared by every tooltip: the first one waits for its delay, the next ones open at once,
|
|
3615
|
+
// without animation, as long as the pointer moves from one control to the next.
|
|
3616
|
+
let openTooltip = null;
|
|
3617
|
+
let warm = false;
|
|
3618
|
+
let coolTimeout;
|
|
3040
3619
|
class AteTooltipDirective {
|
|
3041
3620
|
constructor() {
|
|
3042
3621
|
this.el = inject(ElementRef);
|
|
@@ -3128,7 +3707,7 @@ class AteTooltipDirective {
|
|
|
3128
3707
|
allowHTML,
|
|
3129
3708
|
placement,
|
|
3130
3709
|
delay,
|
|
3131
|
-
duration:
|
|
3710
|
+
duration: DURATION,
|
|
3132
3711
|
offset: [0, 6],
|
|
3133
3712
|
theme: "ate-tooltip",
|
|
3134
3713
|
touch: ["hold", 500],
|
|
@@ -3137,6 +3716,30 @@ class AteTooltipDirective {
|
|
|
3137
3716
|
aria: {
|
|
3138
3717
|
content: "describedby",
|
|
3139
3718
|
},
|
|
3719
|
+
onTrigger: (instance, event) => {
|
|
3720
|
+
const base = this.delay();
|
|
3721
|
+
const instant = warm && event.type === "mouseenter";
|
|
3722
|
+
instance.setProps({
|
|
3723
|
+
delay: instant ? [0, Array.isArray(base) ? base[1] : base] : base,
|
|
3724
|
+
duration: instant ? [0, DURATION[1]] : DURATION,
|
|
3725
|
+
});
|
|
3726
|
+
},
|
|
3727
|
+
onShow: instance => {
|
|
3728
|
+
// Only one tooltip at a time: the previous one goes away at once
|
|
3729
|
+
if (openTooltip && openTooltip !== instance) {
|
|
3730
|
+
openTooltip.unmount();
|
|
3731
|
+
}
|
|
3732
|
+
openTooltip = instance;
|
|
3733
|
+
warm = true;
|
|
3734
|
+
clearTimeout(coolTimeout);
|
|
3735
|
+
},
|
|
3736
|
+
onHidden: instance => {
|
|
3737
|
+
if (openTooltip !== instance) {
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
openTooltip = null;
|
|
3741
|
+
coolTimeout = setTimeout(() => (warm = false), WARM_GAP);
|
|
3742
|
+
},
|
|
3140
3743
|
popperOptions: {
|
|
3141
3744
|
modifiers: [
|
|
3142
3745
|
{
|
|
@@ -3152,6 +3755,9 @@ class AteTooltipDirective {
|
|
|
3152
3755
|
}
|
|
3153
3756
|
destroyTippy() {
|
|
3154
3757
|
if (this.tippyInstance) {
|
|
3758
|
+
if (openTooltip === this.tippyInstance) {
|
|
3759
|
+
openTooltip = null;
|
|
3760
|
+
}
|
|
3155
3761
|
this.tippyInstance.destroy();
|
|
3156
3762
|
this.tippyInstance = null;
|
|
3157
3763
|
}
|
|
@@ -3475,12 +4081,13 @@ class AteImageService {
|
|
|
3475
4081
|
const maxSize = options?.maxSize || 10 * 1024 * 1024;
|
|
3476
4082
|
const allowedTypes = options?.allowedTypes || [];
|
|
3477
4083
|
if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) {
|
|
3478
|
-
return { valid: false, error: this.t().invalidFileType };
|
|
4084
|
+
return { valid: false, error: this.t().invalidFileType, reason: "invalid-type" };
|
|
3479
4085
|
}
|
|
3480
4086
|
if (file.size > maxSize) {
|
|
3481
4087
|
return {
|
|
3482
4088
|
valid: false,
|
|
3483
4089
|
error: `${this.t().imageTooLarge} (max ${Math.round(maxSize / 1024 / 1024)}MB)`,
|
|
4090
|
+
reason: "too-large",
|
|
3484
4091
|
};
|
|
3485
4092
|
}
|
|
3486
4093
|
return { valid: true };
|
|
@@ -3536,7 +4143,7 @@ class AteImageService {
|
|
|
3536
4143
|
});
|
|
3537
4144
|
}
|
|
3538
4145
|
/** Core upload logic with progress tracking */
|
|
3539
|
-
async uploadImageWithProgress(editor, file, insertionStrategy, actionMessage, options) {
|
|
4146
|
+
async uploadImageWithProgress(editor, file, insertionStrategy, actionMessage, options, source) {
|
|
3540
4147
|
try {
|
|
3541
4148
|
this.currentEditor = editor;
|
|
3542
4149
|
this.isUploading.set(true);
|
|
@@ -3565,6 +4172,11 @@ class AteImageService {
|
|
|
3565
4172
|
catch (error) {
|
|
3566
4173
|
this.resetUploadState();
|
|
3567
4174
|
console.error(this.t().uploadError, error);
|
|
4175
|
+
this.onImageRejectedCallback?.({
|
|
4176
|
+
reason: error instanceof AteImageValidationError ? error.reason : "upload-failed",
|
|
4177
|
+
file,
|
|
4178
|
+
source,
|
|
4179
|
+
});
|
|
3568
4180
|
throw error;
|
|
3569
4181
|
}
|
|
3570
4182
|
}
|
|
@@ -3575,7 +4187,7 @@ class AteImageService {
|
|
|
3575
4187
|
allowedTypes: options?.allowedTypes,
|
|
3576
4188
|
});
|
|
3577
4189
|
if (!validation.valid) {
|
|
3578
|
-
throw new
|
|
4190
|
+
throw new AteImageValidationError(validation.reason ?? "invalid-type", validation.error ?? "");
|
|
3579
4191
|
}
|
|
3580
4192
|
onStep?.(30, this.t().compressing);
|
|
3581
4193
|
const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1200);
|
|
@@ -3631,7 +4243,7 @@ class AteImageService {
|
|
|
3631
4243
|
this.currentEditor = null;
|
|
3632
4244
|
}
|
|
3633
4245
|
/** Main entry point for file upload and insertion */
|
|
3634
|
-
async uploadAndInsertImage(editor, file, options) {
|
|
4246
|
+
async uploadAndInsertImage(editor, file, options, source = "api") {
|
|
3635
4247
|
return this.uploadImageWithProgress(editor, file, (ed, result) => {
|
|
3636
4248
|
this.insertImage(ed, {
|
|
3637
4249
|
src: result.src,
|
|
@@ -3640,7 +4252,7 @@ class AteImageService {
|
|
|
3640
4252
|
width: result.width,
|
|
3641
4253
|
height: result.height,
|
|
3642
4254
|
});
|
|
3643
|
-
}, this.t().insertingImage, options);
|
|
4255
|
+
}, this.t().insertingImage, options, source);
|
|
3644
4256
|
}
|
|
3645
4257
|
/** Trigger an editor transaction to force decoration update */
|
|
3646
4258
|
forceEditorUpdate() {
|
|
@@ -3666,7 +4278,7 @@ class AteImageService {
|
|
|
3666
4278
|
const file = e.target.files?.[0];
|
|
3667
4279
|
if (file && file.type.startsWith("image/")) {
|
|
3668
4280
|
try {
|
|
3669
|
-
await uploadMethod(editor, file, options);
|
|
4281
|
+
await uploadMethod(editor, file, options, "picker");
|
|
3670
4282
|
resolve();
|
|
3671
4283
|
}
|
|
3672
4284
|
catch (error) {
|
|
@@ -3697,7 +4309,7 @@ class AteImageService {
|
|
|
3697
4309
|
return this.selectFileAndProcess(editor, this.uploadAndReplaceImage.bind(this), options);
|
|
3698
4310
|
}
|
|
3699
4311
|
/** Internal helper used by replacement logic */
|
|
3700
|
-
async uploadAndReplaceImage(editor, file, options) {
|
|
4312
|
+
async uploadAndReplaceImage(editor, file, options, source = "api") {
|
|
3701
4313
|
// Store current position to ensure we can re-select the image even if selection blurs during upload
|
|
3702
4314
|
const wasActive = editor.isActive("resizableImage");
|
|
3703
4315
|
await this.uploadImageWithProgress(editor, file, (ed, result) => {
|
|
@@ -3727,7 +4339,7 @@ class AteImageService {
|
|
|
3727
4339
|
}
|
|
3728
4340
|
// After replacement, ensure the image is tracked in our signals
|
|
3729
4341
|
this.selectImage(ed);
|
|
3730
|
-
}, this.t().replacingImage, options);
|
|
4342
|
+
}, this.t().replacingImage, options, source);
|
|
3731
4343
|
}
|
|
3732
4344
|
/**
|
|
3733
4345
|
* Handle image drop event.
|
|
@@ -3749,7 +4361,7 @@ class AteImageService {
|
|
|
3749
4361
|
if (pos) {
|
|
3750
4362
|
editor.commands.setTextSelection(pos.pos);
|
|
3751
4363
|
}
|
|
3752
|
-
|
|
4364
|
+
this.uploadAndInsertImage(editor, file, options, "drop").catch(() => undefined);
|
|
3753
4365
|
return true;
|
|
3754
4366
|
}
|
|
3755
4367
|
/**
|
|
@@ -3765,7 +4377,7 @@ class AteImageService {
|
|
|
3765
4377
|
return false;
|
|
3766
4378
|
}
|
|
3767
4379
|
event.preventDefault();
|
|
3768
|
-
|
|
4380
|
+
this.uploadAndInsertImage(editor, imageFile, options, "paste").catch(() => undefined);
|
|
3769
4381
|
return true;
|
|
3770
4382
|
}
|
|
3771
4383
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
@@ -4448,6 +5060,9 @@ class AteEditorCommandsService {
|
|
|
4448
5060
|
set onImageUploaded(callback) {
|
|
4449
5061
|
this.imageService.onImageUploadedCallback = callback || undefined;
|
|
4450
5062
|
}
|
|
5063
|
+
set onImageRejected(callback) {
|
|
5064
|
+
this.imageService.onImageRejectedCallback = callback || undefined;
|
|
5065
|
+
}
|
|
4451
5066
|
set uploadHandler(handler) {
|
|
4452
5067
|
this.imageService.uploadHandler = handler;
|
|
4453
5068
|
}
|
|
@@ -4519,10 +5134,10 @@ class AteEditorCommandsService {
|
|
|
4519
5134
|
this.insertHorizontalRule(editor);
|
|
4520
5135
|
break;
|
|
4521
5136
|
case "insertImage":
|
|
4522
|
-
this.insertImage(editor, args[0]);
|
|
5137
|
+
this.insertImage(editor, args[0]).catch(() => undefined);
|
|
4523
5138
|
break;
|
|
4524
5139
|
case "uploadImage":
|
|
4525
|
-
this.uploadImage(editor, args[0], args[1]);
|
|
5140
|
+
this.uploadImage(editor, args[0], args[1]).catch(() => undefined);
|
|
4526
5141
|
break;
|
|
4527
5142
|
case "toggleHighlight":
|
|
4528
5143
|
this.toggleHighlight(editor, args[0]);
|
|
@@ -5634,6 +6249,7 @@ const ATE_DEFAULT_CONFIG = {
|
|
|
5634
6249
|
showTableMenu: true,
|
|
5635
6250
|
showCellMenu: true,
|
|
5636
6251
|
enableSlashCommands: true,
|
|
6252
|
+
enableBlockShortcuts: true,
|
|
5637
6253
|
blockControls: "none",
|
|
5638
6254
|
floatingToolbar: false,
|
|
5639
6255
|
toolbar: ATE_DEFAULT_TOOLBAR_CONFIG,
|
|
@@ -5645,6 +6261,7 @@ const ATE_DEFAULT_CONFIG = {
|
|
|
5645
6261
|
slashCommands: {},
|
|
5646
6262
|
tiptapExtensions: [],
|
|
5647
6263
|
tiptapOptions: {},
|
|
6264
|
+
starterKitOptions: {},
|
|
5648
6265
|
stateCalculators: [],
|
|
5649
6266
|
angularNodes: [],
|
|
5650
6267
|
};
|
|
@@ -7709,6 +8326,7 @@ function createDefaultSlashCommands(i18n, commands, imageOptions) {
|
|
|
7709
8326
|
quality: imageOptions?.quality,
|
|
7710
8327
|
maxWidth: imageOptions?.maxWidth,
|
|
7711
8328
|
maxHeight: imageOptions?.maxHeight,
|
|
8329
|
+
maxSize: imageOptions?.maxSize,
|
|
7712
8330
|
allowedTypes: imageOptions?.allowedTypes,
|
|
7713
8331
|
}),
|
|
7714
8332
|
},
|
|
@@ -8872,6 +9490,85 @@ function shallowObjectEqual(a, b) {
|
|
|
8872
9490
|
a[key] === b[key]));
|
|
8873
9491
|
}
|
|
8874
9492
|
|
|
9493
|
+
/**
|
|
9494
|
+
* Maps the runtime `.name` of each extension bundled in `@tiptap/starter-kit`
|
|
9495
|
+
* to its corresponding option key in `StarterKitOptions`.
|
|
9496
|
+
*/
|
|
9497
|
+
const STARTER_KIT_NAME_TO_OPTION = {
|
|
9498
|
+
blockquote: "blockquote",
|
|
9499
|
+
bold: "bold",
|
|
9500
|
+
bulletList: "bulletList",
|
|
9501
|
+
code: "code",
|
|
9502
|
+
codeBlock: "codeBlock",
|
|
9503
|
+
doc: "document",
|
|
9504
|
+
dropCursor: "dropcursor",
|
|
9505
|
+
gapCursor: "gapcursor",
|
|
9506
|
+
hardBreak: "hardBreak",
|
|
9507
|
+
heading: "heading",
|
|
9508
|
+
undoRedo: "undoRedo",
|
|
9509
|
+
horizontalRule: "horizontalRule",
|
|
9510
|
+
italic: "italic",
|
|
9511
|
+
listItem: "listItem",
|
|
9512
|
+
listKeymap: "listKeymap",
|
|
9513
|
+
link: "link",
|
|
9514
|
+
orderedList: "orderedList",
|
|
9515
|
+
paragraph: "paragraph",
|
|
9516
|
+
strike: "strike",
|
|
9517
|
+
text: "text",
|
|
9518
|
+
underline: "underline",
|
|
9519
|
+
trailingNode: "trailingNode",
|
|
9520
|
+
};
|
|
9521
|
+
/**
|
|
9522
|
+
* Describes which parts of Angular Tiptap Editor's UI or state calculators
|
|
9523
|
+
* depend on a given built-in or StarterKit extension name.
|
|
9524
|
+
*/
|
|
9525
|
+
const ATE_BUILTIN_UI_DEPENDENCIES = {
|
|
9526
|
+
blockquote: "toolbar/slash menu blockquote buttons, AteStructureCalculator",
|
|
9527
|
+
bold: "toolbar/bubble menu bold buttons, AteMarksCalculator",
|
|
9528
|
+
bulletList: "toolbar/slash menu bullet list buttons, AteStructureCalculator",
|
|
9529
|
+
code: "toolbar/bubble menu inline code buttons, AteMarksCalculator",
|
|
9530
|
+
codeBlock: "toolbar/slash menu code block buttons, AteStructureCalculator",
|
|
9531
|
+
doc: "top-level ProseMirror document schema",
|
|
9532
|
+
dropCursor: "drag-and-drop cursor indicator",
|
|
9533
|
+
gapCursor: "gap cursor navigation around leaf block nodes",
|
|
9534
|
+
hardBreak: "Shift+Enter line break shortcut",
|
|
9535
|
+
heading: "toolbar/bubble menu/slash menu heading controls, table of contents, AteStructureCalculator",
|
|
9536
|
+
undoRedo: "toolbar undo/redo buttons, AteStructureCalculator",
|
|
9537
|
+
horizontalRule: "toolbar/slash menu horizontal rule buttons",
|
|
9538
|
+
italic: "toolbar/bubble menu italic buttons, AteMarksCalculator",
|
|
9539
|
+
listItem: "bullet/ordered list items, block shortcuts",
|
|
9540
|
+
listKeymap: "list backspace/delete keyboard navigation",
|
|
9541
|
+
link: "toolbar/bubble menu link editor, Mod+K shortcut, AteMarksCalculator",
|
|
9542
|
+
orderedList: "toolbar/slash menu ordered list buttons, AteStructureCalculator",
|
|
9543
|
+
paragraph: "default text block node, AteStructureCalculator",
|
|
9544
|
+
strike: "toolbar/bubble menu strikethrough buttons, AteMarksCalculator",
|
|
9545
|
+
text: "core inline text node",
|
|
9546
|
+
underline: "toolbar/bubble menu underline buttons, AteMarksCalculator",
|
|
9547
|
+
trailingNode: "automatic trailing paragraph after block nodes",
|
|
9548
|
+
textStyle: "color picker, AteMarksCalculator",
|
|
9549
|
+
color: "toolbar/bubble menu text color picker, AteMarksCalculator",
|
|
9550
|
+
placeholder: "empty editor placeholder decoration",
|
|
9551
|
+
superscript: "toolbar/bubble menu superscript buttons, AteMarksCalculator",
|
|
9552
|
+
subscript: "toolbar/bubble menu subscript buttons, AteMarksCalculator",
|
|
9553
|
+
textAlign: "toolbar/image bubble menu alignment buttons, AteStructureCalculator",
|
|
9554
|
+
ateLinkClickBehavior: "read-only and Ctrl+click link navigation",
|
|
9555
|
+
ateBlockShortcuts: "Mod+D and Mod+Shift+ArrowUp/Down block shortcuts",
|
|
9556
|
+
ateLinkShortcut: "Mod+K link editor shortcut",
|
|
9557
|
+
highlight: "toolbar/bubble menu highlight picker, AteMarksCalculator",
|
|
9558
|
+
resizableImage: "image node view, image bubble menu, image upload/resize service, AteImageCalculator",
|
|
9559
|
+
atePastedImage: "pasted HTML image sanitization and base64 re-hosting",
|
|
9560
|
+
ateUploadProgress: "image upload progress overlay",
|
|
9561
|
+
tableExtension: "toolbar/slash menu table insertion, table/cell bubble menus, AteTableCalculator",
|
|
9562
|
+
tableOfContents: "slash menu table of contents node, AteTableOfContentsComponent",
|
|
9563
|
+
tiptapState: "reactive editor state engine (toolbar, bubble menus, footer)",
|
|
9564
|
+
blockControls: "block plus button and drag handle",
|
|
9565
|
+
officePaste: "Word/Excel paste normalization",
|
|
9566
|
+
characterCount: "footer character/word counters and maxCharacters limit",
|
|
9567
|
+
};
|
|
9568
|
+
function getExtensionName(ext) {
|
|
9569
|
+
return ext?.name;
|
|
9570
|
+
}
|
|
9571
|
+
|
|
8875
9572
|
function transformBooleanInput(val) {
|
|
8876
9573
|
if (val === undefined || val === null) {
|
|
8877
9574
|
return undefined;
|
|
@@ -8927,6 +9624,9 @@ class AngularTiptapEditorComponent {
|
|
|
8927
9624
|
this.enableSlashCommands = input(undefined, {
|
|
8928
9625
|
transform: transformBooleanInput,
|
|
8929
9626
|
});
|
|
9627
|
+
this.enableBlockShortcuts = input(undefined, {
|
|
9628
|
+
transform: transformBooleanInput,
|
|
9629
|
+
});
|
|
8930
9630
|
this.slashCommands = input(undefined);
|
|
8931
9631
|
this.customSlashCommands = input(undefined);
|
|
8932
9632
|
this.blockControls = input();
|
|
@@ -8943,6 +9643,7 @@ class AngularTiptapEditorComponent {
|
|
|
8943
9643
|
this.spellcheck = input(undefined, { transform: transformBooleanInput });
|
|
8944
9644
|
this.tiptapExtensions = input(undefined);
|
|
8945
9645
|
this.tiptapOptions = input(undefined);
|
|
9646
|
+
this.starterKitOptions = input(undefined);
|
|
8946
9647
|
// Nouveaux inputs pour les bubble menus
|
|
8947
9648
|
this.showBubbleMenu = input(undefined, {
|
|
8948
9649
|
transform: transformBooleanInput,
|
|
@@ -9002,6 +9703,8 @@ class AngularTiptapEditorComponent {
|
|
|
9002
9703
|
this.editorBlur = output();
|
|
9003
9704
|
this.editableChange = output();
|
|
9004
9705
|
this.imageUploaded = output();
|
|
9706
|
+
/** Emitted when an image file is rejected (disallowed type, too large or failed upload) */
|
|
9707
|
+
this.imageRejected = output();
|
|
9005
9708
|
/** Emitted when an image from pasted HTML is dropped (unreachable source or failed upload) */
|
|
9006
9709
|
this.pastedImageRejected = output();
|
|
9007
9710
|
// ViewChild with signal
|
|
@@ -9152,6 +9855,7 @@ class AngularTiptapEditorComponent {
|
|
|
9152
9855
|
// Behavior
|
|
9153
9856
|
this.finalAutofocus = computed(() => this.autofocus() ?? this.effectiveConfig().autofocus);
|
|
9154
9857
|
this.finalMaxCharacters = computed(() => this.maxCharacters() ?? this.effectiveConfig().maxCharacters);
|
|
9858
|
+
this.finalEnableBlockShortcuts = computed(() => this.enableBlockShortcuts() ?? this.effectiveConfig().enableBlockShortcuts ?? true);
|
|
9155
9859
|
this.finalBlockControls = computed(() => this.blockControls() ?? this.effectiveConfig().blockControls ?? "none");
|
|
9156
9860
|
this.finalShowCharacterCount = computed(() => this.showCharacterCount() ?? this.effectiveConfig().showCharacterCount ?? true);
|
|
9157
9861
|
this.finalShowWordCount = computed(() => this.showWordCount() ?? this.effectiveConfig().showWordCount ?? true);
|
|
@@ -9159,6 +9863,7 @@ class AngularTiptapEditorComponent {
|
|
|
9159
9863
|
// Extensions & Options
|
|
9160
9864
|
this.finalTiptapExtensions = computed(() => this.tiptapExtensions() ?? this.effectiveConfig().tiptapExtensions ?? [], { equal: shallowArrayEqual });
|
|
9161
9865
|
this.finalTiptapOptions = computed(() => this.tiptapOptions() ?? this.effectiveConfig().tiptapOptions ?? {}, { equal: shallowObjectEqual });
|
|
9866
|
+
this.finalStarterKitOptions = computed(() => this.starterKitOptions() ?? this.effectiveConfig().starterKitOptions ?? {}, { equal: shallowObjectEqual });
|
|
9162
9867
|
this.finalStateCalculators = computed(() => this.stateCalculators() ?? this.effectiveConfig().stateCalculators ?? []);
|
|
9163
9868
|
this.finalAngularNodesConfig = computed(() => this.effectiveConfig().angularNodes ?? [], {
|
|
9164
9869
|
equal: shallowArrayEqual,
|
|
@@ -9183,8 +9888,7 @@ class AngularTiptapEditorComponent {
|
|
|
9183
9888
|
this.currentTranslations = computed(() => {
|
|
9184
9889
|
const localeOverride = this.finalLocale();
|
|
9185
9890
|
if (localeOverride) {
|
|
9186
|
-
|
|
9187
|
-
return allTranslations[localeOverride] || this.i18nService.translations();
|
|
9891
|
+
return this.i18nService.getTranslations(localeOverride) ?? this.i18nService.translations();
|
|
9188
9892
|
}
|
|
9189
9893
|
return this.i18nService.translations();
|
|
9190
9894
|
});
|
|
@@ -9196,6 +9900,7 @@ class AngularTiptapEditorComponent {
|
|
|
9196
9900
|
// Access editor state via service
|
|
9197
9901
|
this.editorState = this.editorCommandsService.editorState;
|
|
9198
9902
|
this.editorRegistry = inject(AteEditorRegistry);
|
|
9903
|
+
this.warnedExtensionOverrides = new Set();
|
|
9199
9904
|
this.iconRegistry = inject(AteIconRegistry);
|
|
9200
9905
|
this._registeredId = signal(null);
|
|
9201
9906
|
this.registeredId = this._registeredId.asReadonly();
|
|
@@ -9281,6 +9986,7 @@ class AngularTiptapEditorComponent {
|
|
|
9281
9986
|
// Monitor technical dependencies
|
|
9282
9987
|
this.finalTiptapExtensions();
|
|
9283
9988
|
this.finalTiptapOptions();
|
|
9989
|
+
this.finalStarterKitOptions();
|
|
9284
9990
|
this.finalAngularNodesConfig();
|
|
9285
9991
|
this.finalBlockControls();
|
|
9286
9992
|
untracked(() => {
|
|
@@ -9298,6 +10004,9 @@ class AngularTiptapEditorComponent {
|
|
|
9298
10004
|
this.editorCommandsService.onImageUploaded = result => {
|
|
9299
10005
|
this.imageUploaded.emit(result);
|
|
9300
10006
|
};
|
|
10007
|
+
this.editorCommandsService.onImageRejected = rejection => {
|
|
10008
|
+
this.imageRejected.emit(rejection);
|
|
10009
|
+
};
|
|
9301
10010
|
}
|
|
9302
10011
|
ngAfterViewInit() {
|
|
9303
10012
|
// La vue est déjà complètement initialisée dans ngAfterViewInit
|
|
@@ -9319,15 +10028,46 @@ class AngularTiptapEditorComponent {
|
|
|
9319
10028
|
}
|
|
9320
10029
|
}
|
|
9321
10030
|
initEditor() {
|
|
9322
|
-
const
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
10031
|
+
const starterKitOptions = this.finalStarterKitOptions();
|
|
10032
|
+
const customExtensions = this.finalTiptapExtensions();
|
|
10033
|
+
const customNames = new Set(customExtensions.map(getExtensionName).filter((name) => !!name));
|
|
10034
|
+
const defaultLinkOptions = {
|
|
10035
|
+
openOnClick: false,
|
|
10036
|
+
HTMLAttributes: {
|
|
10037
|
+
class: "ate-link",
|
|
10038
|
+
},
|
|
10039
|
+
};
|
|
10040
|
+
const effectiveStarterKitOptions = {
|
|
10041
|
+
...starterKitOptions,
|
|
10042
|
+
link: starterKitOptions.link === false
|
|
10043
|
+
? false
|
|
10044
|
+
: {
|
|
10045
|
+
...defaultLinkOptions,
|
|
10046
|
+
...starterKitOptions.link,
|
|
9326
10047
|
HTMLAttributes: {
|
|
9327
|
-
|
|
10048
|
+
...defaultLinkOptions.HTMLAttributes,
|
|
10049
|
+
...starterKitOptions.link?.HTMLAttributes,
|
|
9328
10050
|
},
|
|
9329
10051
|
},
|
|
9330
|
-
|
|
10052
|
+
};
|
|
10053
|
+
const replacedNames = [];
|
|
10054
|
+
const ignoredStarterKitOptionKeys = [];
|
|
10055
|
+
for (const customName of customNames) {
|
|
10056
|
+
const optionKey = STARTER_KIT_NAME_TO_OPTION[customName];
|
|
10057
|
+
if (!optionKey) {
|
|
10058
|
+
continue;
|
|
10059
|
+
}
|
|
10060
|
+
const userStarterKitValue = starterKitOptions[optionKey];
|
|
10061
|
+
if (userStarterKitValue !== undefined && userStarterKitValue !== false) {
|
|
10062
|
+
ignoredStarterKitOptionKeys.push(optionKey);
|
|
10063
|
+
}
|
|
10064
|
+
if (userStarterKitValue !== false) {
|
|
10065
|
+
replacedNames.push(customName);
|
|
10066
|
+
}
|
|
10067
|
+
effectiveStarterKitOptions[optionKey] = false;
|
|
10068
|
+
}
|
|
10069
|
+
const extensions = [
|
|
10070
|
+
StarterKit.configure(effectiveStarterKitOptions),
|
|
9331
10071
|
TextStyle,
|
|
9332
10072
|
Color.configure({
|
|
9333
10073
|
types: ["textStyle"],
|
|
@@ -9341,6 +10081,9 @@ class AngularTiptapEditorComponent {
|
|
|
9341
10081
|
types: ["heading", "paragraph", "resizableImage"],
|
|
9342
10082
|
}),
|
|
9343
10083
|
AteLinkClickBehavior,
|
|
10084
|
+
AteBlockShortcuts.configure({
|
|
10085
|
+
enabled: () => this.finalEnableBlockShortcuts(),
|
|
10086
|
+
}),
|
|
9344
10087
|
AteLinkShortcut.configure({
|
|
9345
10088
|
canOpen: () => this.editorCommandsService.editorState().can.toggleLink,
|
|
9346
10089
|
open: editor => this.editorCommandsService.execute(editor, "toggleLink"),
|
|
@@ -9416,17 +10159,41 @@ class AngularTiptapEditorComponent {
|
|
|
9416
10159
|
console.error("[ATE] Failed to auto-register node view:", e);
|
|
9417
10160
|
}
|
|
9418
10161
|
});
|
|
9419
|
-
//
|
|
9420
|
-
const customExtensions = this.finalTiptapExtensions();
|
|
10162
|
+
// Custom extensions in tiptapExtensions take precedence over built-in extensions of the same name
|
|
9421
10163
|
if (customExtensions.length > 0) {
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
}
|
|
9429
|
-
extensions.push(...
|
|
10164
|
+
for (let i = extensions.length - 1; i >= 0; i--) {
|
|
10165
|
+
const name = getExtensionName(extensions[i]);
|
|
10166
|
+
if (name && customNames.has(name)) {
|
|
10167
|
+
replacedNames.push(name);
|
|
10168
|
+
extensions.splice(i, 1);
|
|
10169
|
+
}
|
|
10170
|
+
}
|
|
10171
|
+
extensions.push(...customExtensions);
|
|
10172
|
+
if (isDevMode()) {
|
|
10173
|
+
const newlyReplaced = replacedNames.filter(name => !this.warnedExtensionOverrides.has(`override:${name}`));
|
|
10174
|
+
const newlyIgnoredOptions = ignoredStarterKitOptionKeys.filter(key => !this.warnedExtensionOverrides.has(`conflict:${key}`));
|
|
10175
|
+
if (newlyReplaced.length > 0 || newlyIgnoredOptions.length > 0) {
|
|
10176
|
+
newlyReplaced.forEach(name => this.warnedExtensionOverrides.add(`override:${name}`));
|
|
10177
|
+
newlyIgnoredOptions.forEach(key => this.warnedExtensionOverrides.add(`conflict:${key}`));
|
|
10178
|
+
const parts = [];
|
|
10179
|
+
if (newlyReplaced.length > 0) {
|
|
10180
|
+
const details = newlyReplaced
|
|
10181
|
+
.map(name => {
|
|
10182
|
+
const deps = ATE_BUILTIN_UI_DEPENDENCIES[name];
|
|
10183
|
+
return deps ? `${name} (used by: ${deps})` : name;
|
|
10184
|
+
})
|
|
10185
|
+
.join("; ");
|
|
10186
|
+
parts.push(`Custom extension(s) in tiptapExtensions replaced built-in extension(s): ${details}.`);
|
|
10187
|
+
}
|
|
10188
|
+
if (newlyIgnoredOptions.length > 0) {
|
|
10189
|
+
const ignoredList = newlyIgnoredOptions
|
|
10190
|
+
.map(key => `starterKitOptions.${key}`)
|
|
10191
|
+
.join(", ");
|
|
10192
|
+
parts.push(`${ignoredList} was ignored because the custom extension in tiptapExtensions takes precedence.`);
|
|
10193
|
+
}
|
|
10194
|
+
console.warn(`[ATE] ${parts.join(" ")}`);
|
|
10195
|
+
}
|
|
10196
|
+
}
|
|
9430
10197
|
}
|
|
9431
10198
|
// Also allow any tiptap user options
|
|
9432
10199
|
const userOptions = this.finalTiptapOptions();
|
|
@@ -9645,7 +10412,7 @@ class AngularTiptapEditorComponent {
|
|
|
9645
10412
|
}
|
|
9646
10413
|
}
|
|
9647
10414
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9648
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, blockControls: { classPropertyName: "blockControls", publicName: "blockControls", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, showEditToggle: { classPropertyName: "showEditToggle", publicName: "showEditToggle", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange", imageUploaded: "imageUploaded", pastedImageRejected: "pastedImageRejected" }, host: { properties: { "class.fill-container": "finalFillContainer()", "class.floating-toolbar": "finalFloatingToolbar()", "class.is-readonly": "!finalEditable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "finalSeamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "finalSeamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-background": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-border-color": "finalSeamless() ? 'transparent' : null", "class.dark": "config().theme === 'dark'", "class.ate-blocks-inside": "finalBlockControls() === 'inside'", "class.ate-blocks-outside": "finalBlockControls() === 'outside'", "attr.data-theme": "config().theme" } }, providers: [
|
|
10415
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, enableBlockShortcuts: { classPropertyName: "enableBlockShortcuts", publicName: "enableBlockShortcuts", isSignal: true, isRequired: false, transformFunction: null }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, blockControls: { classPropertyName: "blockControls", publicName: "blockControls", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, showEditToggle: { classPropertyName: "showEditToggle", publicName: "showEditToggle", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", isSignal: true, isRequired: false, transformFunction: null }, starterKitOptions: { classPropertyName: "starterKitOptions", publicName: "starterKitOptions", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange", imageUploaded: "imageUploaded", imageRejected: "imageRejected", pastedImageRejected: "pastedImageRejected" }, host: { properties: { "class.fill-container": "finalFillContainer()", "class.floating-toolbar": "finalFloatingToolbar()", "class.is-readonly": "!finalEditable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "finalSeamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "finalSeamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-background": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-border-color": "finalSeamless() ? 'transparent' : null", "class.dark": "config().theme === 'dark'", "class.ate-blocks-inside": "finalBlockControls() === 'inside'", "class.ate-blocks-outside": "finalBlockControls() === 'outside'", "attr.data-theme": "config().theme" } }, providers: [
|
|
9649
10416
|
AteEditorCommandsService,
|
|
9650
10417
|
AteImageService,
|
|
9651
10418
|
AteColorPickerService,
|
|
@@ -10141,5 +10908,5 @@ const ATE_DEFAULT_TOC_CONFIG = {
|
|
|
10141
10908
|
* Generated bundle index. Do not edit.
|
|
10142
10909
|
*/
|
|
10143
10910
|
|
|
10144
|
-
export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_CONFIG, ATE_DEFAULT_ICONS, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOC_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_ICONS, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_MATERIAL_SYMBOLS_VIEWBOX, ATE_SLASH_COMMAND_KEYS, ATE_STROKE_ICONS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteEditorRef, AteEditorRegistry, AteExportService, AteI18nService, AteIconComponent, AteIconRegistry, AteImageCalculator, AteImageService, AteLinkService, AteLinkShortcut, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AtePastedImage, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteTableOfContentsComponent, AteTocNodeComponent, AteTocNodeOptions, AteTooltipDirective, classifyPastedImageSrc, createAngularComponentExtension, createDefaultSlashCommands, dataUriToFile, filterSlashCommands, getAteTocNodeExtension, isLinkShortcut, provideAteEditor, provideAteIcons, registerAngularComponent, sanitizePastedImages };
|
|
10911
|
+
export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_CONFIG, ATE_DEFAULT_ICONS, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOC_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_ICONS, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_MATERIAL_SYMBOLS_VIEWBOX, ATE_SLASH_COMMAND_KEYS, ATE_STROKE_ICONS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteBlockShortcuts, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteEditorRef, AteEditorRegistry, AteExportService, AteI18nService, AteIconComponent, AteIconRegistry, AteImageCalculator, AteImageService, AteImageValidationError, AteLinkService, AteLinkShortcut, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AtePastedImage, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteTableOfContentsComponent, AteTocNodeComponent, AteTocNodeOptions, AteTooltipDirective, classifyPastedImageSrc, createAngularComponentExtension, createDefaultSlashCommands, dataUriToFile, filterSlashCommands, getAteTocNodeExtension, isLinkShortcut, provideAteEditor, provideAteIcons, registerAngularComponent, sanitizePastedImages };
|
|
10145
10912
|
//# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map
|