@aster-editor/core 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +191 -92
  2. package/dist/api/commands.d.ts +8 -1
  3. package/dist/api/commands.d.ts.map +1 -1
  4. package/dist/api/commands.js +3 -0
  5. package/dist/api/commands.js.map +1 -1
  6. package/dist/api/index.d.ts +2 -0
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/index.js +1 -0
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/api/layout.d.ts +181 -0
  11. package/dist/api/layout.d.ts.map +1 -0
  12. package/dist/api/layout.js +28 -0
  13. package/dist/api/layout.js.map +1 -0
  14. package/dist/api/options.d.ts +6 -0
  15. package/dist/api/options.d.ts.map +1 -1
  16. package/dist/commands/layout.d.ts +40 -0
  17. package/dist/commands/layout.d.ts.map +1 -0
  18. package/dist/commands/layout.js +262 -0
  19. package/dist/commands/layout.js.map +1 -0
  20. package/dist/commands/standard.d.ts +4 -3
  21. package/dist/commands/standard.d.ts.map +1 -1
  22. package/dist/commands/standard.js +7 -3
  23. package/dist/commands/standard.js.map +1 -1
  24. package/dist/editor/aster-editor.d.ts +16 -1
  25. package/dist/editor/aster-editor.d.ts.map +1 -1
  26. package/dist/editor/aster-editor.js +41 -1
  27. package/dist/editor/aster-editor.js.map +1 -1
  28. package/dist/extensions/aster-extensions.d.ts +3 -0
  29. package/dist/extensions/aster-extensions.d.ts.map +1 -1
  30. package/dist/extensions/aster-extensions.js +24 -5
  31. package/dist/extensions/aster-extensions.js.map +1 -1
  32. package/dist/extensions/header-footer-sanitize.d.ts +22 -0
  33. package/dist/extensions/header-footer-sanitize.d.ts.map +1 -0
  34. package/dist/extensions/header-footer-sanitize.js +226 -0
  35. package/dist/extensions/header-footer-sanitize.js.map +1 -0
  36. package/dist/extensions/layout-css.d.ts +88 -0
  37. package/dist/extensions/layout-css.d.ts.map +1 -0
  38. package/dist/extensions/layout-css.js +297 -0
  39. package/dist/extensions/layout-css.js.map +1 -0
  40. package/dist/extensions/list-layout.d.ts +23 -0
  41. package/dist/extensions/list-layout.d.ts.map +1 -0
  42. package/dist/extensions/list-layout.js +65 -0
  43. package/dist/extensions/list-layout.js.map +1 -0
  44. package/dist/extensions/page-break.d.ts +8 -0
  45. package/dist/extensions/page-break.d.ts.map +1 -0
  46. package/dist/extensions/page-break.js +20 -0
  47. package/dist/extensions/page-break.js.map +1 -0
  48. package/dist/extensions/page-view.d.ts +68 -0
  49. package/dist/extensions/page-view.d.ts.map +1 -0
  50. package/dist/extensions/page-view.js +189 -0
  51. package/dist/extensions/page-view.js.map +1 -0
  52. package/dist/extensions/pagination-controller.d.ts +110 -0
  53. package/dist/extensions/pagination-controller.d.ts.map +1 -0
  54. package/dist/extensions/pagination-controller.js +295 -0
  55. package/dist/extensions/pagination-controller.js.map +1 -0
  56. package/dist/extensions/pagination-layout.d.ts +54 -0
  57. package/dist/extensions/pagination-layout.d.ts.map +1 -0
  58. package/dist/extensions/pagination-layout.js +109 -0
  59. package/dist/extensions/pagination-layout.js.map +1 -0
  60. package/dist/extensions/pagination-measure.d.ts +42 -0
  61. package/dist/extensions/pagination-measure.d.ts.map +1 -0
  62. package/dist/extensions/pagination-measure.js +108 -0
  63. package/dist/extensions/pagination-measure.js.map +1 -0
  64. package/dist/extensions/pagination.d.ts +36 -0
  65. package/dist/extensions/pagination.d.ts.map +1 -0
  66. package/dist/extensions/pagination.js +69 -0
  67. package/dist/extensions/pagination.js.map +1 -0
  68. package/dist/extensions/paragraph-layout.d.ts +62 -0
  69. package/dist/extensions/paragraph-layout.d.ts.map +1 -0
  70. package/dist/extensions/paragraph-layout.js +227 -0
  71. package/dist/extensions/paragraph-layout.js.map +1 -0
  72. package/dist/extensions/run-layout.d.ts +79 -0
  73. package/dist/extensions/run-layout.d.ts.map +1 -0
  74. package/dist/extensions/run-layout.js +302 -0
  75. package/dist/extensions/run-layout.js.map +1 -0
  76. package/dist/extensions/table-layout.d.ts +85 -0
  77. package/dist/extensions/table-layout.d.ts.map +1 -0
  78. package/dist/extensions/table-layout.js +314 -0
  79. package/dist/extensions/table-layout.js.map +1 -0
  80. package/dist/html/serialize-html.d.ts +42 -0
  81. package/dist/html/serialize-html.d.ts.map +1 -0
  82. package/dist/html/serialize-html.js +159 -0
  83. package/dist/html/serialize-html.js.map +1 -0
  84. package/dist/i18n/en.d.ts.map +1 -1
  85. package/dist/i18n/en.js +8 -0
  86. package/dist/i18n/en.js.map +1 -1
  87. package/dist/i18n/fr.d.ts.map +1 -1
  88. package/dist/i18n/fr.js +8 -0
  89. package/dist/i18n/fr.js.map +1 -1
  90. package/dist/index.d.ts +11 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +13 -0
  93. package/dist/index.js.map +1 -1
  94. package/package.json +2 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ✳️ @aster-editor/core
2
2
 
3
- > Moteur d'Aster Editor : `createEditor` sur Tiptap 3 / ProseMirror, registre de commandes typées, variables de document (champs de fusion), recherche / remplacement, sommaire, reproduction de mise en forme, i18n, événements, sérialisation HTML, JSON et Markdown, autosave. Aucune UI dedans, aucun framework.
3
+ > Moteur d'Aster Editor : `createEditor` sur Tiptap 3 / ProseMirror, registre de commandes typées, variables de document (champs de fusion), recherche / remplacement, sommaire, reproduction de mise en forme, mise en page des paragraphes et des runs (session 3), vue page avec pagination approximative, i18n, événements, sérialisation HTML, JSON et Markdown, autosave. Aucune UI dedans, aucun framework.
4
4
 
5
5
  Ce README est le tutoriel. La référence exhaustive du contrat est dans [`docs/API_CORE.md`](../../docs/API_CORE.md).
6
6
 
@@ -32,23 +32,24 @@ editor.destroy();
32
32
 
33
33
  ## ⚙️ Options (`AsterOptions`)
34
34
 
35
- | Champ | Type | Défaut | Rôle |
36
- | ------------------- | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
37
- | `element` | `HTMLElement` | requis | Hôte. Le core y ajoute `.aster-content`. |
38
- | `content` | `string \| AsterDocument` | `''` | Contenu initial, HTML ou JSON ProseMirror. |
39
- | `placeholder` | `string` | i18n | Texte affiché quand le document est vide. Sans valeur, `editor.placeholder` traduit selon la locale. |
40
- | `readOnly` | `boolean` | `false` | Lecture seule au montage. |
41
- | `locale` | `AsterLocale` | `'fr'` | Locale initiale. `fr` et `en` fournies ; toute autre chaîne après `i18n.addTranslations`. |
42
- | `autofocus` | `boolean` | `false` | Focus en fin de document au montage. |
43
- | `extensions` | `readonly AnyExtension[]` | `[]` | Extensions Tiptap ajoutées après le jeu standard, donc prioritaires pour surcharger. |
44
- | `commands` | `readonly AsterCommand[]` | `[]` | Commandes custom enregistrées au montage. Un `id` existant remplace la commande standard. |
45
- | `pasteTransformers` | `readonly PasteTransformer[]` | `[]` | Transformateurs de HTML collé, chaînés dans l'ordre. |
46
- | `upload` | `UploadHandler` | — | `(file: File) => Promise<string>` : URL finale d'une image. Sans hook, repli en data URL base64. |
47
- | `linkPolicy` | `LinkPolicy` | voir § | Protocoles autorisés, cible et `rel` par défaut, autolink. S'applique aussi aux sources d'images. |
48
- | `variables` | `VariableSource` | `{}` | Variables de document : déclarations, valeurs initiales, résolveur, `allowUnknown`. Voir « Variables de document ». |
49
- | `disabledCommands` | `readonly string[]` | `[]` | Commandes standard retirées du registre **et** dont le raccourci clavier est avalé (sinon la liaison native de Tiptap continuerait). |
50
-
51
- Le contrat `AsterOptions` est figé : ce qui n'y entre pas (autosave, Markdown, sommaire, reproduction de mise en forme) est fourni par des **fonctions compagnons** qui prennent l'éditeur en premier argument.
35
+ | Champ | Type | Défaut | Rôle |
36
+ | ------------------- | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
37
+ | `element` | `HTMLElement` | requis | Hôte. Le core y ajoute `.aster-content`. |
38
+ | `content` | `string \| AsterDocument` | `''` | Contenu initial, HTML ou JSON ProseMirror. |
39
+ | `placeholder` | `string` | i18n | Texte affiché quand le document est vide. Sans valeur, `editor.placeholder` traduit selon la locale. |
40
+ | `readOnly` | `boolean` | `false` | Lecture seule au montage. |
41
+ | `locale` | `AsterLocale` | `'fr'` | Locale initiale. `fr` et `en` fournies ; toute autre chaîne après `i18n.addTranslations`. |
42
+ | `autofocus` | `boolean` | `false` | Focus en fin de document au montage. |
43
+ | `extensions` | `readonly AnyExtension[]` | `[]` | Extensions Tiptap ajoutées après le jeu standard, donc prioritaires pour surcharger. |
44
+ | `commands` | `readonly AsterCommand[]` | `[]` | Commandes custom enregistrées au montage. Un `id` existant remplace la commande standard. |
45
+ | `pasteTransformers` | `readonly PasteTransformer[]` | `[]` | Transformateurs de HTML collé, chaînés dans l'ordre. |
46
+ | `upload` | `UploadHandler` | — | `(file: File) => Promise<string>` : URL finale d'une image. Sans hook, repli en data URL base64. |
47
+ | `linkPolicy` | `LinkPolicy` | voir § | Protocoles autorisés, cible et `rel` par défaut, autolink. S'applique aussi aux sources d'images. |
48
+ | `variables` | `VariableSource` | `{}` | Variables de document : déclarations, valeurs initiales, résolveur, `allowUnknown`. Voir « Variables de document ». |
49
+ | `pageView` | `boolean \| PageViewOptions` | `false` | Vue page au montage : feuille aux dimensions et marges de `layout.page`, en-têtes et pieds en lecture seule, pagination approximative. `true` = A4 portrait, marges 25,4 mm. Voir « Vue page et pagination ». |
50
+ | `disabledCommands` | `readonly string[]` | `[]` | Commandes standard retirées du registre **et** dont le raccourci clavier est avalé (sinon la liaison native de Tiptap continuerait). |
51
+
52
+ Le contrat `AsterOptions` est figé : ce qui n'y entre pas (autosave, Markdown, sommaire, reproduction de mise en forme) est fourni par des **fonctions compagnons** qui prennent l'éditeur en premier argument. La session 3 l'a enrichi sans rupture (`pageView`, commandes `paragraph.*`, types de `api/layout.ts`).
52
53
 
53
54
  ## 🧰 API de `AsterEditor`
54
55
 
@@ -65,16 +66,16 @@ Le contrat `AsterOptions` est figé : ce qui n'y entre pas (autosave, Markdown,
65
66
 
66
67
  ### Contenu
67
68
 
68
- | Méthode | Rôle |
69
- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
70
- | `getHTML(options?)` | HTML sémantique stable, sans `colgroup`, `min-width` ni `colspan="1"` sur les tables. `setHTML(getHTML())` est idempotent. Mis en cache tant que le document ne change pas : l'appeler à chaque frappe ne coûte qu'une sérialisation par transaction. `{ variables: 'resolve' }` substitue les valeurs connues aux puces (texte brut échappé, `{{nom}}` conservé sans valeur) ; `'placeholders'` (défaut) garde les `<span data-aster-variable>`. |
71
- | `setHTML(html, emit?)` | Remplace tout le contenu. `emit = false` n'émet pas `change`, n'entre pas dans l'historique **et vide l'historique antérieur** (un `undo` qui suit ne fait rien) : c'est le mode de `writeValue` côté formulaire. Avec `emit = true` (défaut), le remplacement est une étape annulable. |
72
- | `getJSON(): AsterDocument` | Document JSON ProseMirror (`JSONContent` de Tiptap). |
73
- | `setJSON(doc, emit?)` | Idem avec un document JSON, mêmes règles pour `emit`. |
74
- | `getText(): string` | Texte brut : un seul `\n` entre deux blocs de texte, cellules de table et items de liste compris ; un `\n` par `hardBreak`. Une puce de variable rend sa valeur si elle est connue, sinon `{{nom}}`. |
75
- | `insertHTML(html)` | Insère à la sélection courante, en passant par le schéma. HTML **brut, non transformé** : ni `pasteTransformers` ni normaliseur Word ne s'appliquent, seule la politique de liens et d'images filtre. Transforme le HTML avant si besoin. Donne le focus. |
76
- | `isEmpty(): boolean` | Vrai pour un document sans contenu. Note : `getHTML()` d'un document vide vaut `<p></p>`, teste `isEmpty()` plutôt. |
77
- | `getCounts(): AsterCounts` | `{ words, characters }` via `CharacterCount`. |
69
+ | Méthode | Rôle |
70
+ | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
71
+ | `getHTML(options?)` | HTML sémantique stable, sans `colgroup`, `min-width` ni `colspan="1"` sur les tables. `setHTML(getHTML())` est idempotent, attributs de mise en page compris (sérialisation verbatim, voir « Sérialiseur HTML verbatim »). Mis en cache tant que le document ne change pas : l'appeler à chaque frappe ne coûte qu'une sérialisation par transaction. `{ variables: 'resolve' }` substitue les valeurs connues aux puces (texte brut échappé, `{{nom}}` conservé sans valeur) ; `'placeholders'` (défaut) garde les `<span data-aster-variable>`. |
72
+ | `setHTML(html, emit?)` | Remplace tout le contenu. `emit = false` n'émet pas `change`, n'entre pas dans l'historique **et vide l'historique antérieur** (un `undo` qui suit ne fait rien) : c'est le mode de `writeValue` côté formulaire. Avec `emit = true` (défaut), le remplacement est une étape annulable. |
73
+ | `getJSON(): AsterDocument` | Document JSON ProseMirror (`JSONContent` de Tiptap). |
74
+ | `setJSON(doc, emit?)` | Idem avec un document JSON, mêmes règles pour `emit`. |
75
+ | `getText(): string` | Texte brut : un seul `\n` entre deux blocs de texte, cellules de table et items de liste compris ; un `\n` par `hardBreak`. Une puce de variable rend sa valeur si elle est connue, sinon `{{nom}}`. |
76
+ | `insertHTML(html)` | Insère à la sélection courante, en passant par le schéma. HTML **brut, non transformé** : ni `pasteTransformers` ni normaliseur Word ne s'appliquent, seule la politique de liens et d'images filtre. Transforme le HTML avant si besoin. Donne le focus. |
77
+ | `isEmpty(): boolean` | Vrai pour un document sans contenu. Note : `getHTML()` d'un document vide vaut `<p></p>`, teste `isEmpty()` plutôt. |
78
+ | `getCounts(): AsterCounts` | `{ words, characters }` via `CharacterCount`. |
78
79
 
79
80
  Markdown : `getMarkdown(editor)` et `setMarkdown(editor, markdown, emit?)`, fonctions compagnons, voir plus bas.
80
81
 
@@ -114,68 +115,70 @@ editor.commands.isActive('heading', { level: 2 });
114
115
 
115
116
  Les identifiants standard sont autocomplétés et leurs arguments typés par `StandardCommandArgs` (`run('heading', …)` attend `{ level }`). Le registre garde aussi une surcharge libre `run(id: string, args?: unknown)` pour les commandes custom et `search.*` : `run('heading')` sans argument compile donc par cette surcharge et répond `false` à l'exécution. Vérifie tes arguments, TypeScript ne le fera pas à ta place sur cette surcharge.
116
117
 
117
- ### Tableau des 50 commandes standard
118
-
119
- Raccourcis au format Tiptap : `Mod` = `Ctrl` sur Windows/Linux, `⌘` sur macOS. Libellés = dictionnaire `fr` (clé `command.<id>`).
120
-
121
- | Id | Libellé fr | Raccourci | Arguments |
122
- | -------------------------- | ---------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
123
- | `bold` | Gras | `Mod-b` | — |
124
- | `italic` | Italique | `Mod-i` | — |
125
- | `underline` | Souligné | `Mod-u` | — |
126
- | `strike` | Barré | `Mod-Shift-s` | — |
127
- | `subscript` | Indice | — | — |
128
- | `superscript` | Exposant | — | — |
129
- | `code` | Code | `Mod-e` | — |
130
- | `highlight` | Surligner | `Mod-Shift-h` | — |
131
- | `clearFormatting` | Effacer la mise en forme | — | — (retire les marks sauf `link`, ramène les blocs de texte au paragraphe sans alignement ; liste, citation et cellule restent en place ; impossible sur document vide) |
132
- | `paragraph` | Paragraphe | — | — (pose le type sans repli : impossible dans un item de liste ou si le bloc est déjà un paragraphe) |
133
- | `heading` | Titre | `Mod-Alt-1` … `Mod-Alt-6` | `{ level: 1 \| 2 \| 3 \| 4 \| 5 \| 6 }` (idem : pas de bascule, pas de titre dans un item de liste en V1) |
134
- | `blockquote` | Citation | — | — |
135
- | `codeBlock` | Bloc de code | — | — |
136
- | `horizontalRule` | Séparateur | — | — |
137
- | `hardBreak` | Saut de ligne | — | — |
138
- | `bulletList` | Liste à puces | `Mod-Shift-8` | — |
139
- | `orderedList` | Liste numérotée | `Mod-Shift-7` | — |
140
- | `taskList` | Liste de tâches | — | — |
141
- | `indent` | Augmenter le retrait | — | — (`listItem` puis `taskItem`) |
142
- | `outdent` | Réduire le retrait | — | — |
143
- | `alignLeft` | Aligner à gauche | — | — (retire l'attribut ; actif quand aucun alignement explicite) |
144
- | `alignCenter` | Centrer | — | — |
145
- | `alignRight` | Aligner à droite | — | — |
146
- | `alignJustify` | Justifier | — | — |
147
- | `link.set` | Insérer un lien | `Mod-k` | `{ href: string; target?: '_blank' \| '_self'; title?: string }` |
148
- | `link.unset` | Supprimer le lien | — | — |
149
- | `image.insert` | Insérer une image | — | `{ src: string; alt?: string; title?: string; width?: number }` (jamais active : pas une bascule ; impossible dans un bloc de code ; `src` soumis à la politique) |
150
- | `image.upload` | Importer une image | — | `{ file: File }` (asynchrone : voir `uploadStart` / `uploadDone`) |
151
- | `image.setAttributes` | Propriétés de l'image | — | `{ alt?: string; title?: string; width?: number; align?: 'left' \| 'center' \| 'right' }` (sur l'image sélectionnée) |
152
- | `table.insert` | Insérer un tableau | — | `{ rows: number; cols: number; withHeaderRow?: boolean }` (`withHeaderRow` vrai par défaut ; impossible dans une table : pas de tables imbriquées en V1) |
153
- | `table.delete` | Supprimer le tableau | — | — |
154
- | `table.addRowBefore` | Insérer une ligne au-dessus | — | — |
155
- | `table.addRowAfter` | Insérer une ligne en dessous | — | — |
156
- | `table.deleteRow` | Supprimer la ligne | — | — |
157
- | `table.addColumnBefore` | Insérer une colonne à gauche | — | — |
158
- | `table.addColumnAfter` | Insérer une colonne à droite | — | — |
159
- | `table.deleteColumn` | Supprimer la colonne | — | — |
160
- | `table.mergeCells` | Fusionner les cellules | — | — |
161
- | `table.splitCell` | Scinder la cellule | — | — |
162
- | `table.toggleHeaderRow` | Ligne d'en-tête | — | — |
163
- | `table.toggleHeaderColumn` | Colonne d'en-tête | — | — |
164
- | `textColor` | Couleur du texte | — | `{ color: string \| null }` |
165
- | `backgroundColor` | Couleur de fond | — | `{ color: string \| null }` |
166
- | `fontFamily` | Police | — | `{ family: string \| null }` |
167
- | `fontSize` | Taille | — | `{ size: string \| null }` (ex. `'14px'`) |
168
- | `variable.insert` | Insérer une variable | — | `{ name: string; label?: string }` (remplace la sélection par une puce ; refusé si le nom est invalide, non déclaré avec `allowUnknown: false`, ou dans un bloc de code) |
169
- | `variable.remove` | Supprimer la variable | — | — (la puce sélectionnée ou collée au curseur ; `canRun` et `isActive` disent s'il y en a une) |
170
- | `undo` | Annuler | `Mod-z` | — |
171
- | `redo` | Rétablir | `Mod-Shift-z`, `Mod-y` | — |
172
- | `selectAll` | Tout sélectionner | `Mod-a` | — |
118
+ ### Tableau des 52 commandes standard
119
+
120
+ Raccourcis au format Tiptap : `Mod` = `Ctrl` sur Windows/Linux, `⌘` sur macOS. Libellés = dictionnaire `fr` (clé `command.<id>`). Les deux commandes `paragraph.*` sont celles de la session 3.
121
+
122
+ | Id | Libellé fr | Raccourci | Arguments |
123
+ | -------------------------- | ------------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124
+ | `bold` | Gras | `Mod-b` | — |
125
+ | `italic` | Italique | `Mod-i` | — |
126
+ | `underline` | Souligné | `Mod-u` | — |
127
+ | `strike` | Barré | `Mod-Shift-s` | — |
128
+ | `subscript` | Indice | — | — |
129
+ | `superscript` | Exposant | — | — |
130
+ | `code` | Code | `Mod-e` | — |
131
+ | `highlight` | Surligner | `Mod-Shift-h` | — |
132
+ | `clearFormatting` | Effacer la mise en forme | — | — (retire les marks sauf `link`, ramène les blocs de texte au paragraphe sans alignement ; liste, citation et cellule restent en place ; impossible sur document vide) |
133
+ | `paragraph` | Paragraphe | — | — (pose le type sans repli : impossible dans un item de liste ou si le bloc est déjà un paragraphe) |
134
+ | `heading` | Titre | `Mod-Alt-1` … `Mod-Alt-6` | `{ level: 1 \| 2 \| 3 \| 4 \| 5 \| 6 }` (idem : pas de bascule, pas de titre dans un item de liste en V1) |
135
+ | `blockquote` | Citation | — | — |
136
+ | `codeBlock` | Bloc de code | — | — |
137
+ | `horizontalRule` | Séparateur | — | — |
138
+ | `hardBreak` | Saut de ligne | — | — |
139
+ | `bulletList` | Liste à puces | `Mod-Shift-8` | — |
140
+ | `orderedList` | Liste numérotée | `Mod-Shift-7` | — |
141
+ | `taskList` | Liste de tâches | — | — |
142
+ | `indent` | Augmenter le retrait | — | — (`listItem` puis `taskItem`) |
143
+ | `outdent` | Réduire le retrait | — | — |
144
+ | `alignLeft` | Aligner à gauche | — | — (retire l'attribut ; actif quand aucun alignement explicite) |
145
+ | `alignCenter` | Centrer | — | — |
146
+ | `alignRight` | Aligner à droite | — | — |
147
+ | `alignJustify` | Justifier | — | — |
148
+ | `link.set` | Insérer un lien | `Mod-k` | `{ href: string; target?: '_blank' \| '_self'; title?: string }` |
149
+ | `link.unset` | Supprimer le lien | — | — |
150
+ | `image.insert` | Insérer une image | — | `{ src: string; alt?: string; title?: string; width?: number }` (jamais active : pas une bascule ; impossible dans un bloc de code ; `src` soumis à la politique) |
151
+ | `image.upload` | Importer une image | — | `{ file: File }` (asynchrone : voir `uploadStart` / `uploadDone`) |
152
+ | `image.setAttributes` | Propriétés de l'image | — | `{ alt?: string; title?: string; width?: number; align?: 'left' \| 'center' \| 'right' }` (sur l'image sélectionnée) |
153
+ | `table.insert` | Insérer un tableau | — | `{ rows: number; cols: number; withHeaderRow?: boolean }` (`withHeaderRow` vrai par défaut ; impossible dans une table : pas de tables imbriquées en V1) |
154
+ | `table.delete` | Supprimer le tableau | — | — |
155
+ | `table.addRowBefore` | Insérer une ligne au-dessus | — | — |
156
+ | `table.addRowAfter` | Insérer une ligne en dessous | — | — |
157
+ | `table.deleteRow` | Supprimer la ligne | — | — |
158
+ | `table.addColumnBefore` | Insérer une colonne à gauche | — | — |
159
+ | `table.addColumnAfter` | Insérer une colonne à droite | — | — |
160
+ | `table.deleteColumn` | Supprimer la colonne | — | — |
161
+ | `table.mergeCells` | Fusionner les cellules | — | — |
162
+ | `table.splitCell` | Scinder la cellule | — | — |
163
+ | `table.toggleHeaderRow` | Ligne d'en-tête | — | — |
164
+ | `table.toggleHeaderColumn` | Colonne d'en-tête | — | — |
165
+ | `textColor` | Couleur du texte | — | `{ color: string \| null }` |
166
+ | `backgroundColor` | Couleur de fond | — | `{ color: string \| null }` |
167
+ | `fontFamily` | Police | — | `{ family: string \| null }` |
168
+ | `fontSize` | Taille | — | `{ size: string \| null }` (ex. `'14px'`) |
169
+ | `variable.insert` | Insérer une variable | — | `{ name: string; label?: string }` (remplace la sélection par une puce ; refusé si le nom est invalide, non déclaré avec `allowUnknown: false`, ou dans un bloc de code) |
170
+ | `variable.remove` | Supprimer la variable | — | — (la puce sélectionnée ou collée au curseur ; `canRun` et `isActive` disent s'il y en a une) |
171
+ | `paragraph.setLayout` | Mise en page du paragraphe | — | `ParagraphLayoutAttrs` : fusionne les attributs donnés dans chaque paragraphe et titre de la sélection (cellules et items compris), `null` efface un attribut, une valeur invalide est ignorée. Voir « Mise en page » |
172
+ | `paragraph.unsetLayout` | Effacer la mise en page du paragraphe | — | `{ attrs?: ParagraphLayoutAttrName[] } \| undefined` : efface les attributs nommés, ou tous sans argument |
173
+ | `undo` | Annuler | `Mod-z` | — |
174
+ | `redo` | Rétablir | `Mod-Shift-z`, `Mod-y` | — |
175
+ | `selectAll` | Tout sélectionner | `Mod-a` | — |
173
176
 
174
177
  Les raccourcis à liaisons multiples (`heading`, `redo`) sont déclarés dans `EXTRA_SHORTCUT_BINDINGS` (7 liaisons) ; `Tab` / `Shift-Tab` dans les listes et les tables sont gérés nativement par Tiptap. Une commande custom qui déclare un `shortcut` est câblée automatiquement par `collectShortcutBindings`.
175
178
 
176
179
  ### Les 6 commandes de recherche (`search.*`)
177
180
 
178
- Enregistrées par `createStandardCommands` en plus des 50 du contrat, mais **hors de `STANDARD_COMMAND_IDS`** : leurs identifiants sont dans `SEARCH_COMMAND_IDS` et leurs arguments dans `SearchCommandArgs` (`{ query: string; replacement?: string; caseSensitive?: boolean }`, tous lus de façon tolérante : `run('search.next')` sans argument marche). Avec les deux commandes `formatPainter.*` (voir plus bas), le registre compte 58 commandes au montage.
181
+ Enregistrées par `createStandardCommands` en plus des 52 du contrat, mais **hors de `STANDARD_COMMAND_IDS`** : leurs identifiants sont dans `SEARCH_COMMAND_IDS` et leurs arguments dans `SearchCommandArgs` (`{ query: string; replacement?: string; caseSensitive?: boolean }`, tous lus de façon tolérante : `run('search.next')` sans argument marche). Avec les deux commandes `formatPainter.*` et les trois commandes `text.*` (voir plus bas), le registre compte **63 commandes** au montage (`editor.commands.list().length`).
179
182
 
180
183
  | Id | Libellé fr | Raccourci | Comportement |
181
184
  | ------------------- | ------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -410,7 +413,100 @@ editor.element.addEventListener(IMAGE_EDIT_EVENT, (event) => {
410
413
 
411
414
  ## 📋 Tables
412
415
 
413
- `TableKit` avec `resizable: true` et `cellMinWidth: 48` : les colonnes se redimensionnent à la souris (`column-resize-handle`, curseur `resize-cursor`, styles dans `images-tables.css`). Les largeurs sont stockées dans `colwidth` et sérialisées… puis retirées par `normalizeOutputHtml` : `getHTML()` ne contient ni `colgroup`, ni `min-width`, ni `colspan="1"`, pour un HTML stable d'une session à l'autre. Pas de tables imbriquées en V1 : `table.insert` répond `false` dans une table, même si le schéma les tolère au parsing.
416
+ `TableKit` pour la ligne, `AsterTable`, `AsterTableCell` et `AsterTableHeader` (celles de Tiptap plus les attributs de mise en page, voir plus bas) avec `resizable: true` et `cellMinWidth: 48` : les colonnes se redimensionnent à la souris (`column-resize-handle`, curseur `resize-cursor`, styles dans `images-tables.css`). Les largeurs sont stockées dans `colwidth` et sérialisées… puis le bruit est retiré par `normalizeOutputHtml` : `getHTML()` ne contient ni `colgroup`, ni `min-width`, ni `colspan="1"`, pour un HTML stable d'une session à l'autre. `colspan` est borné à 63 et `rowspan` à 1 000 à l'analyse (`MAX_COLSPAN`, `MAX_ROWSPAN`) : un `colspan="1000000"` venu d'un `.docx` hostile faisait allouer une grille de 4 Go. Pas de tables imbriquées **par la commande** : `table.insert` répond `false` dans une table ; le schéma les accepte au parsing et l'import Word en produit.
417
+
418
+ ## 📐 Mise en page (session 3)
419
+
420
+ Le contrat `api/layout.ts` décrit ce que l'import Word sait apporter et que l'éditeur sait représenter : des attributs de paragraphe, des attributs de run, de liste, de tableau et de cellule, chacun avec une **sérialisation HTML exacte** (`style` inline normalisé dans un ordre figé, attributs `data-*`), et un `DocumentLayout` pour la page. Unités : points typographiques (`pt`) pour le texte et les paragraphes, millimètres pour la page, nombre sans unité pour un interligne multiple ; couleurs en `#rrggbb` minuscules. `setHTML(getHTML())` conserve chaque attribut à l'identique (idempotence stricte, vérifiée sur les fixtures Word 11-17).
421
+
422
+ ### Attributs de paragraphe (`ParagraphLayoutAttrs`, extension `ParagraphLayout`)
423
+
424
+ Portés par `paragraph` et `heading`, tous `null` par défaut (hérités du style de l'éditeur). Déclarations émises dans cet ordre, après le `text-align` de `TextAlign`, uniquement pour les valeurs présentes ; puis les attributs `data-*` dans l'ordre `data-border-between`, `data-docx-style`, `data-keep-next`, `data-page-break-before` :
425
+
426
+ | Attribut | Type | Sérialisé | Exemple |
427
+ | ------------------- | --------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
428
+ | `lineHeight` | `number` | `line-height: 1.15` (multiple, sans unité ; `115%` relu comme `1.15`) | `<p style="line-height: 1.15">` |
429
+ | `lineHeightPt` | `number` | `line-height: 14pt` (exact ; l'emporte sur `lineHeight`) | `<p style="line-height: 14pt">` |
430
+ | `spacingBeforePt` | `number` | `margin-top: 6pt` | `<p style="margin-top: 6pt">` |
431
+ | `spacingAfterPt` | `number` | `margin-bottom: 6pt` | `<p style="margin-bottom: 6pt">` |
432
+ | `indentLeftPt` | `number` | `margin-left: 36pt` | `<p style="margin-left: 36pt">` |
433
+ | `indentRightPt` | `number` | `margin-right: 12pt` | `<p style="margin-right: 12pt">` |
434
+ | `indentFirstLinePt` | `number` | `text-indent: 18pt` (négatif = retrait suspendu) | `<p style="margin-left: 36pt; text-indent: -18pt">` |
435
+ | `borders` | `BlockBorder[]` | `border-<côté>: <épaisseur>pt <style> #rrggbb` par côté ; `between` en `data-border-between` | `<p style="border-bottom: 1pt solid #000000" data-border-between="0.5pt dashed #808080">` |
436
+ | `shading` | `string` | `background-color: #eeeeee` | `<p style="background-color: #eeeeee">` |
437
+ | `keepWithNext` | `boolean` | `data-keep-next` (présent = vrai) | `<h2 data-keep-next>` |
438
+ | `pageBreakBefore` | `boolean` | `data-page-break-before` | `<h1 data-page-break-before>` |
439
+ | `docxStyle` | `string` | `data-docx-style` (identifiant du style Word, jamais interprété par l'éditeur) | `<p data-docx-style="Citation">` |
440
+
441
+ `PARAGRAPH_LAYOUT_ATTR_NAMES` (12 noms, dans l'ordre de sérialisation) et `ParagraphLayoutAttrName` sont exportés. Les nombres sont arrondis à deux décimales et bornés à ±100 000 (`LAYOUT_NUMBER_LIMIT`) : `1e307` ne sérialise jamais `Infinitypt`. `BlockBorder` = `{ side: 'top' | 'right' | 'bottom' | 'left' | 'between', style: 'solid' | 'dashed' | 'dotted' | 'double', widthPt, color }`. Un `<p>` ou un `<li>` importé de Word peut porter en plus `data-docx-num-indent` (extension `ListLayout`, hors contrat) : son retrait vient du niveau de numérotation, l'export ne le réécrit pas.
442
+
443
+ ### Marques de run (`RunLayoutAttrs`, extension `RunLayout`)
444
+
445
+ Sur la marque `textStyle`, après les attributs de `TextStyleKit` (`color`, `background-color`, `font-family`, `font-size`, dans l'ordre `background-color, color, font-family, font-size, letter-spacing, …`) ; sur `underline` et `strike`, un style de trait :
446
+
447
+ | Attribut | Marque | Sérialisé | Exemple |
448
+ | ----------------- | --------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
449
+ | `letterSpacingPt` | `textStyle` | `letter-spacing: 1pt` | `<span style="letter-spacing: 1pt">` |
450
+ | `caps` | `textStyle` | `text-transform: uppercase` (`all`) ou `font-variant: small-caps` (`small`) | `<span style="font-variant: small-caps">` |
451
+ | `docxRunStyle` | `textStyle` | `data-docx-run-style` (un `<span data-docx-run-style>` sans `style` est accepté) | `<span data-docx-run-style="Code">` |
452
+ | `decorationStyle` | `underline`, `strike` | `text-decoration-style: double \| dotted \| dashed \| wavy` (`solid` implicite) | `<u style="text-decoration-style: double">`, `<s style="text-decoration-style: double">` |
453
+
454
+ Les couleurs de `textStyle` et de `highlight` sont normalisées en `#rrggbb` minuscules au rendu (`setColor('#FF0000')` sort `color: #ff0000`, `rgb(255, 0, 0)` aussi). Un `<span style>` dont **aucun** attribut de `textStyle` ne se résout (`text-decoration: underline`, `mso-*` d'un collage Word) n'est plus accepté comme marque : Tiptap créait un `<span>` vide qui disparaissait à la relecture. Les marques s'imbriquent dans un ordre figé, `<span><strong><em><s><u><sup>`, le même que celui du lecteur Word.
455
+
456
+ ### Listes et tableaux (`ListLayoutAttrs`, `TableLayoutAttrs`, `CellLayoutAttrs`)
457
+
458
+ - Listes (`ListLayout`) : `orderedList` a `type` et `start` de Tiptap (`<ol type="a" start="3">`) plus `docxNumId` (`data-docx-num-id`) ; `bulletList` reçoit `bullet` (`data-bullet="–"`) et `docxNumId`. Rien n'est interprété par l'éditeur : ces attributs relient la liste à la numérotation du gabarit Word.
459
+ - Tableau (`AsterTable`) : `width` (`style="width: 100%"` ou `width: 450pt` ; les pixels sont ignorés, c'est la largeur que Tiptap calcule lui-même depuis les `colwidth`), `borders` (`border-top: 0.5pt solid #000000`, un par côté), `docxStyle` (`data-docx-style="TableGrid"`). Tant qu'aucune colonne n'est redimensionnée, la largeur du contrat est celle affichée ; dès qu'une colonne porte un `colwidth`, la largeur calculée par Tiptap prime en édition (`AsterTableView`).
460
+ - Cellule (`AsterTableCell`, `AsterTableHeader`) : `borders`, `shading` (`background-color`), `verticalAlign` (`vertical-align: top | middle | bottom`), `paddingPt` (`padding: 2pt 4pt 2pt 4pt`, quadruplet `top right bottom left`). Exemple complet : `<td colspan="2" style="border-top: 0.5pt solid #000000; background-color: #d9e2f3; vertical-align: middle; padding: 4pt 4pt 4pt 4pt">`.
461
+ - Saut de page : `AsterHorizontalRule` conserve `<hr data-page-break>` (l'import Word le produit pour `w:br w:type="page"`, l'export le relit, la vue page le dessine en coupure de feuille) ; un `<hr>` nu reste un séparateur.
462
+
463
+ ### Commandes `paragraph.*` et `text.*`
464
+
465
+ `paragraph.setLayout` et `paragraph.unsetLayout` sont dans le contrat (`STANDARD_COMMAND_IDS`) ; `text.setLetterSpacing`, `text.setCaps` et `text.unsetCaps` sont additives comme `search.*` (`TEXT_LAYOUT_COMMAND_IDS`, `TextLayoutCommandId`, arguments `SetLetterSpacingArgs` et `SetCapsArgs`, surcharge libre de `run`). Toutes parcourent la sélection **plage par plage** : une sélection de cellules (`CellSelection`) applique la commande à chaque cellule, pas seulement à la cellule d'ancrage (revue R23).
466
+
467
+ ```ts
468
+ editor.commands.run('paragraph.setLayout', {
469
+ lineHeight: 1.5,
470
+ spacingAfterPt: 6,
471
+ indentLeftPt: 36,
472
+ indentFirstLinePt: -18, // retrait suspendu
473
+ borders: [{ side: 'bottom', style: 'solid', widthPt: 1, color: '#000000' }],
474
+ shading: '#eeeeee',
475
+ keepWithNext: true,
476
+ });
477
+ editor.commands.run('paragraph.setLayout', { shading: null }); // null efface un attribut
478
+ editor.commands.run('paragraph.setLayout', { lineHeight: 'abc' as unknown as number }); // false : valeur invalide ignorée, rien d'effacé
479
+ editor.commands.run('paragraph.unsetLayout', { attrs: ['borders', 'shading'] });
480
+ editor.commands.run('paragraph.unsetLayout'); // tout
481
+ editor.commands.run('text.setLetterSpacing', { pt: 1.5 });
482
+ editor.commands.run('text.setCaps', { caps: 'small' });
483
+ editor.commands.isActive('text.setCaps', { caps: 'small' }); // true
484
+ editor.commands.run('text.unsetCaps');
485
+ editor.commands.run('text.setLetterSpacing', { pt: null }); // retire ; une marque textStyle vidée est supprimée
486
+ ```
487
+
488
+ `canRun('paragraph.setLayout')` est vrai dès que la sélection touche un paragraphe ou un titre éditable (`hasLayoutBlockInSelection`), avec des arguments vides ou au moins une valeur valide ; les valeurs sont normalisées (nombres arrondis et bornés, couleurs `#rrggbb`, bordures mal formées filtrées, `false` et chaîne vide valent `null`). Pas de raccourci : ce sont des commandes de menu, câblées par les widgets de `ui`.
489
+
490
+ ## 📄 Vue page et pagination
491
+
492
+ La vue page rend le `.ProseMirror` comme une feuille aux dimensions et marges de `layout.page` (`A4` par défaut, formats `A3`, `A4`, `A5`, `Letter`, `Legal` ou `{ widthMm, heightMm }`, orientation, marges, distances d'en-tête et de pied), avec les en-têtes et pieds `default` en lecture seule au-dessus et au-dessous du corps. Le core ne fait que poser des classes, des variables CSS et des conteneurs ; la feuille de style est `page.css` de `ui`.
493
+
494
+ ```ts
495
+ const editor = createEditor({
496
+ element,
497
+ pageView: { layout, pagination: true, showHeadersFooters: true }, // ou `true` : A4 portrait, 25,4 mm
498
+ });
499
+ ```
500
+
501
+ Ce que `applyPageView` pose : la classe `aster--page-view` sur l'hôte (`editor.element`) ; les huit variables `PAGE_VIEW_CSS_VARIABLES` (`--aster-page-width`, `--aster-page-height`, `--aster-page-margin-top/right/bottom/left`, `--aster-page-margin-header`, `--aster-page-margin-footer`, en `mm`) calculées par `resolvePageMetrics(layout)` (valeurs absurdes, négatives ou au-delà de 10 000 mm ramenées aux défauts : jamais `Infinitymm`) ; deux conteneurs `div.aster-page-header` / `div.aster-page-footer` (`contenteditable="false"`) avant et après `contentElement`, remplis avec `layout.headers.default.html` / `footers.default.html` passés par `sanitizeHeaderFooterHtml` (liste blanche stricte de balises et d'attributs, `href` / `src` limités à `http`, `https`, `mailto`, `tel`, `data:image/`, caractères de contrôle retirés avant le test, `style` sans `url(`, `expression(` ni `\`, imbrication plafonnée à 64 niveaux, pile explicite plutôt que récursion). `showHeadersFooters: false` n'insère aucun conteneur.
502
+
503
+ À chaud, l'implémentation expose `setPageView(options: boolean | PageViewOptions)` (`false` retire tout, idempotent) et `getLayout(): DocumentLayout | null`, **hors du contrat `AsterEditor`** pour l'instant (proposition de contrat de L23 et L26, voir `docs/API_CORE.md`) : `ui` les détecte à l'exécution via `pageViewApiOf(editor)` et le widget `pageLayout` se désactive si elles manquent. Une vue page qui lève au montage (mise en page hostile) est ignorée avec un avertissement, l'éditeur se monte quand même. `getActivePageView(contentElement)` rend les options actives, et l'événement DOM `aster:page-view-change` (`PAGE_VIEW_CHANGE_EVENT`, sans bulle) est émis sur `contentElement` à l'activation et au retrait.
504
+
505
+ **Pagination approximative** (extension `Pagination`, toujours montée, inerte hors vue page ou avec `pagination: false` ; répartie en `pagination.ts` (extension et API), `pagination-measure.ts`, `pagination-controller.ts` et `pagination-layout.ts`, tout étant réexporté depuis `@aster-editor/core`) : un plugin ProseMirror mesure la hauteur rendue des blocs de premier niveau, en lot (`measureBlocks` : alignement DOM / document puis lectures de rectangles, aucune écriture ; un saut de page explicite mesure 0, la coupure qui le suit prend sa place), et pose en **décorations widget** (jamais dans le document, jamais dans `getHTML()`, aucun `change` émis) une coupure `div.aster-page-gap[data-page-number][data-page-count]` avec le libellé « Page n sur N » (`pageView.page`, `pageView.of` de l'i18n) avant chaque bloc qui dépasse la hauteur utile (`usablePageHeightPx` : hauteur de page moins marges, lue dans les variables `--aster-page-*`, 96 / 25,4 px par mm). Recalcul débouncé (`PAGINATION_DEBOUNCE_MS` = 150 ms) puis à la frame suivante, jamais dans un `dispatch` ; redimensionnement de la feuille observé. Sauts de page explicites (`<hr data-page-break>`, ou un nœud `pageBreak` d'intégrateur) forcés ; tableaux et listes **entiers** à la page suivante ; `--aster-page-count` sur l'hôte et `--aster-page-gap-fill` (espace libre en bas de la page précédente) sur chaque coupure, pour que `page.css` étire la feuille et dessine la bande de bureau. 4 000 paragraphes se paginent en 11 ms. **Aucune garantie d'exactitude avec Word** : césure, polices de substitution, interlignes « au moins », veuves et orphelines, `keepWithNext`, tableaux coupés ne sont pas simulés ; le nombre de pages est un ordre de grandeur. `getPaginationResult(editor)` rend `{ gaps, pageCount }` (`PaginationResult`), `paginateNow(editor)` mesure sans attendre (tests, feuille de style changée), `paginate(heights, usableHeight, forcedBreaks)` est la fonction pure.
506
+
507
+ ## 🧾 Sérialiseur HTML verbatim
508
+
509
+ `getHTML()` ne passe plus par `tiptap.getHTML()` : le `DOMSerializer` de ProseMirror pose `style` via `element.style.cssText`, et le moteur CSS (navigateur ou jsdom) réécrit la valeur : couleurs en `rgb()`, `;` final, longhands repliés en raccourcis (`margin: 6pt 6pt 36pt 0pt`, dans un ordre faux sous jsdom). Le contrat de mise en page fige une sérialisation exacte que le paquet `word` relit. `serializeDocumentHtml(doc)` rend donc les `DOMOutputSpec` lui-même (`renderRawSpec`, `createRawStyleSerializer(schema)`), en posant chaque `style` par `setAttribute` verbatim ; tout le reste (structure, trous de contenu, marques) suit la sémantique de `renderSpec`, puis `normalizeOutputHtml` retire le bruit de table. Effet de bord assumé : les couleurs sortent en `#rrggbb`, plus en `rgb()`. La garde de ProseMirror contre un `toDOM` qui renverrait un tableau sorti tel quel des attributs (vecteur XSS : `<img onerror>` décrit par un JSON stocké) est reprise à l'identique (`SUSPICIOUS_SPEC_MESSAGE`).
414
510
 
415
511
  ## 📡 Événements (`AsterEvents`)
416
512
 
@@ -438,7 +534,7 @@ off();
438
534
 
439
535
  ## 🌍 i18n
440
536
 
441
- `fr` et `en` sont intégrés (63 clés chacun), `en` est la locale de repli : clé absente → `en` → la clé elle-même, jamais d'exception. L'interpolation utilise `{name}`.
537
+ `fr` et `en` sont intégrés (70 clés chacun, mêmes clés dans les deux), `en` est la locale de repli : clé absente → `en` → la clé elle-même, jamais d'exception. L'interpolation utilise `{name}`.
442
538
 
443
539
  ```ts
444
540
  import { createEditor, en } from '@aster-editor/core';
@@ -455,7 +551,7 @@ editor.i18n.t('command.bold'); // 'Fett'
455
551
  editor.i18n.setLocale('fr'); // émet localeChange, la toolbar se retraduit
456
552
  ```
457
553
 
458
- Convention de clés : `command.<id>` pour les 58 commandes (`command.table.insert`, `command.search.open`, `command.variable.insert`, `command.formatPainter.copy`), `command.heading.level` avec `{level}`, `editor.placeholder`, `editor.words`, `editor.characters`, `variable.unresolved` avec `{name}` (`title` d'une puce sans valeur). Le paquet `ui` ajoute ses propres clés (`ui.*`) via `addTranslations`.
554
+ Convention de clés : `command.<id>` pour les 63 commandes (`command.table.insert`, `command.search.open`, `command.variable.insert`, `command.formatPainter.copy`, `command.paragraph.setLayout`, `command.text.setCaps`), `command.heading.level` avec `{level}`, `editor.placeholder`, `editor.words`, `editor.characters`, `variable.unresolved` avec `{name}` (`title` d'une puce sans valeur), `pageView.page` et `pageView.of` (libellé « Page n sur N » de la pagination). Le paquet `ui` ajoute ses propres clés (`ui.*`) via `addTranslations`.
459
555
 
460
556
  ## 🔗 Politique de liens et d'images (`LinkPolicy`)
461
557
 
@@ -565,7 +661,7 @@ Tu peux aussi enregistrer après coup : `editor.commands.register(command)` / `u
565
661
 
566
662
  ## 🧱 Extensions Tiptap custom
567
663
 
568
- `options.extensions` ajoute des extensions après le jeu standard. Le jeu standard (`createAsterExtensions`) : `StarterKit` (sans `link`, titres 1-6), `Link` sécurisé, `TaskList` / `TaskItem` imbriqués, `TableKit` redimensionnable, `TextAlign` (paragraphes et titres, sans alignement par défaut), `Image` Aster (`align`, `width`, NodeView), `Variable` (puces liées au magasin de l'éditeur), `Subscript`, `Superscript`, `Highlight` multicolore, `TextStyleKit`, `Placeholder` (fonction de la locale), `CharacterCount`, `Search`, `Outline` (`id` des titres), raccourcis Aster.
664
+ `options.extensions` ajoute des extensions après le jeu standard. Le jeu standard (`createAsterExtensions`, 28 entrées, 64 extensions une fois les kits aplatis) : `StarterKit` (sans `link`, `underline`, `strike` ni `horizontalRule`, titres 1-6), `AsterStrike` et `AsterUnderline` (style de trait), `AsterHorizontalRule` (`data-page-break`), `Link` sécurisé, `TaskList` / `TaskItem` imbriqués, tables redimensionnables (`TableKit`, `AsterTable`, `AsterTableCell`, `AsterTableHeader`), `TextAlign` (paragraphes et titres, sans alignement par défaut), `ParagraphLayout`, `ListLayout`, `Image` Aster (`align`, `width`, NodeView), `Subscript`, `Superscript`, `AsterHighlight` multicolore, `TextStyleKit` sans son `textStyle`, `AsterTextStyle`, `RunLayout`, `Variable` (puces liées au magasin de l'éditeur), `Placeholder` (fonction de la locale), `CharacterCount`, `Search`, `Outline` (`id` des titres), `Pagination`, raccourcis Aster.
569
665
 
570
666
  ```ts
571
667
  import { Extension } from '@tiptap/core';
@@ -598,8 +694,11 @@ const { from, to } = editor.tiptap.state.selection;
598
694
 
599
695
  Tout ce qui suit est dans `packages/core/src/index.ts` :
600
696
 
601
- - **Contrat** (`api/`) : `STANDARD_COMMAND_IDS` et tous les types (`AsterEditor`, `AsterOptions`, `AsterCommand`, `CommandRegistry`, `AsterEvents`, `AsterDocument`, `AsterCounts`, `I18n`, `PasteTransformer`, `ToolbarConfig`, `AsterVariable`, `VariableSource`, `VariableStore`, `VariableValues`, `VariableResolver`, `VariableRenderMode`, `GetHtmlOptions`…).
602
- - **Commandes** : `MARK_COMMANDS`, `BLOCK_COMMANDS`, `LIST_COMMANDS`, `ALIGNMENT_COMMANDS`, `TABLE_COMMANDS`, `TEXT_STYLE_COMMANDS`, `HISTORY_COMMANDS`, `SEARCH_COMMANDS`, `SEARCH_COMMAND_IDS`, `VARIABLE_COMMANDS`, `FORMAT_PAINTER_COMMANDS`, `FORMAT_PAINTER_COMMAND_IDS`, `createLinkCommands(policy)`, `createImageCommands(policy, upload)`, `createStandardCommands(context)`, `defineStandardCommand(id, spec)`, `iconIdFor(id)`, `toImageAttributes`, `getSearchStorage`, `SEARCH_OPEN_EVENT`, `FORMAT_PAINTER_CHANGE_EVENT`.
697
+ - **Contrat** (`api/`) : `STANDARD_COMMAND_IDS`, `PARAGRAPH_LAYOUT_ATTR_NAMES` et tous les types (`AsterEditor`, `AsterOptions`, `AsterCommand`, `CommandRegistry`, `AsterEvents`, `AsterDocument`, `AsterCounts`, `I18n`, `PasteTransformer`, `ToolbarConfig`, `AsterVariable`, `VariableSource`, `VariableStore`, `VariableValues`, `VariableResolver`, `VariableRenderMode`, `GetHtmlOptions`, et ceux de `layout.ts` : `DocumentLayout`, `PageSetup`, `PageMargins`, `PageDimensions`, `PageSizeName`, `PageOrientation`, `HeaderFooterSet`, `HeaderFooterContent`, `DefaultFont`, `ParagraphLayoutAttrs`, `ParagraphLayoutAttrName`, `BlockBorder`, `BorderSide`, `BorderStyle`, `RunLayoutAttrs`, `DecorationStyle`, `ListLayoutAttrs`, `OrderedListType`, `TableLayoutAttrs`, `CellLayoutAttrs`, `CellVerticalAlign`, `PageViewOptions`).
698
+ - **Commandes** : `MARK_COMMANDS`, `BLOCK_COMMANDS`, `LIST_COMMANDS`, `ALIGNMENT_COMMANDS`, `TABLE_COMMANDS`, `TEXT_STYLE_COMMANDS`, `HISTORY_COMMANDS`, `SEARCH_COMMANDS`, `SEARCH_COMMAND_IDS`, `VARIABLE_COMMANDS`, `FORMAT_PAINTER_COMMANDS`, `FORMAT_PAINTER_COMMAND_IDS`, `PARAGRAPH_LAYOUT_COMMANDS`, `TEXT_LAYOUT_COMMANDS`, `TEXT_LAYOUT_COMMAND_IDS`, `hasLayoutBlockInSelection`, `createLinkCommands(policy)`, `createImageCommands(policy, upload)`, `createStandardCommands(context)`, `defineStandardCommand(id, spec)`, `iconIdFor(id)`, `toImageAttributes`, `getSearchStorage`, `SEARCH_OPEN_EVENT`, `FORMAT_PAINTER_CHANGE_EVENT`.
699
+ - **Mise en page** : `ParagraphLayout`, `parseParagraphLayout`, `renderParagraphLayout`, `paragraphLayoutDeclarations`, `normalizeParagraphLayoutValue`, `parseLineHeight`, `DOCX_STYLE_ATTRIBUTE`, `KEEP_NEXT_ATTRIBUTE`, `PAGE_BREAK_BEFORE_ATTRIBUTE`, `BORDER_BETWEEN_ATTRIBUTE`, `RunLayout`, `AsterTextStyle`, `AsterHighlight`, `AsterUnderline`, `AsterStrike`, `RUN_CAPS`, `DECORATION_STYLES`, `isCaps`, `isDecorationStyle`, `parseCaps`, `parseDecorationStyle`, `normalizeStyleColors`, `DOCX_RUN_STYLE_ATTRIBUTE`, `ListLayout`, `DOCX_NUM_ID_ATTRIBUTE`, `BULLET_ATTRIBUTE`, `DOCX_NUM_INDENT_ATTRIBUTE`, `AsterTable`, `AsterTableCell`, `AsterTableHeader`, `AsterTableView`, `createTableExtensions`, `MAX_COLSPAN`, `MAX_ROWSPAN`, `parseSpan`, `parseTableWidth`, `parseCellPadding`, `tableLayoutDeclarations`, `cellLayoutDeclarations` (`AsterHorizontalRule` n'est pas exporté : il est câblé par `createAsterExtensions`), et les helpers CSS de `layout-css` (`normalizeColor`, `parsePt`, `formatPt`, `parseStyleDeclarations`, `sanitizeBorders`, `borderDeclarations`, `isLayoutNumber`, `LAYOUT_NUMBER_LIMIT`…).
700
+ - **Vue page et pagination** : `applyPageView`, `resolvePageMetrics`, `pageViewCssValues`, `sanitizeHeaderFooterHtml`, `getActivePageView`, `PAGE_VIEW_CLASS`, `PAGE_HEADER_CLASS`, `PAGE_FOOTER_CLASS`, `PAGE_VIEW_CSS_VARIABLES`, `PAGE_SIZES_MM`, `DEFAULT_PAGE_MARGIN_MM`, `PAGE_VIEW_CHANGE_EVENT`, `Pagination`, `getPaginationResult`, `paginateNow`, `measureBlocks`, `measurePagination`, `usablePageHeightPx`, `isPaginationEnabled`, `paginate`, `samePagination`, `cssLengthToPx`, `MM_TO_PX`, `EMPTY_PAGINATION`, `PAGE_GAP_CLASS`, `PAGE_GAP_NUMBER_CLASS`, `PAGE_NUMBER_ATTRIBUTE`, `PAGE_COUNT_ATTRIBUTE`, `PAGE_COUNT_CSS_VARIABLE`, `PAGE_GAP_FILL_CSS_VARIABLE`, `PAGINATION_DEBOUNCE_MS`, `paginationPluginKey`, types `PageMetrics`, `PageViewHandle`, `PaginationResult`, `PageGap`, `PaginatedPageViewOptions`.
701
+ - **Sérialisation** : `serializeDocumentHtml`, `createRawStyleSerializer`, `renderRawSpec`, `SUSPICIOUS_SPEC_MESSAGE`, `normalizeOutputHtml`.
603
702
  - **Recherche** : `Search`, `findMatches`, `searchPluginKey`, `SEARCH_EXTENSION_NAME`, `SEARCH_MATCH_CLASS`, `SEARCH_CURRENT_CLASS`.
604
703
  - **Variables** : `Variable`, `createVariableStore`, `resolveVariablesHtml`, `findVariableAtSelection`, `isValidVariableName`, `variablePlaceholder`, `VARIABLE_EDIT_EVENT`, `VARIABLE_SELECTOR` et le reste de la liste de la section « Variables de document ».
605
704
  - **Sommaire et pinceau** : `Outline`, `getOutline`, `scrollToHeading`, `ensureHeadingIds`, `headingIdNumber`, `HEADING_ID_PREFIX`, `OUTLINE_EXTENSION_NAME`, `getFormatClipboard`, `hasFormatClipboard`, `clearFormatClipboard`, `readFormat`, `applyFormat`, `wordRangeAt`.
@@ -608,4 +707,4 @@ Tout ce qui suit est dans `packages/core/src/index.ts` :
608
707
  - **i18n et registre** : `createCommandRegistry(editor)`, `createI18n(locale, editor)`, `interpolate(template, params)`, `fr`, `en`, `FALLBACK_LOCALE`.
609
708
  - **Liens et images** : `DEFAULT_LINK_POLICY`, `resolveLinkPolicy`, `createLinkExtension`, `extractScheme`, `isAllowedHref`, `isAllowedImageSrc`, `createImageExtension`, `ImageNodeView`, `renderImageNodeView`, `parseImageWidth`, `clampImageWidth`, `isImageAlignment`, `IMAGE_ALIGNMENTS`, `IMAGE_CLASS`, `IMAGE_SELECTED_CLASS`, `IMAGE_HANDLE_CLASS`, `IMAGE_EDIT_EVENT`, `IMAGE_MIN_WIDTH`, `IMAGE_DEFAULT_DRAG_WIDTH`.
610
709
  - **Upload et collage** : `isImageFile`, `readFileAsDataUrl`, `insertImageFile`, `collectImageFiles`, `createImageUploadProps`, `applyPasteTransformers`, `createPastePipelineProps`.
611
- - **Raccourcis et assemblage** : `EXTRA_SHORTCUT_BINDINGS`, `collectShortcutBindings`, `createShortcutsExtension`, `createAsterExtensions`, `normalizeOutputHtml`, `CONTENT_CLASS`.
710
+ - **Raccourcis et assemblage** : `EXTRA_SHORTCUT_BINDINGS`, `collectShortcutBindings`, `createShortcutsExtension`, `createAsterExtensions`, `CONTENT_CLASS`.
@@ -1,10 +1,11 @@
1
1
  import type { AsterEditor } from './editor';
2
+ import type { ParagraphLayoutAttrName, ParagraphLayoutAttrs } from './layout';
2
3
  /**
3
4
  * Identifiants des commandes standard fournies par le core. La toolbar et le wrapper
4
5
  * Angular s'appuient sur cette liste. Un identifiant pointé indique un domaine :
5
6
  * `table.insert`, `link.set`, `image.insert`.
6
7
  */
7
- export declare const STANDARD_COMMAND_IDS: readonly ["bold", "italic", "underline", "strike", "subscript", "superscript", "code", "highlight", "clearFormatting", "paragraph", "heading", "blockquote", "codeBlock", "horizontalRule", "hardBreak", "bulletList", "orderedList", "taskList", "indent", "outdent", "alignLeft", "alignCenter", "alignRight", "alignJustify", "link.set", "link.unset", "image.insert", "image.upload", "image.setAttributes", "table.insert", "table.delete", "table.addRowBefore", "table.addRowAfter", "table.deleteRow", "table.addColumnBefore", "table.addColumnAfter", "table.deleteColumn", "table.mergeCells", "table.splitCell", "table.toggleHeaderRow", "table.toggleHeaderColumn", "textColor", "backgroundColor", "fontFamily", "fontSize", "variable.insert", "variable.remove", "undo", "redo", "selectAll"];
8
+ export declare const STANDARD_COMMAND_IDS: readonly ["bold", "italic", "underline", "strike", "subscript", "superscript", "code", "highlight", "clearFormatting", "paragraph", "heading", "blockquote", "codeBlock", "horizontalRule", "hardBreak", "bulletList", "orderedList", "taskList", "indent", "outdent", "alignLeft", "alignCenter", "alignRight", "alignJustify", "link.set", "link.unset", "image.insert", "image.upload", "image.setAttributes", "table.insert", "table.delete", "table.addRowBefore", "table.addRowAfter", "table.deleteRow", "table.addColumnBefore", "table.addColumnAfter", "table.deleteColumn", "table.mergeCells", "table.splitCell", "table.toggleHeaderRow", "table.toggleHeaderColumn", "textColor", "backgroundColor", "fontFamily", "fontSize", "variable.insert", "variable.remove", "paragraph.setLayout", "paragraph.unsetLayout", "undo", "redo", "selectAll"];
8
9
  export type StandardCommandId = (typeof STANDARD_COMMAND_IDS)[number];
9
10
  /** Identifiant de commande : standard ou custom. */
10
11
  export type CommandId = StandardCommandId | (string & {});
@@ -58,6 +59,12 @@ export interface StandardCommandArgs {
58
59
  name: string;
59
60
  label?: string;
60
61
  };
62
+ /** Fusionne les attributs donnés dans les paragraphes et titres de la sélection ; `null` efface un attribut. */
63
+ 'paragraph.setLayout': ParagraphLayoutAttrs;
64
+ /** Efface les attributs nommés, ou tous sans argument. */
65
+ 'paragraph.unsetLayout': {
66
+ attrs?: readonly ParagraphLayoutAttrName[];
67
+ } | undefined;
61
68
  }
62
69
  /** Type d'argument d'une commande standard, `undefined` si elle n'en prend pas. */
63
70
  export type CommandArgs<K extends CommandId> = K extends keyof StandardCommandArgs ? StandardCommandArgs[K] : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/api/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/api/commands.ts"],"names":[],"mappings":"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"}
@@ -60,6 +60,9 @@ export const STANDARD_COMMAND_IDS = [
60
60
  // Variables (champs de fusion)
61
61
  'variable.insert',
62
62
  'variable.remove',
63
+ // Mise en page des paragraphes (session 3)
64
+ 'paragraph.setLayout',
65
+ 'paragraph.unsetLayout',
63
66
  // Historique et divers
64
67
  'undo',
65
68
  'redo',
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/api/commands.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,WAAW;IACX,aAAa;IACb,MAAM;IACN,WAAW;IACX,iBAAiB;IACjB,QAAQ;IACR,WAAW;IACX,SAAS;IACT,YAAY;IACZ,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,SAAS;IACT,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,SAAS;IACT,aAAa;IACb,WAAW;IACX,aAAa;IACb,YAAY;IACZ,cAAc;IACd,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,SAAS;IACT,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,SAAS;IACT,cAAc;IACd,cAAc;IACd,oBAAoB;IACpB,mBAAmB;IACnB,iBAAiB;IACjB,uBAAuB;IACvB,sBAAsB;IACtB,oBAAoB;IACpB,kBAAkB;IAClB,iBAAiB;IACjB,uBAAuB;IACvB,0BAA0B;IAC1B,iBAAiB;IACjB,WAAW;IACX,iBAAiB;IACjB,YAAY;IACZ,UAAU;IACV,+BAA+B;IAC/B,iBAAiB;IACjB,iBAAiB;IACjB,uBAAuB;IACvB,MAAM;IACN,MAAM;IACN,WAAW;CACH,CAAC"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/api/commands.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,WAAW;IACX,aAAa;IACb,MAAM;IACN,WAAW;IACX,iBAAiB;IACjB,QAAQ;IACR,WAAW;IACX,SAAS;IACT,YAAY;IACZ,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,SAAS;IACT,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,SAAS;IACT,aAAa;IACb,WAAW;IACX,aAAa;IACb,YAAY;IACZ,cAAc;IACd,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,SAAS;IACT,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,SAAS;IACT,cAAc;IACd,cAAc;IACd,oBAAoB;IACpB,mBAAmB;IACnB,iBAAiB;IACjB,uBAAuB;IACvB,sBAAsB;IACtB,oBAAoB;IACpB,kBAAkB;IAClB,iBAAiB;IACjB,uBAAuB;IACvB,0BAA0B;IAC1B,iBAAiB;IACjB,WAAW;IACX,iBAAiB;IACjB,YAAY;IACZ,UAAU;IACV,+BAA+B;IAC/B,iBAAiB;IACjB,iBAAiB;IACjB,2CAA2C;IAC3C,qBAAqB;IACrB,uBAAuB;IACvB,uBAAuB;IACvB,MAAM;IACN,MAAM;IACN,WAAW;CACH,CAAC"}
@@ -9,6 +9,8 @@ export type { AsterEditor } from './editor';
9
9
  export type { AsterEventName, AsterEvents, Unsubscribe } from './events';
10
10
  export type { AsterDictionary, AsterLocale, I18n, TranslateParams } from './i18n';
11
11
  export type { AsterOptions, LinkPolicy, UploadHandler } from './options';
12
+ export type { BlockBorder, BorderSide, BorderStyle, CellLayoutAttrs, CellVerticalAlign, DecorationStyle, DefaultFont, DocumentLayout, HeaderFooterContent, HeaderFooterSet, ListLayoutAttrs, OrderedListType, PageDimensions, PageMargins, PageOrientation, PageSetup, PageSizeName, PageViewOptions, ParagraphLayoutAttrName, ParagraphLayoutAttrs, RunLayoutAttrs, TableLayoutAttrs, } from './layout';
13
+ export { PARAGRAPH_LAYOUT_ATTR_NAMES } from './layout';
12
14
  export type { PasteContext, PasteTransformer } from './paste';
13
15
  export type { AsterVariable, GetHtmlOptions, VariableRenderMode, VariableResolver, VariableSource, VariableStore, VariableValues, } from './variables';
14
16
  export type { AsterTheme, ToolbarButtonItem, ToolbarConfig, ToolbarDropdownItem, ToolbarGroup, ToolbarItem, ToolbarPreset, ToolbarWidgetItem, } from './toolbar';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,eAAe,EACf,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACzE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,eAAe,EACf,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACzE,YAAY,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,WAAW,EACX,eAAe,EACf,SAAS,EACT,YAAY,EACZ,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,cAAc,EACd,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
package/dist/api/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { STANDARD_COMMAND_IDS } from './commands';
2
+ export { PARAGRAPH_LAYOUT_ATTR_NAMES } from './layout';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA8BlD,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC"}