@aster-editor/core 0.4.2 → 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.
- package/README.md +191 -92
- package/dist/api/commands.d.ts +8 -1
- package/dist/api/commands.d.ts.map +1 -1
- package/dist/api/commands.js +3 -0
- package/dist/api/commands.js.map +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +1 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/layout.d.ts +181 -0
- package/dist/api/layout.d.ts.map +1 -0
- package/dist/api/layout.js +28 -0
- package/dist/api/layout.js.map +1 -0
- package/dist/api/options.d.ts +6 -0
- package/dist/api/options.d.ts.map +1 -1
- package/dist/commands/layout.d.ts +40 -0
- package/dist/commands/layout.d.ts.map +1 -0
- package/dist/commands/layout.js +262 -0
- package/dist/commands/layout.js.map +1 -0
- package/dist/commands/standard.d.ts +4 -3
- package/dist/commands/standard.d.ts.map +1 -1
- package/dist/commands/standard.js +7 -3
- package/dist/commands/standard.js.map +1 -1
- package/dist/editor/aster-editor.d.ts +16 -1
- package/dist/editor/aster-editor.d.ts.map +1 -1
- package/dist/editor/aster-editor.js +41 -1
- package/dist/editor/aster-editor.js.map +1 -1
- package/dist/extensions/aster-extensions.d.ts +3 -0
- package/dist/extensions/aster-extensions.d.ts.map +1 -1
- package/dist/extensions/aster-extensions.js +24 -5
- package/dist/extensions/aster-extensions.js.map +1 -1
- package/dist/extensions/header-footer-sanitize.d.ts +22 -0
- package/dist/extensions/header-footer-sanitize.d.ts.map +1 -0
- package/dist/extensions/header-footer-sanitize.js +226 -0
- package/dist/extensions/header-footer-sanitize.js.map +1 -0
- package/dist/extensions/layout-css.d.ts +88 -0
- package/dist/extensions/layout-css.d.ts.map +1 -0
- package/dist/extensions/layout-css.js +297 -0
- package/dist/extensions/layout-css.js.map +1 -0
- package/dist/extensions/list-layout.d.ts +23 -0
- package/dist/extensions/list-layout.d.ts.map +1 -0
- package/dist/extensions/list-layout.js +65 -0
- package/dist/extensions/list-layout.js.map +1 -0
- package/dist/extensions/page-break.d.ts +8 -0
- package/dist/extensions/page-break.d.ts.map +1 -0
- package/dist/extensions/page-break.js +20 -0
- package/dist/extensions/page-break.js.map +1 -0
- package/dist/extensions/page-view.d.ts +68 -0
- package/dist/extensions/page-view.d.ts.map +1 -0
- package/dist/extensions/page-view.js +189 -0
- package/dist/extensions/page-view.js.map +1 -0
- package/dist/extensions/pagination-controller.d.ts +110 -0
- package/dist/extensions/pagination-controller.d.ts.map +1 -0
- package/dist/extensions/pagination-controller.js +295 -0
- package/dist/extensions/pagination-controller.js.map +1 -0
- package/dist/extensions/pagination-layout.d.ts +54 -0
- package/dist/extensions/pagination-layout.d.ts.map +1 -0
- package/dist/extensions/pagination-layout.js +109 -0
- package/dist/extensions/pagination-layout.js.map +1 -0
- package/dist/extensions/pagination-measure.d.ts +42 -0
- package/dist/extensions/pagination-measure.d.ts.map +1 -0
- package/dist/extensions/pagination-measure.js +108 -0
- package/dist/extensions/pagination-measure.js.map +1 -0
- package/dist/extensions/pagination.d.ts +36 -0
- package/dist/extensions/pagination.d.ts.map +1 -0
- package/dist/extensions/pagination.js +69 -0
- package/dist/extensions/pagination.js.map +1 -0
- package/dist/extensions/paragraph-layout.d.ts +62 -0
- package/dist/extensions/paragraph-layout.d.ts.map +1 -0
- package/dist/extensions/paragraph-layout.js +227 -0
- package/dist/extensions/paragraph-layout.js.map +1 -0
- package/dist/extensions/run-layout.d.ts +79 -0
- package/dist/extensions/run-layout.d.ts.map +1 -0
- package/dist/extensions/run-layout.js +302 -0
- package/dist/extensions/run-layout.js.map +1 -0
- package/dist/extensions/table-layout.d.ts +85 -0
- package/dist/extensions/table-layout.d.ts.map +1 -0
- package/dist/extensions/table-layout.js +314 -0
- package/dist/extensions/table-layout.js.map +1 -0
- package/dist/html/serialize-html.d.ts +42 -0
- package/dist/html/serialize-html.d.ts.map +1 -0
- package/dist/html/serialize-html.js +159 -0
- package/dist/html/serialize-html.js.map +1 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +8 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/fr.d.ts.map +1 -1
- package/dist/i18n/fr.js +8 -0
- package/dist/i18n/fr.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calcul pur de la pagination approximative (session 3, lot L30) : aucune dépendance au
|
|
3
|
+
* DOM, testable seul. Le plugin `pagination.ts` mesure les blocs rendus et appelle
|
|
4
|
+
* `paginate` ; ce fichier ne connaît que des hauteurs en pixels.
|
|
5
|
+
*
|
|
6
|
+
* Modèle : chaque bloc de premier niveau est **insécable** (paragraphe, titre, liste,
|
|
7
|
+
* tableau, image…). Un bloc qui ne tient pas dans le reste de la page passe entier à la
|
|
8
|
+
* page suivante ; un bloc plus haut qu'une page occupe sa page seul et la déborde. C'est
|
|
9
|
+
* une approximation assumée (Word coupe les paragraphes et les tableaux ligne à ligne).
|
|
10
|
+
*/
|
|
11
|
+
/** Pixels CSS par millimètre : 1 in = 96 px = 25,4 mm, valeur exacte de la spécification CSS. */
|
|
12
|
+
export declare const MM_TO_PX: number;
|
|
13
|
+
/**
|
|
14
|
+
* Convertit une longueur CSS absolue (`297mm`, `11in`, `72pt`, `120px`, `0`) en pixels CSS.
|
|
15
|
+
* `null` pour une valeur vide, relative (`em`, `%`, `vh`…) ou illisible : l'appelant
|
|
16
|
+
* retombe alors sur les métriques résolues depuis `DocumentLayout`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function cssLengthToPx(value: string): number | null;
|
|
19
|
+
/** Une coupure de page : posée **avant** le bloc d'index `index`. */
|
|
20
|
+
export interface PageGap {
|
|
21
|
+
/** Index du bloc de premier niveau qui ouvre la nouvelle page. */
|
|
22
|
+
readonly index: number;
|
|
23
|
+
/** Numéro (1-based) de la page qui commence après la coupure. */
|
|
24
|
+
readonly page: number;
|
|
25
|
+
/** Espace resté libre en bas de la page précédente, en px (jamais négatif). */
|
|
26
|
+
readonly fill: number;
|
|
27
|
+
}
|
|
28
|
+
/** Résultat d'une pagination : coupures dans l'ordre et nombre total de pages. */
|
|
29
|
+
export interface PaginationResult {
|
|
30
|
+
readonly gaps: readonly PageGap[];
|
|
31
|
+
readonly pageCount: number;
|
|
32
|
+
}
|
|
33
|
+
/** Résultat d'un document d'une seule page (ou d'une pagination inactive). */
|
|
34
|
+
export declare const EMPTY_PAGINATION: PaginationResult;
|
|
35
|
+
/**
|
|
36
|
+
* Répartit des blocs insécables sur des pages de hauteur utile `pageHeight` (px).
|
|
37
|
+
*
|
|
38
|
+
* - `heights[i]` : hauteur rendue du bloc `i`, marges comprises.
|
|
39
|
+
* - `breaks` : index des blocs devant lesquels une coupure est **forcée** (saut de page
|
|
40
|
+
* explicite, `pageBreakBefore`). Un index hors plage ou `0` est ignoré : la première
|
|
41
|
+
* page existe toujours, une coupure forcée en tête ne crée pas de page vide avant elle.
|
|
42
|
+
*
|
|
43
|
+
* Règles : un bloc qui dépasserait la page passe entier à la suivante, sauf s'il est le
|
|
44
|
+
* premier de sa page (il la déborde alors, seul). Un bloc de hauteur nulle (saut de page
|
|
45
|
+
* explicite, remplacé visuellement par la coupure, R30-01) n'ouvre jamais de page à lui
|
|
46
|
+
* seul, même après un bloc qui déborde : il reste sur la page courante et la coupure
|
|
47
|
+
* forcée qui le suit fait le travail. Une coupure forcée remet le compteur à zéro même
|
|
48
|
+
* si la page courante est vide (deux sauts consécutifs = une page vide, comme Word).
|
|
49
|
+
* `pageHeight` nulle, négative ou infinie : une seule page, aucune coupure.
|
|
50
|
+
*/
|
|
51
|
+
export declare function paginate(heights: readonly number[], pageHeight: number, breaks?: ReadonlySet<number> | readonly number[]): PaginationResult;
|
|
52
|
+
/** Vrai si deux résultats décrivent les mêmes coupures (au pixel près pour `fill`). */
|
|
53
|
+
export declare function samePagination(a: PaginationResult, b: PaginationResult): boolean;
|
|
54
|
+
//# sourceMappingURL=pagination-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-layout.d.ts","sourceRoot":"","sources":["../../src/extensions/pagination-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iGAAiG;AACjG,eAAO,MAAM,QAAQ,QAAY,CAAC;AAkBlC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe1D;AAED,qEAAqE;AACrE,MAAM,WAAW,OAAO;IACtB,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,gBAG7B,CAAC;AAOH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,MAAM,EAAO,GACnD,gBAAgB,CAoBlB;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAgBhF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calcul pur de la pagination approximative (session 3, lot L30) : aucune dépendance au
|
|
3
|
+
* DOM, testable seul. Le plugin `pagination.ts` mesure les blocs rendus et appelle
|
|
4
|
+
* `paginate` ; ce fichier ne connaît que des hauteurs en pixels.
|
|
5
|
+
*
|
|
6
|
+
* Modèle : chaque bloc de premier niveau est **insécable** (paragraphe, titre, liste,
|
|
7
|
+
* tableau, image…). Un bloc qui ne tient pas dans le reste de la page passe entier à la
|
|
8
|
+
* page suivante ; un bloc plus haut qu'une page occupe sa page seul et la déborde. C'est
|
|
9
|
+
* une approximation assumée (Word coupe les paragraphes et les tableaux ligne à ligne).
|
|
10
|
+
*/
|
|
11
|
+
/** Pixels CSS par millimètre : 1 in = 96 px = 25,4 mm, valeur exacte de la spécification CSS. */
|
|
12
|
+
export const MM_TO_PX = 96 / 25.4;
|
|
13
|
+
/** Tolérance de comparaison des hauteurs, en px : absorbe les arrondis sous-pixel du rendu. */
|
|
14
|
+
const HEIGHT_EPSILON = 0.5;
|
|
15
|
+
/** Facteur px par unité pour les longueurs CSS absolues. */
|
|
16
|
+
const CSS_UNIT_TO_PX = {
|
|
17
|
+
px: 1,
|
|
18
|
+
mm: MM_TO_PX,
|
|
19
|
+
cm: MM_TO_PX * 10,
|
|
20
|
+
q: MM_TO_PX / 4,
|
|
21
|
+
in: 96,
|
|
22
|
+
pt: 96 / 72,
|
|
23
|
+
pc: 16,
|
|
24
|
+
};
|
|
25
|
+
const CSS_LENGTH_PATTERN = /^\s*([+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)\s*([a-z]*)\s*$/i;
|
|
26
|
+
/**
|
|
27
|
+
* Convertit une longueur CSS absolue (`297mm`, `11in`, `72pt`, `120px`, `0`) en pixels CSS.
|
|
28
|
+
* `null` pour une valeur vide, relative (`em`, `%`, `vh`…) ou illisible : l'appelant
|
|
29
|
+
* retombe alors sur les métriques résolues depuis `DocumentLayout`.
|
|
30
|
+
*/
|
|
31
|
+
export function cssLengthToPx(value) {
|
|
32
|
+
const match = CSS_LENGTH_PATTERN.exec(value);
|
|
33
|
+
if (!match || match[1] === undefined) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const amount = Number.parseFloat(match[1]);
|
|
37
|
+
if (!Number.isFinite(amount)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const unit = (match[2] ?? '').toLowerCase();
|
|
41
|
+
if (unit === '') {
|
|
42
|
+
return amount === 0 ? 0 : null;
|
|
43
|
+
}
|
|
44
|
+
const factor = CSS_UNIT_TO_PX[unit];
|
|
45
|
+
return factor === undefined ? null : amount * factor;
|
|
46
|
+
}
|
|
47
|
+
/** Résultat d'un document d'une seule page (ou d'une pagination inactive). */
|
|
48
|
+
export const EMPTY_PAGINATION = Object.freeze({
|
|
49
|
+
gaps: Object.freeze([]),
|
|
50
|
+
pageCount: 1,
|
|
51
|
+
});
|
|
52
|
+
/** Hauteur finie et positive ou nulle ; `NaN`, `Infinity` et négatifs comptent pour 0. */
|
|
53
|
+
function sanitizeHeight(value) {
|
|
54
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Répartit des blocs insécables sur des pages de hauteur utile `pageHeight` (px).
|
|
58
|
+
*
|
|
59
|
+
* - `heights[i]` : hauteur rendue du bloc `i`, marges comprises.
|
|
60
|
+
* - `breaks` : index des blocs devant lesquels une coupure est **forcée** (saut de page
|
|
61
|
+
* explicite, `pageBreakBefore`). Un index hors plage ou `0` est ignoré : la première
|
|
62
|
+
* page existe toujours, une coupure forcée en tête ne crée pas de page vide avant elle.
|
|
63
|
+
*
|
|
64
|
+
* Règles : un bloc qui dépasserait la page passe entier à la suivante, sauf s'il est le
|
|
65
|
+
* premier de sa page (il la déborde alors, seul). Un bloc de hauteur nulle (saut de page
|
|
66
|
+
* explicite, remplacé visuellement par la coupure, R30-01) n'ouvre jamais de page à lui
|
|
67
|
+
* seul, même après un bloc qui déborde : il reste sur la page courante et la coupure
|
|
68
|
+
* forcée qui le suit fait le travail. Une coupure forcée remet le compteur à zéro même
|
|
69
|
+
* si la page courante est vide (deux sauts consécutifs = une page vide, comme Word).
|
|
70
|
+
* `pageHeight` nulle, négative ou infinie : une seule page, aucune coupure.
|
|
71
|
+
*/
|
|
72
|
+
export function paginate(heights, pageHeight, breaks = []) {
|
|
73
|
+
if (!Number.isFinite(pageHeight) || pageHeight <= 0 || heights.length === 0) {
|
|
74
|
+
return EMPTY_PAGINATION;
|
|
75
|
+
}
|
|
76
|
+
const forced = breaks instanceof Set ? breaks : new Set(breaks);
|
|
77
|
+
const gaps = [];
|
|
78
|
+
let used = 0;
|
|
79
|
+
let page = 1;
|
|
80
|
+
for (let index = 0; index < heights.length; index += 1) {
|
|
81
|
+
const height = sanitizeHeight(heights[index]);
|
|
82
|
+
const forcedHere = index > 0 && forced.has(index);
|
|
83
|
+
const overflows = used > 0 && height > 0 && used + height > pageHeight + HEIGHT_EPSILON;
|
|
84
|
+
if (forcedHere || overflows) {
|
|
85
|
+
page += 1;
|
|
86
|
+
gaps.push({ index, page, fill: Math.max(0, pageHeight - used) });
|
|
87
|
+
used = 0;
|
|
88
|
+
}
|
|
89
|
+
used += height;
|
|
90
|
+
}
|
|
91
|
+
return gaps.length === 0 ? EMPTY_PAGINATION : { gaps, pageCount: page };
|
|
92
|
+
}
|
|
93
|
+
/** Vrai si deux résultats décrivent les mêmes coupures (au pixel près pour `fill`). */
|
|
94
|
+
export function samePagination(a, b) {
|
|
95
|
+
if (a === b) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (a.pageCount !== b.pageCount || a.gaps.length !== b.gaps.length) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return a.gaps.every((gap, position) => {
|
|
102
|
+
const other = b.gaps[position];
|
|
103
|
+
return (other !== undefined &&
|
|
104
|
+
gap.index === other.index &&
|
|
105
|
+
gap.page === other.page &&
|
|
106
|
+
Math.round(gap.fill) === Math.round(other.fill));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=pagination-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-layout.js","sourceRoot":"","sources":["../../src/extensions/pagination-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { EditorView } from '@tiptap/pm/view';
|
|
2
|
+
import type { PageViewOptions } from '../api';
|
|
3
|
+
import { type PaginationResult } from './pagination-layout';
|
|
4
|
+
/**
|
|
5
|
+
* Phase de **mesure** de la pagination approximative (session 3, L30, extrait de
|
|
6
|
+
* `pagination.ts` en F30) : hauteur utile de la page depuis l'hôte, hauteurs rendues des
|
|
7
|
+
* blocs de premier niveau depuis le DOM, puis calcul pur (`pagination-layout.ts`). Aucune
|
|
8
|
+
* écriture dans le DOM ici ; le contrôleur (`pagination-controller.ts`) planifie et pose.
|
|
9
|
+
*/
|
|
10
|
+
/** Classe du widget de coupure de page posé avant le bloc qui ouvre une page. */
|
|
11
|
+
export declare const PAGE_GAP_CLASS = "aster-page-gap";
|
|
12
|
+
/**
|
|
13
|
+
* Hauteur utile d'une page en px : hauteur moins marges haute et basse, lues dans les
|
|
14
|
+
* variables `--aster-page-*` de l'hôte (calculées, puis inline), sinon depuis la mise en
|
|
15
|
+
* page résolue. Conversion mm → px exacte (96 / 25,4), pas d'élément témoin : les
|
|
16
|
+
* rectangles mesurés sont eux aussi en px CSS, quel que soit le zoom.
|
|
17
|
+
*/
|
|
18
|
+
export declare function usablePageHeightPx(host: HTMLElement | null, options: PageViewOptions): number;
|
|
19
|
+
/** Hauteurs mesurées des blocs de premier niveau et index des coupures forcées. */
|
|
20
|
+
export interface MeasuredBlocks {
|
|
21
|
+
readonly heights: readonly number[];
|
|
22
|
+
readonly breaks: ReadonlySet<number>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Mesure chaque bloc de premier niveau, en lot : d'abord l'alignement DOM / document,
|
|
26
|
+
* puis toutes les lectures de rectangles, aucune écriture. La hauteur d'un bloc va de son
|
|
27
|
+
* haut au haut du suivant (ou de la coupure déjà posée entre eux), marges comprises ; le
|
|
28
|
+
* dernier bloc prend la hauteur de son rectangle.
|
|
29
|
+
*
|
|
30
|
+
* Un saut de page explicite mesure **0** (R30-01) : `page.css` le rend haut tant qu'aucune
|
|
31
|
+
* coupure ne le suit, puis l'efface derrière elle (`hr:has(+ .aster-page-gap)`). Le
|
|
32
|
+
* compter ferait déborder la page au premier rendu (page vide) et fausserait le
|
|
33
|
+
* remplissage de la coupure jusqu'à la frappe suivante.
|
|
34
|
+
*
|
|
35
|
+
* Alignement : les enfants directs de `view.dom` qui ne sont pas des widgets sont, dans
|
|
36
|
+
* l'ordre, les DOM des enfants du document. Si le compte diffère (DOM d'un intégrateur),
|
|
37
|
+
* on retombe sur `view.nodeDOM` bloc par bloc, plus lent mais sûr.
|
|
38
|
+
*/
|
|
39
|
+
export declare function measureBlocks(view: EditorView): MeasuredBlocks;
|
|
40
|
+
/** Mesure puis pagine la vue : hauteur utile depuis l'hôte, hauteurs depuis le DOM. */
|
|
41
|
+
export declare function measurePagination(view: EditorView, options: PageViewOptions): PaginationResult;
|
|
42
|
+
//# sourceMappingURL=pagination-measure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-measure.d.ts","sourceRoot":"","sources":["../../src/extensions/pagination-measure.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAqC,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE/F;;;;;GAKG;AAEH,iFAAiF;AACjF,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAc/C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAiB7F;AAED,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,CA2C9D;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,GAAG,gBAAgB,CAK9F"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { PAGE_VIEW_CLASS, resolvePageMetrics } from './page-view';
|
|
2
|
+
import { MM_TO_PX, cssLengthToPx, paginate } from './pagination-layout';
|
|
3
|
+
/**
|
|
4
|
+
* Phase de **mesure** de la pagination approximative (session 3, L30, extrait de
|
|
5
|
+
* `pagination.ts` en F30) : hauteur utile de la page depuis l'hôte, hauteurs rendues des
|
|
6
|
+
* blocs de premier niveau depuis le DOM, puis calcul pur (`pagination-layout.ts`). Aucune
|
|
7
|
+
* écriture dans le DOM ici ; le contrôleur (`pagination-controller.ts`) planifie et pose.
|
|
8
|
+
*/
|
|
9
|
+
/** Classe du widget de coupure de page posé avant le bloc qui ouvre une page. */
|
|
10
|
+
export const PAGE_GAP_CLASS = 'aster-page-gap';
|
|
11
|
+
/** Classe posée par ProseMirror sur tout widget de décoration (exclu de l'alignement DOM / doc). */
|
|
12
|
+
const PROSEMIRROR_WIDGET_CLASS = 'ProseMirror-widget';
|
|
13
|
+
/** Nom du nœud de saut de page d'un intégrateur (`slash-menu` le propose s'il existe). */
|
|
14
|
+
const PAGE_BREAK_NODE_NAME = 'pageBreak';
|
|
15
|
+
/** Vrai pour un saut de page explicite : `<hr data-page-break>` ou nœud `pageBreak` d'un intégrateur. */
|
|
16
|
+
function isExplicitPageBreak(node) {
|
|
17
|
+
if (node.type.name === PAGE_BREAK_NODE_NAME) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return node.type.name === 'horizontalRule' && node.attrs['pageBreak'] === true;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Hauteur utile d'une page en px : hauteur moins marges haute et basse, lues dans les
|
|
24
|
+
* variables `--aster-page-*` de l'hôte (calculées, puis inline), sinon depuis la mise en
|
|
25
|
+
* page résolue. Conversion mm → px exacte (96 / 25,4), pas d'élément témoin : les
|
|
26
|
+
* rectangles mesurés sont eux aussi en px CSS, quel que soit le zoom.
|
|
27
|
+
*/
|
|
28
|
+
export function usablePageHeightPx(host, options) {
|
|
29
|
+
const metrics = resolvePageMetrics(options.layout);
|
|
30
|
+
const computed = host && typeof getComputedStyle === 'function' ? getComputedStyle(host) : null;
|
|
31
|
+
const read = (name, fallbackMm) => {
|
|
32
|
+
const raw = (computed?.getPropertyValue(name) ||
|
|
33
|
+
host?.style.getPropertyValue(name) ||
|
|
34
|
+
'').trim();
|
|
35
|
+
const px = raw === '' ? null : cssLengthToPx(raw);
|
|
36
|
+
return px ?? fallbackMm * MM_TO_PX;
|
|
37
|
+
};
|
|
38
|
+
return (read('--aster-page-height', metrics.heightMm) -
|
|
39
|
+
read('--aster-page-margin-top', metrics.marginTopMm) -
|
|
40
|
+
read('--aster-page-margin-bottom', metrics.marginBottomMm));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Mesure chaque bloc de premier niveau, en lot : d'abord l'alignement DOM / document,
|
|
44
|
+
* puis toutes les lectures de rectangles, aucune écriture. La hauteur d'un bloc va de son
|
|
45
|
+
* haut au haut du suivant (ou de la coupure déjà posée entre eux), marges comprises ; le
|
|
46
|
+
* dernier bloc prend la hauteur de son rectangle.
|
|
47
|
+
*
|
|
48
|
+
* Un saut de page explicite mesure **0** (R30-01) : `page.css` le rend haut tant qu'aucune
|
|
49
|
+
* coupure ne le suit, puis l'efface derrière elle (`hr:has(+ .aster-page-gap)`). Le
|
|
50
|
+
* compter ferait déborder la page au premier rendu (page vide) et fausserait le
|
|
51
|
+
* remplissage de la coupure jusqu'à la frappe suivante.
|
|
52
|
+
*
|
|
53
|
+
* Alignement : les enfants directs de `view.dom` qui ne sont pas des widgets sont, dans
|
|
54
|
+
* l'ordre, les DOM des enfants du document. Si le compte diffère (DOM d'un intégrateur),
|
|
55
|
+
* on retombe sur `view.nodeDOM` bloc par bloc, plus lent mais sûr.
|
|
56
|
+
*/
|
|
57
|
+
export function measureBlocks(view) {
|
|
58
|
+
const { doc } = view.state;
|
|
59
|
+
const count = doc.childCount;
|
|
60
|
+
const domChildren = [];
|
|
61
|
+
const gapsBefore = new Map();
|
|
62
|
+
for (const child of Array.from(view.dom.children)) {
|
|
63
|
+
if (child.classList.contains(PAGE_GAP_CLASS)) {
|
|
64
|
+
gapsBefore.set(domChildren.length, child);
|
|
65
|
+
}
|
|
66
|
+
else if (!child.classList.contains(PROSEMIRROR_WIDGET_CLASS)) {
|
|
67
|
+
domChildren.push(child);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const aligned = domChildren.length === count;
|
|
71
|
+
const breaks = new Set();
|
|
72
|
+
const explicitBreaks = new Set();
|
|
73
|
+
const blocks = [];
|
|
74
|
+
doc.forEach((node, offset, index) => {
|
|
75
|
+
if (isExplicitPageBreak(node)) {
|
|
76
|
+
explicitBreaks.add(index);
|
|
77
|
+
breaks.add(index + 1);
|
|
78
|
+
}
|
|
79
|
+
if (node.attrs['pageBreakBefore'] === true) {
|
|
80
|
+
breaks.add(index);
|
|
81
|
+
}
|
|
82
|
+
const dom = aligned ? domChildren[index] : view.nodeDOM(offset);
|
|
83
|
+
blocks.push(dom instanceof Element ? dom : null);
|
|
84
|
+
});
|
|
85
|
+
const rects = blocks.map((dom) => (dom ? dom.getBoundingClientRect() : null));
|
|
86
|
+
const gapTops = new Map();
|
|
87
|
+
if (aligned) {
|
|
88
|
+
for (const [index, gap] of gapsBefore) {
|
|
89
|
+
gapTops.set(index, gap.getBoundingClientRect().top);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const heights = rects.map((rect, index) => {
|
|
93
|
+
if (!rect || explicitBreaks.has(index)) {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
const bottom = gapTops.get(index + 1) ?? rects[index + 1]?.top ?? rect.bottom;
|
|
97
|
+
return Math.max(rect.height, bottom - rect.top);
|
|
98
|
+
});
|
|
99
|
+
return { heights, breaks };
|
|
100
|
+
}
|
|
101
|
+
/** Mesure puis pagine la vue : hauteur utile depuis l'hôte, hauteurs depuis le DOM. */
|
|
102
|
+
export function measurePagination(view, options) {
|
|
103
|
+
const host = view.dom.closest(`.${PAGE_VIEW_CLASS}`);
|
|
104
|
+
const pageHeight = usablePageHeightPx(host, options);
|
|
105
|
+
const { heights, breaks } = measureBlocks(view);
|
|
106
|
+
return paginate(heights, pageHeight, breaks);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=pagination-measure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-measure.js","sourceRoot":"","sources":["../../src/extensions/pagination-measure.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import type { AsterEditor } from '../api';
|
|
3
|
+
import { type PaginationResult } from './pagination-layout';
|
|
4
|
+
/**
|
|
5
|
+
* Extension `pagination` (session 3, L30) et son API publique. Le travail est réparti en
|
|
6
|
+
* trois fichiers (F30, R30-13) : `pagination-layout.ts` (calcul pur), `pagination-measure.ts`
|
|
7
|
+
* (hauteur utile et mesure du DOM) et `pagination-controller.ts` (vue du plugin, décorations).
|
|
8
|
+
* Tout est réexporté d'ici : les imports de `index.ts` et des intégrateurs ne changent pas.
|
|
9
|
+
*/
|
|
10
|
+
export { PAGE_COUNT_ATTRIBUTE, PAGE_COUNT_CSS_VARIABLE, PAGE_GAP_FILL_CSS_VARIABLE, PAGE_GAP_NUMBER_CLASS, PAGE_NUMBER_ATTRIBUTE, PAGINATION_DEBOUNCE_MS, isPaginationEnabled, paginationPluginKey, type PaginatedPageViewOptions, type PaginationDecorations, } from './pagination-controller';
|
|
11
|
+
export { PAGE_GAP_CLASS, measureBlocks, measurePagination, usablePageHeightPx, type MeasuredBlocks, } from './pagination-measure';
|
|
12
|
+
/** Nom de l'extension. */
|
|
13
|
+
export declare const PAGINATION_EXTENSION_NAME = "pagination";
|
|
14
|
+
/** Options de l'extension `Pagination`. */
|
|
15
|
+
export interface PaginationOptions {
|
|
16
|
+
/** Éditeur Aster propriétaire : i18n du libellé de page. `null` : libellé « Page n / N ». */
|
|
17
|
+
readonly aster: AsterEditor | null;
|
|
18
|
+
}
|
|
19
|
+
/** Dernière pagination calculée (coupures et nombre de pages) ; une page hors vue page. */
|
|
20
|
+
export declare function getPaginationResult(editor: AsterEditor): PaginationResult;
|
|
21
|
+
/**
|
|
22
|
+
* Mesure et pose les coupures tout de suite, sans attendre le débounce ni la frame : pour
|
|
23
|
+
* les tests et pour un intégrateur qui vient de changer la feuille de style. Résultat
|
|
24
|
+
* vide hors vue page ou avec `pagination: false`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function paginateNow(editor: AsterEditor): PaginationResult;
|
|
27
|
+
/**
|
|
28
|
+
* Extension `pagination` : pagination **approximative** de la vue page. Mesure la hauteur
|
|
29
|
+
* rendue des blocs de premier niveau et pose, en décorations widget (jamais dans le
|
|
30
|
+
* document), une coupure `div.aster-page-gap` avant chaque bloc qui ouvre une page. Les
|
|
31
|
+
* sauts de page explicites forcent la coupure ; tableaux et listes passent entiers à la
|
|
32
|
+
* page suivante. Inactive hors vue page ou avec `pagination: false`. Aucune promesse
|
|
33
|
+
* d'exactitude Word : la feuille `ui/themes/page.css` dessine, le core ne fait que mesurer.
|
|
34
|
+
*/
|
|
35
|
+
export declare const Pagination: Extension<PaginationOptions, any>;
|
|
36
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/extensions/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAQ1C,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE9E;;;;;GAKG;AAEH,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC;AAE9B,0BAA0B;AAC1B,eAAO,MAAM,yBAAyB,eAAe,CAAC;AAEtD,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAChC,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CACpC;AAUD,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAEjE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,mCA2BrB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import { Plugin } from '@tiptap/pm/state';
|
|
3
|
+
import { DecorationSet } from '@tiptap/pm/view';
|
|
4
|
+
import { PaginationController, initPaginationDecorations, mapPaginationDecorations, paginationControllerOf, paginationPluginKey, } from './pagination-controller';
|
|
5
|
+
import { EMPTY_PAGINATION } from './pagination-layout';
|
|
6
|
+
/**
|
|
7
|
+
* Extension `pagination` (session 3, L30) et son API publique. Le travail est réparti en
|
|
8
|
+
* trois fichiers (F30, R30-13) : `pagination-layout.ts` (calcul pur), `pagination-measure.ts`
|
|
9
|
+
* (hauteur utile et mesure du DOM) et `pagination-controller.ts` (vue du plugin, décorations).
|
|
10
|
+
* Tout est réexporté d'ici : les imports de `index.ts` et des intégrateurs ne changent pas.
|
|
11
|
+
*/
|
|
12
|
+
export { PAGE_COUNT_ATTRIBUTE, PAGE_COUNT_CSS_VARIABLE, PAGE_GAP_FILL_CSS_VARIABLE, PAGE_GAP_NUMBER_CLASS, PAGE_NUMBER_ATTRIBUTE, PAGINATION_DEBOUNCE_MS, isPaginationEnabled, paginationPluginKey, } from './pagination-controller';
|
|
13
|
+
export { PAGE_GAP_CLASS, measureBlocks, measurePagination, usablePageHeightPx, } from './pagination-measure';
|
|
14
|
+
/** Nom de l'extension. */
|
|
15
|
+
export const PAGINATION_EXTENSION_NAME = 'pagination';
|
|
16
|
+
/** Contrôleur de l'éditeur, `null` sans extension `Pagination` ou éditeur détruit. */
|
|
17
|
+
function controllerOf(editor) {
|
|
18
|
+
if (editor.isDestroyed()) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return paginationControllerOf(editor.tiptap.view);
|
|
22
|
+
}
|
|
23
|
+
/** Dernière pagination calculée (coupures et nombre de pages) ; une page hors vue page. */
|
|
24
|
+
export function getPaginationResult(editor) {
|
|
25
|
+
return controllerOf(editor)?.result ?? EMPTY_PAGINATION;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Mesure et pose les coupures tout de suite, sans attendre le débounce ni la frame : pour
|
|
29
|
+
* les tests et pour un intégrateur qui vient de changer la feuille de style. Résultat
|
|
30
|
+
* vide hors vue page ou avec `pagination: false`.
|
|
31
|
+
*/
|
|
32
|
+
export function paginateNow(editor) {
|
|
33
|
+
return controllerOf(editor)?.measureNow() ?? EMPTY_PAGINATION;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extension `pagination` : pagination **approximative** de la vue page. Mesure la hauteur
|
|
37
|
+
* rendue des blocs de premier niveau et pose, en décorations widget (jamais dans le
|
|
38
|
+
* document), une coupure `div.aster-page-gap` avant chaque bloc qui ouvre une page. Les
|
|
39
|
+
* sauts de page explicites forcent la coupure ; tableaux et listes passent entiers à la
|
|
40
|
+
* page suivante. Inactive hors vue page ou avec `pagination: false`. Aucune promesse
|
|
41
|
+
* d'exactitude Word : la feuille `ui/themes/page.css` dessine, le core ne fait que mesurer.
|
|
42
|
+
*/
|
|
43
|
+
export const Pagination = Extension.create({
|
|
44
|
+
name: PAGINATION_EXTENSION_NAME,
|
|
45
|
+
addOptions() {
|
|
46
|
+
return { aster: null };
|
|
47
|
+
},
|
|
48
|
+
addProseMirrorPlugins() {
|
|
49
|
+
const aster = this.options.aster;
|
|
50
|
+
let controller = null;
|
|
51
|
+
return [
|
|
52
|
+
new Plugin({
|
|
53
|
+
key: paginationPluginKey,
|
|
54
|
+
state: {
|
|
55
|
+
init: initPaginationDecorations,
|
|
56
|
+
apply: mapPaginationDecorations,
|
|
57
|
+
},
|
|
58
|
+
view: (view) => {
|
|
59
|
+
controller = new PaginationController(view, aster);
|
|
60
|
+
return controller;
|
|
61
|
+
},
|
|
62
|
+
props: {
|
|
63
|
+
decorations: (state) => controller?.decorationsFor(state) ?? DecorationSet.empty,
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
];
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/extensions/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAyB,MAAM,qBAAqB,CAAC;AAE9E;;;;;GAKG;AAEH,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GAGpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC;AAE9B,0BAA0B;AAC1B,MAAM,CAAC,MAAM,yBAAyB,GAAG,YAAY,CAAC;AAQtD,sFAAsF;AACtF,SAAS,YAAY,CAAC,MAAmB;IACvC,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,mBAAmB,CAAC,MAAmB;IACrD,OAAO,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,gBAAgB,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,OAAO,YAAY,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,IAAI,gBAAgB,CAAC;AAChE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAoB;IAC5D,IAAI,EAAE,yBAAyB;IAE/B,UAAU;QACR,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,qBAAqB;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACjC,IAAI,UAAU,GAAgC,IAAI,CAAC;QACnD,OAAO;YACL,IAAI,MAAM,CAAC;gBACT,GAAG,EAAE,mBAAmB;gBACxB,KAAK,EAAE;oBACL,IAAI,EAAE,yBAAyB;oBAC/B,KAAK,EAAE,wBAAwB;iBAChC;gBACD,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;oBACb,UAAU,GAAG,IAAI,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;oBACnD,OAAO,UAAU,CAAC;gBACpB,CAAC;gBACD,KAAK,EAAE;oBACL,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,KAAK;iBACjF;aACF,CAAC;SACH,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import { type ParagraphLayoutAttrName, type ParagraphLayoutAttrs } from '../api';
|
|
3
|
+
/** Nom de l'extension, clé dans `editor.extensionManager`. */
|
|
4
|
+
export declare const PARAGRAPH_LAYOUT_EXTENSION_NAME = "paragraphLayout";
|
|
5
|
+
/** Types de bloc qui portent les attributs de mise en page, alignés sur `TextAlign`. */
|
|
6
|
+
export declare const PARAGRAPH_LAYOUT_TYPES: readonly ["paragraph", "heading"];
|
|
7
|
+
/** Attribut HTML du nom de style Word d'un bloc. */
|
|
8
|
+
export declare const DOCX_STYLE_ATTRIBUTE = "data-docx-style";
|
|
9
|
+
/** Attribut HTML booléen « paragraphe solidaire du suivant ». */
|
|
10
|
+
export declare const KEEP_NEXT_ATTRIBUTE = "data-keep-next";
|
|
11
|
+
/** Attribut HTML booléen « saut de page avant ». */
|
|
12
|
+
export declare const PAGE_BREAK_BEFORE_ATTRIBUTE = "data-page-break-before";
|
|
13
|
+
/** Attribut HTML de la bordure `between` (pas d'équivalent CSS). */
|
|
14
|
+
export declare const BORDER_BETWEEN_ATTRIBUTE = "data-border-between";
|
|
15
|
+
/**
|
|
16
|
+
* Lit un `line-height` : nombre sans unité ou pourcentage → multiple, longueur → points.
|
|
17
|
+
* `normal` et les valeurs inconnues donnent deux `null`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseLineHeight(value: string | null): {
|
|
20
|
+
lineHeight: number | null;
|
|
21
|
+
lineHeightPt: number | null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Lit tous les attributs de mise en page d'un élément de bloc : `style` inline et
|
|
25
|
+
* attributs `data-*`. Un attribut absent vaut `null`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseParagraphLayout(element: HTMLElement): Required<ParagraphLayoutAttrs>;
|
|
28
|
+
/**
|
|
29
|
+
* Déclarations CSS d'un jeu d'attributs, dans l'ordre figé du contrat : `line-height`,
|
|
30
|
+
* `margin-top`, `margin-bottom`, `margin-left`, `margin-right`, `text-indent`,
|
|
31
|
+
* `border-*`, `background-color`. `lineHeightPt` l'emporte sur `lineHeight`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function paragraphLayoutDeclarations(attributes: Record<string, unknown>): string[];
|
|
34
|
+
/** Valeur `data-border-between` d'un jeu d'attributs, `null` sans bordure `between`. */
|
|
35
|
+
export declare function paragraphBorderBetween(attributes: Record<string, unknown>): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Attributs HTML complets d'un jeu d'attributs de mise en page, dans l'ordre : `style`,
|
|
38
|
+
* `data-border-between`, `data-docx-style`, `data-keep-next`, `data-page-break-before`.
|
|
39
|
+
* C'est ce que `renderHTML` émet et ce que les tests d'idempotence comparent.
|
|
40
|
+
*/
|
|
41
|
+
export declare function renderParagraphLayout(attributes: Record<string, unknown>): Record<string, string>;
|
|
42
|
+
/**
|
|
43
|
+
* Normalise une valeur d'attribut telle que `setLayout` la reçoit : nombres arrondis,
|
|
44
|
+
* bordures filtrées, couleurs normalisées, booléens stricts.
|
|
45
|
+
*
|
|
46
|
+
* Trois issues, à ne pas confondre : `null` efface l'attribut (demande explicite : `null`,
|
|
47
|
+
* `false`, chaîne vide, tableau vide) ; `undefined` signifie « ignorer » (attribut absent,
|
|
48
|
+
* ou valeur **invalide** : `'abc'` pour un nombre, `NaN`, `1e307`, un mot qui n'est pas une
|
|
49
|
+
* couleur, des bordures toutes mal formées). Une valeur invalide ne doit jamais effacer ce
|
|
50
|
+
* que le bloc portait.
|
|
51
|
+
*/
|
|
52
|
+
export declare function normalizeParagraphLayoutValue(name: ParagraphLayoutAttrName, value: unknown): unknown;
|
|
53
|
+
/**
|
|
54
|
+
* Extension `ParagraphLayout` : ajoute à `paragraph` et `heading` les attributs de
|
|
55
|
+
* `ParagraphLayoutAttrs`, lus dans le `style` inline et les `data-*`, et sérialisés
|
|
56
|
+
* exactement comme le contrat le fige. Déclarée après `TextAlign` dans le jeu d'Aster :
|
|
57
|
+
* son `text-align` vient en premier dans le `style`, les déclarations de mise en page
|
|
58
|
+
* ensuite. Aucune commande Tiptap : les commandes Aster `paragraph.setLayout` /
|
|
59
|
+
* `paragraph.unsetLayout` manipulent les attributs directement.
|
|
60
|
+
*/
|
|
61
|
+
export declare const ParagraphLayout: Extension<any, any>;
|
|
62
|
+
//# sourceMappingURL=paragraph-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paragraph-layout.d.ts","sourceRoot":"","sources":["../../src/extensions/paragraph-layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,cAAc,CAAC;AACzD,OAAO,EAGL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,QAAQ,CAAC;AAkBhB,8DAA8D;AAC9D,eAAO,MAAM,+BAA+B,oBAAoB,CAAC;AAEjE,wFAAwF;AACxF,eAAO,MAAM,sBAAsB,mCAAoC,CAAC;AAExE,oDAAoD;AACpD,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AACtD,iEAAiE;AACjE,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,oDAAoD;AACpD,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AACpE,oEAAoE;AACpE,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AA8B9D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG;IACrD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAmBA;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAsBzF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAwBzF;AAED,wFAAwF;AACxF,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAIzF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBjG;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,uBAAuB,EAC7B,KAAK,EAAE,OAAO,GACb,OAAO,CA6BT;AAiBD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,qBAU1B,CAAC"}
|