@meistrari/minuta-editor 1.3.0 → 1.4.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.
|
@@ -1,11 +1,33 @@
|
|
|
1
|
-
import { f as footnoteHtmlToRuns, p as pocLoneCellIndex, a as pocLooksLikeTitle } from '../shared/minuta-editor.
|
|
2
|
-
import { BorderStyle, TextRun, ExternalHyperlink, Paragraph, Document, Header, Packer,
|
|
1
|
+
import { f as footnoteHtmlToRuns, p as pocLoneCellIndex, a as formatTopicNumber, b as pocLooksLikeTitle, T as TOPIC_DEFAULT_GROUP } from '../shared/minuta-editor.b3351035.mjs';
|
|
2
|
+
import { BorderStyle, TextRun, ExternalHyperlink, Paragraph, Document, LevelFormat, AlignmentType, LevelSuffix, Header, Packer, LineRuleType, Table, TableRow, TableCell, WidthType, TableLayoutType, Footer, FootnoteReferenceRun, VerticalAlign, ImageRun, HorizontalPositionRelativeFrom, VerticalPositionRelativeFrom, TextWrappingType, FrameAnchorType, PageNumber, HeadingLevel } from 'docx';
|
|
3
3
|
import '@tiptap/pm/state';
|
|
4
4
|
import '@tiptap/pm/view';
|
|
5
5
|
|
|
6
6
|
const A4 = { width: 11906, height: 16838 };
|
|
7
7
|
const PX_TO_TWIP = 15;
|
|
8
8
|
const PX_PER_PT = 96 / 72;
|
|
9
|
+
function topicSequenceFor(ctx, group, roman, number) {
|
|
10
|
+
const key = group || TOPIC_DEFAULT_GROUP;
|
|
11
|
+
let seq = ctx.topicSequences.get(key);
|
|
12
|
+
if (!seq || seq.roman !== roman || seq.next !== number) {
|
|
13
|
+
const reference = `cdb-topic-${ctx.topicNumbering.size + 1}`;
|
|
14
|
+
ctx.topicNumbering.set(reference, { roman, start: number });
|
|
15
|
+
seq = { reference, roman, next: number };
|
|
16
|
+
ctx.topicSequences.set(key, seq);
|
|
17
|
+
}
|
|
18
|
+
seq.next = number + 1;
|
|
19
|
+
return seq.reference;
|
|
20
|
+
}
|
|
21
|
+
function leadingTopicNumber(node) {
|
|
22
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
23
|
+
const child = node.child(i);
|
|
24
|
+
if (child.isText && !child.text?.trim())
|
|
25
|
+
continue;
|
|
26
|
+
const number = Number(child.attrs.number);
|
|
27
|
+
return child.type.name === "topicNumber" && !child.attrs.ref && Number.isInteger(number) && number >= 1 ? child : null;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
9
31
|
function getProp(style, prop) {
|
|
10
32
|
if (!style)
|
|
11
33
|
return void 0;
|
|
@@ -185,9 +207,15 @@ function withMarks(base, marks) {
|
|
|
185
207
|
}
|
|
186
208
|
return info;
|
|
187
209
|
}
|
|
188
|
-
function inlineToRuns(node, base, ctx) {
|
|
210
|
+
function inlineToRuns(node, base, ctx, skip) {
|
|
189
211
|
const runs = [];
|
|
190
212
|
node.forEach((child) => {
|
|
213
|
+
if (skip && child === skip)
|
|
214
|
+
return;
|
|
215
|
+
if (child.type.name === "topicNumber") {
|
|
216
|
+
runs.push(new TextRun({ text: formatTopicNumber(child.attrs.number, child.attrs.roman), ...runOptions(withMarks(base, child.marks)) }));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
191
219
|
if (child.type.name === "footnoteRef") {
|
|
192
220
|
const text2 = String(child.attrs.text ?? "").trim();
|
|
193
221
|
if (ctx && text2) {
|
|
@@ -327,10 +355,18 @@ function textBlockToParagraph(node, pos, ctx, opts = {}) {
|
|
|
327
355
|
if (spacing.before && !breakBefore)
|
|
328
356
|
spacing.before = Math.max(0, spacing.before - ctx.lastAfterTw);
|
|
329
357
|
ctx.lastAfterTw = spacing.after ?? 0;
|
|
330
|
-
const
|
|
358
|
+
const topic = leadingTopicNumber(node);
|
|
359
|
+
let numbering;
|
|
360
|
+
if (topic) {
|
|
361
|
+
const reference = topicSequenceFor(ctx, topic.attrs.group, Boolean(topic.attrs.roman), Number(topic.attrs.number));
|
|
362
|
+
numbering = { reference, level: 0, custom: true };
|
|
363
|
+
}
|
|
364
|
+
const runs = inlineToRuns(node, base, ctx, topic);
|
|
331
365
|
const keepNext = Boolean(opts.heading || m && pocLooksLikeTitle(m.el)) || void 0;
|
|
332
366
|
const paragraph = new Paragraph({
|
|
333
367
|
children: runs,
|
|
368
|
+
numbering,
|
|
369
|
+
run: numbering ? runOptions(topic ? withMarks(base, topic.marks) : base) : void 0,
|
|
334
370
|
// sem alinhamento explícito, corpo de peça vai justificado (o Word
|
|
335
371
|
// usaria esquerda e o .docx sairia diferente da praxe e do preview)
|
|
336
372
|
alignment: m?.align ?? parseAlignment(style) ?? (opts.heading ? void 0 : AlignmentType.JUSTIFIED),
|
|
@@ -340,7 +376,7 @@ function textBlockToParagraph(node, pos, ctx, opts = {}) {
|
|
|
340
376
|
pageBreakBefore: breakBefore,
|
|
341
377
|
keepNext
|
|
342
378
|
});
|
|
343
|
-
ctx.meta.set(paragraph, { spacer: runs.length === 0 && !opts.heading, breakBefore });
|
|
379
|
+
ctx.meta.set(paragraph, { spacer: runs.length === 0 && !numbering && !opts.heading, breakBefore });
|
|
344
380
|
return paragraph;
|
|
345
381
|
}
|
|
346
382
|
async function srcToDataUrl(src) {
|
|
@@ -963,22 +999,13 @@ async function nodeToDocx(node, pos, contentWidthPx, ctx) {
|
|
|
963
999
|
case "table":
|
|
964
1000
|
return tableToDocx(node, pos, contentWidthPx, ctx);
|
|
965
1001
|
case "missingImage": {
|
|
966
|
-
const
|
|
967
|
-
children: [
|
|
968
|
-
text: `A imagem ${node.attrs.variableId ?? ""} est\xE1 faltando`,
|
|
969
|
-
italics: true,
|
|
970
|
-
color: "773613"
|
|
971
|
-
})],
|
|
1002
|
+
const lugar = new Paragraph({
|
|
1003
|
+
children: [],
|
|
972
1004
|
alignment: AlignmentType.CENTER,
|
|
973
|
-
|
|
974
|
-
top: { style: BorderStyle.DASHED, size: 4, color: "DF8B0D" },
|
|
975
|
-
bottom: { style: BorderStyle.DASHED, size: 4, color: "DF8B0D" },
|
|
976
|
-
left: { style: BorderStyle.DASHED, size: 4, color: "DF8B0D" },
|
|
977
|
-
right: { style: BorderStyle.DASHED, size: 4, color: "DF8B0D" }
|
|
978
|
-
},
|
|
1005
|
+
spacing: { after: 0, before: 0 },
|
|
979
1006
|
pageBreakBefore: consumeBreak(ctx)
|
|
980
1007
|
});
|
|
981
|
-
return [
|
|
1008
|
+
return [lugar];
|
|
982
1009
|
}
|
|
983
1010
|
case "horizontalRule":
|
|
984
1011
|
return [new Paragraph({ children: [], border: { bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" } } })];
|
|
@@ -1326,7 +1353,9 @@ async function pocExportDocx(editor, margins, chrome, options = {}) {
|
|
|
1326
1353
|
pending: { breakBefore: false },
|
|
1327
1354
|
lastAfterTw: 0,
|
|
1328
1355
|
meta: /* @__PURE__ */ new WeakMap(),
|
|
1329
|
-
footnotes: []
|
|
1356
|
+
footnotes: [],
|
|
1357
|
+
topicNumbering: /* @__PURE__ */ new Map(),
|
|
1358
|
+
topicSequences: /* @__PURE__ */ new Map()
|
|
1330
1359
|
};
|
|
1331
1360
|
const children = [];
|
|
1332
1361
|
let pos = 0;
|
|
@@ -1375,6 +1404,22 @@ async function pocExportDocx(editor, margins, chrome, options = {}) {
|
|
|
1375
1404
|
}
|
|
1376
1405
|
},
|
|
1377
1406
|
footnotes: Object.keys(footnotes).length ? footnotes : void 0,
|
|
1407
|
+
numbering: ctx.topicNumbering.size ? {
|
|
1408
|
+
config: [...ctx.topicNumbering].map(([reference, { roman, start }]) => ({
|
|
1409
|
+
reference,
|
|
1410
|
+
levels: [{
|
|
1411
|
+
level: 0,
|
|
1412
|
+
format: roman ? LevelFormat.UPPER_ROMAN : LevelFormat.DECIMAL,
|
|
1413
|
+
text: "%1",
|
|
1414
|
+
start,
|
|
1415
|
+
alignment: AlignmentType.START,
|
|
1416
|
+
// o ". " depois do número é texto do template; e sem
|
|
1417
|
+
// recuo/tab o parágrafo fica igual ao preview
|
|
1418
|
+
suffix: LevelSuffix.NOTHING,
|
|
1419
|
+
style: { paragraph: { indent: { left: 0, hanging: 0 } } }
|
|
1420
|
+
}]
|
|
1421
|
+
}))
|
|
1422
|
+
} : void 0,
|
|
1378
1423
|
sections: [{
|
|
1379
1424
|
properties: {
|
|
1380
1425
|
page: {
|
package/dist/docx.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
/// <reference types="@tiptap/extension-text" />
|
|
18
18
|
/// <reference types="@tiptap/extension-table" />
|
|
19
19
|
/// <reference types="@tiptap/extension-bubble-menu" />
|
|
20
|
-
import { Node, Editor,
|
|
20
|
+
import { Node, Editor, Extension, Mark } from '@tiptap/core';
|
|
21
|
+
import { Transaction } from '@tiptap/pm/state';
|
|
21
22
|
import { EditorView } from '@tiptap/pm/view';
|
|
22
23
|
import { P as PocPageConfig } from './shared/minuta-editor.9e65d163.mjs';
|
|
23
24
|
export { e as PAGINATE_META, a as PocDocxChrome, b as PocDocxExportOptions, s as PocLoneRow, d as PocPageBreak, c as PocPageNote, v as PocPaginationPlugin, u as breaksEqual, h as buildPocFooterEl, g as buildPocHeaderEl, j as buildPocNotesEl, l as computePocBreaks, t as computePocLoneRows, i as isPocChromeCanvas, n as isPocFlexRow, f as pocChromeFlowHeight, m as pocDescendsInto, r as pocLoneCellIndex, k as pocLooksLikeTitle, o as pocNodeHasVisibleContent, q as pocNodePaintsBox, p as pocPageKey } from './shared/minuta-editor.9e65d163.mjs';
|
|
24
25
|
import '@tiptap/pm/model';
|
|
25
|
-
import '@tiptap/pm/state';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Variáveis de template da minuta — o formato do placeholder e a resolução dele.
|
|
@@ -162,6 +162,29 @@ declare const PocTemplateVariable: Node<{
|
|
|
162
162
|
declare const PocFootnoteRef: Node<any, any>;
|
|
163
163
|
/** re-sequencia a numeração das chamadas de nota na ordem do documento */
|
|
164
164
|
declare function renumberPocFootnotes(editor: Editor): void;
|
|
165
|
+
/**
|
|
166
|
+
* Número de tópico/parágrafo — o `<topic group="paragrafo"/>` do template já
|
|
167
|
+
* resolvido pelo render. É NÓ, e não texto, por dois motivos: quem edita a
|
|
168
|
+
* minuta apaga, move ou insere um parágrafo numerado e a sequência do grupo se
|
|
169
|
+
* refaz sozinha (`PocTopicRenumber`), e o export leva o número como numeração
|
|
170
|
+
* nativa do Word, que também se refaz quando o advogado apaga um parágrafo lá.
|
|
171
|
+
* Contrato do marcador em `utils/topicNumber.ts`.
|
|
172
|
+
*/
|
|
173
|
+
declare const PocTopicNumber: Node<any, any>;
|
|
174
|
+
/**
|
|
175
|
+
* Re-sequencia os números de tópico na ordem do documento, por grupo, dentro
|
|
176
|
+
* da transação dada. Devolve se mudou algo. Um nó `ref` (latest) recebe o
|
|
177
|
+
* último número já contado do grupo — a mesma regra do render.
|
|
178
|
+
*/
|
|
179
|
+
declare function renumberPocTopicsIn(tr: Transaction): boolean;
|
|
180
|
+
/** re-sequencia a numeração dos tópicos no editor dado (uso pontual; o plugin faz isso a cada mudança) */
|
|
181
|
+
declare function renumberPocTopics(editor: Editor): void;
|
|
182
|
+
/**
|
|
183
|
+
* A cada transação que muda o documento, refaz a sequência dos tópicos. Só
|
|
184
|
+
* despacha quando algum número de fato mudou, então digitar dentro de um
|
|
185
|
+
* parágrafo não custa nada além da varredura.
|
|
186
|
+
*/
|
|
187
|
+
declare const PocTopicRenumber: Extension<any, any>;
|
|
165
188
|
declare const PocStyledDiv: Node<any, any>;
|
|
166
189
|
declare const PocInlineStyle: Mark<any, any>;
|
|
167
190
|
declare const PocUnderline: Mark<any, any>;
|
|
@@ -181,7 +204,7 @@ declare function buildPocExtensions(pageConfig?: PocPageConfig, options?: {
|
|
|
181
204
|
* ainda no editor — o seletor de variável — depende disso.
|
|
182
205
|
*/
|
|
183
206
|
handleKeyDown?: (view: EditorView, event: KeyboardEvent) => boolean;
|
|
184
|
-
}): (Node<any, any> |
|
|
207
|
+
}): (Node<any, any> | Extension<any, any> | Mark<any, any>)[];
|
|
185
208
|
|
|
186
209
|
/**
|
|
187
210
|
* O editor de minuta como coisa montável em qualquer lugar: `createMinutaEditor(el, opts)`.
|
|
@@ -480,6 +503,40 @@ declare function refreshVaultImages(editor: Editor, resolveUrl: (vaultUrl: strin
|
|
|
480
503
|
*/
|
|
481
504
|
declare function sanitizeRichHtml(html: string | null | undefined): string;
|
|
482
505
|
|
|
506
|
+
/**
|
|
507
|
+
* Número de tópico/parágrafo — o `<topic group="paragrafo"/>` dos templates.
|
|
508
|
+
*
|
|
509
|
+
* O render resolve o número, mas em vez de achatá-lo em texto ("12") o guarda
|
|
510
|
+
* num `<span data-topic-number>`: no editor ele vira o nó `topicNumber`, que se
|
|
511
|
+
* re-sequencia sozinho quando um parágrafo é apagado, movido ou inserido, e no
|
|
512
|
+
* DOCX vira numeração nativa do Word (que também se refaz quando o advogado
|
|
513
|
+
* apaga um parágrafo lá). Este é o contrato do marcador — server, client e
|
|
514
|
+
* pacote falam por ele.
|
|
515
|
+
*/
|
|
516
|
+
declare const TOPIC_NUMBER_ATTR = "data-topic-number";
|
|
517
|
+
declare const TOPIC_GROUP_ATTR = "data-topic-group";
|
|
518
|
+
declare const TOPIC_ROMAN_ATTR = "data-topic-roman";
|
|
519
|
+
declare const TOPIC_REF_ATTR = "data-topic-ref";
|
|
520
|
+
declare const TOPIC_DEFAULT_GROUP = "default";
|
|
521
|
+
interface TopicNumberInfo {
|
|
522
|
+
/** valor numérico (o que se conta) */
|
|
523
|
+
number: number;
|
|
524
|
+
/** grupo do contador (`group` da tag); sem grupo = `default` */
|
|
525
|
+
group: string;
|
|
526
|
+
/** exibido em algarismos romanos maiúsculos */
|
|
527
|
+
roman: boolean;
|
|
528
|
+
/** `<topic latest="true">`: repete o último número do grupo em vez de avançar */
|
|
529
|
+
ref: boolean;
|
|
530
|
+
}
|
|
531
|
+
declare function toRoman(num: number): string;
|
|
532
|
+
declare function fromRoman(text: string): number | null;
|
|
533
|
+
/** texto exibido para o número (decimal ou romano) */
|
|
534
|
+
declare function formatTopicNumber(number: number, roman: boolean): string;
|
|
535
|
+
/** o marcador em HTML — é o que o render emite e o que o editor lê e grava */
|
|
536
|
+
declare function topicNumberHtml(info: TopicNumberInfo): string;
|
|
537
|
+
/** lê o marcador de um elemento (`span[data-topic-number]`) */
|
|
538
|
+
declare function readTopicNumber(el: Element): TopicNumberInfo;
|
|
539
|
+
|
|
483
540
|
/**
|
|
484
541
|
* A tag de imagem que o editor insere após o upload: guarda o `src` presignado
|
|
485
542
|
* (funciona agora) E o `data-vault-src` durável (`vault://…`). Quem re-resolve
|
|
@@ -504,5 +561,5 @@ declare function collectVaultRefs(html: string): string[];
|
|
|
504
561
|
/** aplica as URLs resolvidas às `<img>` do trecho; tags sem resolução ficam como estão */
|
|
505
562
|
declare function renewVaultImageTags(html: string, resolved: Map<string, string>): string;
|
|
506
563
|
|
|
507
|
-
export { A4_HEIGHT_PX, A4_WIDTH_PX, DEFAULT_MARGINS, DOC_FONTS, ICON_PATHS, POC_ASSET_SWAP, PocDocument, PocFootnoteRef, PocHtmlIsland, PocInlineStyle, PocMinutaBlock, PocMissingImage, PocPageConfig, PocStylePassthrough, PocStyledDiv, PocTemplateVariable, PocUnderline, PocVariableChip, buildPocExtensions, collectVaultRefs, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, footnoteHtmlToRuns, footnoteSizePt, iconSvg, refreshVaultImages, renewVaultImageTags, renumberPocFootnotes, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, shouldMoveBreakToHeading, swapVaultSrc, variableChipHtml, vaultImageHtml, vaultRefOf };
|
|
508
|
-
export type { FootnoteRun, MinutaChromeText, MinutaEditor, MinutaEditorOptions, MinutaHeader, MinutaMargins, MinutaVariableCatalog, MinutaVariableDef, MinutaVariableRef, PocKeepWithNextItem, RefreshVaultImagesOptions, VariableClickKind };
|
|
564
|
+
export { A4_HEIGHT_PX, A4_WIDTH_PX, DEFAULT_MARGINS, DOC_FONTS, ICON_PATHS, POC_ASSET_SWAP, PocDocument, PocFootnoteRef, PocHtmlIsland, PocInlineStyle, PocMinutaBlock, PocMissingImage, PocPageConfig, PocStylePassthrough, PocStyledDiv, PocTemplateVariable, PocTopicNumber, PocTopicRenumber, PocUnderline, PocVariableChip, TOPIC_DEFAULT_GROUP, TOPIC_GROUP_ATTR, TOPIC_NUMBER_ATTR, TOPIC_REF_ATTR, TOPIC_ROMAN_ATTR, buildPocExtensions, collectVaultRefs, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, footnoteHtmlToRuns, footnoteSizePt, formatTopicNumber, fromRoman, iconSvg, readTopicNumber, refreshVaultImages, renewVaultImageTags, renumberPocFootnotes, renumberPocTopics, renumberPocTopicsIn, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, shouldMoveBreakToHeading, swapVaultSrc, toRoman, topicNumberHtml, variableChipHtml, vaultImageHtml, vaultRefOf };
|
|
565
|
+
export type { FootnoteRun, MinutaChromeText, MinutaEditor, MinutaEditorOptions, MinutaHeader, MinutaMargins, MinutaVariableCatalog, MinutaVariableDef, MinutaVariableRef, PocKeepWithNextItem, RefreshVaultImagesOptions, TopicNumberInfo, VariableClickKind };
|
package/dist/index.d.ts
CHANGED
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
/// <reference types="@tiptap/extension-text" />
|
|
18
18
|
/// <reference types="@tiptap/extension-table" />
|
|
19
19
|
/// <reference types="@tiptap/extension-bubble-menu" />
|
|
20
|
-
import { Node, Editor,
|
|
20
|
+
import { Node, Editor, Extension, Mark } from '@tiptap/core';
|
|
21
|
+
import { Transaction } from '@tiptap/pm/state';
|
|
21
22
|
import { EditorView } from '@tiptap/pm/view';
|
|
22
23
|
import { P as PocPageConfig } from './shared/minuta-editor.9e65d163.js';
|
|
23
24
|
export { e as PAGINATE_META, a as PocDocxChrome, b as PocDocxExportOptions, s as PocLoneRow, d as PocPageBreak, c as PocPageNote, v as PocPaginationPlugin, u as breaksEqual, h as buildPocFooterEl, g as buildPocHeaderEl, j as buildPocNotesEl, l as computePocBreaks, t as computePocLoneRows, i as isPocChromeCanvas, n as isPocFlexRow, f as pocChromeFlowHeight, m as pocDescendsInto, r as pocLoneCellIndex, k as pocLooksLikeTitle, o as pocNodeHasVisibleContent, q as pocNodePaintsBox, p as pocPageKey } from './shared/minuta-editor.9e65d163.js';
|
|
24
25
|
import '@tiptap/pm/model';
|
|
25
|
-
import '@tiptap/pm/state';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Variáveis de template da minuta — o formato do placeholder e a resolução dele.
|
|
@@ -162,6 +162,29 @@ declare const PocTemplateVariable: Node<{
|
|
|
162
162
|
declare const PocFootnoteRef: Node<any, any>;
|
|
163
163
|
/** re-sequencia a numeração das chamadas de nota na ordem do documento */
|
|
164
164
|
declare function renumberPocFootnotes(editor: Editor): void;
|
|
165
|
+
/**
|
|
166
|
+
* Número de tópico/parágrafo — o `<topic group="paragrafo"/>` do template já
|
|
167
|
+
* resolvido pelo render. É NÓ, e não texto, por dois motivos: quem edita a
|
|
168
|
+
* minuta apaga, move ou insere um parágrafo numerado e a sequência do grupo se
|
|
169
|
+
* refaz sozinha (`PocTopicRenumber`), e o export leva o número como numeração
|
|
170
|
+
* nativa do Word, que também se refaz quando o advogado apaga um parágrafo lá.
|
|
171
|
+
* Contrato do marcador em `utils/topicNumber.ts`.
|
|
172
|
+
*/
|
|
173
|
+
declare const PocTopicNumber: Node<any, any>;
|
|
174
|
+
/**
|
|
175
|
+
* Re-sequencia os números de tópico na ordem do documento, por grupo, dentro
|
|
176
|
+
* da transação dada. Devolve se mudou algo. Um nó `ref` (latest) recebe o
|
|
177
|
+
* último número já contado do grupo — a mesma regra do render.
|
|
178
|
+
*/
|
|
179
|
+
declare function renumberPocTopicsIn(tr: Transaction): boolean;
|
|
180
|
+
/** re-sequencia a numeração dos tópicos no editor dado (uso pontual; o plugin faz isso a cada mudança) */
|
|
181
|
+
declare function renumberPocTopics(editor: Editor): void;
|
|
182
|
+
/**
|
|
183
|
+
* A cada transação que muda o documento, refaz a sequência dos tópicos. Só
|
|
184
|
+
* despacha quando algum número de fato mudou, então digitar dentro de um
|
|
185
|
+
* parágrafo não custa nada além da varredura.
|
|
186
|
+
*/
|
|
187
|
+
declare const PocTopicRenumber: Extension<any, any>;
|
|
165
188
|
declare const PocStyledDiv: Node<any, any>;
|
|
166
189
|
declare const PocInlineStyle: Mark<any, any>;
|
|
167
190
|
declare const PocUnderline: Mark<any, any>;
|
|
@@ -181,7 +204,7 @@ declare function buildPocExtensions(pageConfig?: PocPageConfig, options?: {
|
|
|
181
204
|
* ainda no editor — o seletor de variável — depende disso.
|
|
182
205
|
*/
|
|
183
206
|
handleKeyDown?: (view: EditorView, event: KeyboardEvent) => boolean;
|
|
184
|
-
}): (Node<any, any> |
|
|
207
|
+
}): (Node<any, any> | Extension<any, any> | Mark<any, any>)[];
|
|
185
208
|
|
|
186
209
|
/**
|
|
187
210
|
* O editor de minuta como coisa montável em qualquer lugar: `createMinutaEditor(el, opts)`.
|
|
@@ -480,6 +503,40 @@ declare function refreshVaultImages(editor: Editor, resolveUrl: (vaultUrl: strin
|
|
|
480
503
|
*/
|
|
481
504
|
declare function sanitizeRichHtml(html: string | null | undefined): string;
|
|
482
505
|
|
|
506
|
+
/**
|
|
507
|
+
* Número de tópico/parágrafo — o `<topic group="paragrafo"/>` dos templates.
|
|
508
|
+
*
|
|
509
|
+
* O render resolve o número, mas em vez de achatá-lo em texto ("12") o guarda
|
|
510
|
+
* num `<span data-topic-number>`: no editor ele vira o nó `topicNumber`, que se
|
|
511
|
+
* re-sequencia sozinho quando um parágrafo é apagado, movido ou inserido, e no
|
|
512
|
+
* DOCX vira numeração nativa do Word (que também se refaz quando o advogado
|
|
513
|
+
* apaga um parágrafo lá). Este é o contrato do marcador — server, client e
|
|
514
|
+
* pacote falam por ele.
|
|
515
|
+
*/
|
|
516
|
+
declare const TOPIC_NUMBER_ATTR = "data-topic-number";
|
|
517
|
+
declare const TOPIC_GROUP_ATTR = "data-topic-group";
|
|
518
|
+
declare const TOPIC_ROMAN_ATTR = "data-topic-roman";
|
|
519
|
+
declare const TOPIC_REF_ATTR = "data-topic-ref";
|
|
520
|
+
declare const TOPIC_DEFAULT_GROUP = "default";
|
|
521
|
+
interface TopicNumberInfo {
|
|
522
|
+
/** valor numérico (o que se conta) */
|
|
523
|
+
number: number;
|
|
524
|
+
/** grupo do contador (`group` da tag); sem grupo = `default` */
|
|
525
|
+
group: string;
|
|
526
|
+
/** exibido em algarismos romanos maiúsculos */
|
|
527
|
+
roman: boolean;
|
|
528
|
+
/** `<topic latest="true">`: repete o último número do grupo em vez de avançar */
|
|
529
|
+
ref: boolean;
|
|
530
|
+
}
|
|
531
|
+
declare function toRoman(num: number): string;
|
|
532
|
+
declare function fromRoman(text: string): number | null;
|
|
533
|
+
/** texto exibido para o número (decimal ou romano) */
|
|
534
|
+
declare function formatTopicNumber(number: number, roman: boolean): string;
|
|
535
|
+
/** o marcador em HTML — é o que o render emite e o que o editor lê e grava */
|
|
536
|
+
declare function topicNumberHtml(info: TopicNumberInfo): string;
|
|
537
|
+
/** lê o marcador de um elemento (`span[data-topic-number]`) */
|
|
538
|
+
declare function readTopicNumber(el: Element): TopicNumberInfo;
|
|
539
|
+
|
|
483
540
|
/**
|
|
484
541
|
* A tag de imagem que o editor insere após o upload: guarda o `src` presignado
|
|
485
542
|
* (funciona agora) E o `data-vault-src` durável (`vault://…`). Quem re-resolve
|
|
@@ -504,5 +561,5 @@ declare function collectVaultRefs(html: string): string[];
|
|
|
504
561
|
/** aplica as URLs resolvidas às `<img>` do trecho; tags sem resolução ficam como estão */
|
|
505
562
|
declare function renewVaultImageTags(html: string, resolved: Map<string, string>): string;
|
|
506
563
|
|
|
507
|
-
export { A4_HEIGHT_PX, A4_WIDTH_PX, DEFAULT_MARGINS, DOC_FONTS, ICON_PATHS, POC_ASSET_SWAP, PocDocument, PocFootnoteRef, PocHtmlIsland, PocInlineStyle, PocMinutaBlock, PocMissingImage, PocPageConfig, PocStylePassthrough, PocStyledDiv, PocTemplateVariable, PocUnderline, PocVariableChip, buildPocExtensions, collectVaultRefs, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, footnoteHtmlToRuns, footnoteSizePt, iconSvg, refreshVaultImages, renewVaultImageTags, renumberPocFootnotes, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, shouldMoveBreakToHeading, swapVaultSrc, variableChipHtml, vaultImageHtml, vaultRefOf };
|
|
508
|
-
export type { FootnoteRun, MinutaChromeText, MinutaEditor, MinutaEditorOptions, MinutaHeader, MinutaMargins, MinutaVariableCatalog, MinutaVariableDef, MinutaVariableRef, PocKeepWithNextItem, RefreshVaultImagesOptions, VariableClickKind };
|
|
564
|
+
export { A4_HEIGHT_PX, A4_WIDTH_PX, DEFAULT_MARGINS, DOC_FONTS, ICON_PATHS, POC_ASSET_SWAP, PocDocument, PocFootnoteRef, PocHtmlIsland, PocInlineStyle, PocMinutaBlock, PocMissingImage, PocPageConfig, PocStylePassthrough, PocStyledDiv, PocTemplateVariable, PocTopicNumber, PocTopicRenumber, PocUnderline, PocVariableChip, TOPIC_DEFAULT_GROUP, TOPIC_GROUP_ATTR, TOPIC_NUMBER_ATTR, TOPIC_REF_ATTR, TOPIC_ROMAN_ATTR, buildPocExtensions, collectVaultRefs, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, footnoteHtmlToRuns, footnoteSizePt, formatTopicNumber, fromRoman, iconSvg, readTopicNumber, refreshVaultImages, renewVaultImageTags, renumberPocFootnotes, renumberPocTopics, renumberPocTopicsIn, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, shouldMoveBreakToHeading, swapVaultSrc, toRoman, topicNumberHtml, variableChipHtml, vaultImageHtml, vaultRefOf };
|
|
565
|
+
export type { FootnoteRun, MinutaChromeText, MinutaEditor, MinutaEditorOptions, MinutaHeader, MinutaMargins, MinutaVariableCatalog, MinutaVariableDef, MinutaVariableRef, PocKeepWithNextItem, RefreshVaultImagesOptions, TopicNumberInfo, VariableClickKind };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Node as Node$1, mergeAttributes,
|
|
1
|
+
import { Node as Node$1, mergeAttributes, Extension, Mark, Editor } from '@tiptap/core';
|
|
2
2
|
import BubbleMenu from '@tiptap/extension-bubble-menu';
|
|
3
3
|
import Bold from '@tiptap/extension-bold';
|
|
4
4
|
import Blockquote from '@tiptap/extension-blockquote';
|
|
@@ -22,8 +22,8 @@ import TableCell from '@tiptap/extension-table-cell';
|
|
|
22
22
|
import TableHeader from '@tiptap/extension-table-header';
|
|
23
23
|
import TableRow from '@tiptap/extension-table-row';
|
|
24
24
|
import { Plugin } from '@tiptap/pm/state';
|
|
25
|
-
import { s as sanitizeRichHtml, P as PocPaginationPlugin,
|
|
26
|
-
export {
|
|
25
|
+
import { s as sanitizeRichHtml, T as TOPIC_DEFAULT_GROUP, c as TOPIC_NUMBER_ATTR, r as readTopicNumber, d as TOPIC_GROUP_ATTR, e as TOPIC_ROMAN_ATTR, g as TOPIC_REF_ATTR, a as formatTopicNumber, P as PocPaginationPlugin, h as sanitizeFootnoteHtml, i as computePocBreaks, j as pocPageKey, k as breaksEqual, l as PAGINATE_META } from './shared/minuta-editor.b3351035.mjs';
|
|
26
|
+
export { q as buildPocFooterEl, o as buildPocHeaderEl, t as buildPocNotesEl, y as computePocLoneRows, f as footnoteHtmlToRuns, z as footnoteSizePt, C as fromRoman, n as isPocChromeCanvas, v as isPocFlexRow, m as pocChromeFlowHeight, u as pocDescendsInto, p as pocLoneCellIndex, b as pocLooksLikeTitle, w as pocNodeHasVisibleContent, x as pocNodePaintsBox, A as shouldMoveBreakToHeading, B as toRoman, D as topicNumberHtml } from './shared/minuta-editor.b3351035.mjs';
|
|
27
27
|
import '@tiptap/pm/view';
|
|
28
28
|
|
|
29
29
|
const POC_ASSET_SWAP = "pocAssetSwap";
|
|
@@ -472,6 +472,76 @@ function renumberPocFootnotes(editor) {
|
|
|
472
472
|
if (touched)
|
|
473
473
|
editor.view.dispatch(tr);
|
|
474
474
|
}
|
|
475
|
+
const PocTopicNumber = Node$1.create({
|
|
476
|
+
name: "topicNumber",
|
|
477
|
+
inline: true,
|
|
478
|
+
group: "inline",
|
|
479
|
+
atom: true,
|
|
480
|
+
selectable: false,
|
|
481
|
+
addAttributes() {
|
|
482
|
+
return {
|
|
483
|
+
number: { default: 1 },
|
|
484
|
+
group: { default: TOPIC_DEFAULT_GROUP },
|
|
485
|
+
roman: { default: false },
|
|
486
|
+
/** `<topic latest="true">`: repete o último número do grupo em vez de avançar */
|
|
487
|
+
ref: { default: false }
|
|
488
|
+
};
|
|
489
|
+
},
|
|
490
|
+
parseHTML() {
|
|
491
|
+
return [{
|
|
492
|
+
tag: `span[${TOPIC_NUMBER_ATTR}]`,
|
|
493
|
+
priority: 110,
|
|
494
|
+
getAttrs: (el) => readTopicNumber(el)
|
|
495
|
+
}];
|
|
496
|
+
},
|
|
497
|
+
renderHTML({ node }) {
|
|
498
|
+
const attrs = {
|
|
499
|
+
[TOPIC_NUMBER_ATTR]: String(node.attrs.number),
|
|
500
|
+
[TOPIC_GROUP_ATTR]: node.attrs.group || TOPIC_DEFAULT_GROUP,
|
|
501
|
+
class: "poc-topic-number"
|
|
502
|
+
};
|
|
503
|
+
if (node.attrs.roman)
|
|
504
|
+
attrs[TOPIC_ROMAN_ATTR] = "true";
|
|
505
|
+
if (node.attrs.ref)
|
|
506
|
+
attrs[TOPIC_REF_ATTR] = "true";
|
|
507
|
+
return ["span", attrs, formatTopicNumber(node.attrs.number, node.attrs.roman)];
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
function renumberPocTopicsIn(tr) {
|
|
511
|
+
const counters = {};
|
|
512
|
+
let touched = false;
|
|
513
|
+
tr.doc.descendants((node, pos) => {
|
|
514
|
+
if (node.type.name !== "topicNumber")
|
|
515
|
+
return;
|
|
516
|
+
const group = node.attrs.group || TOPIC_DEFAULT_GROUP;
|
|
517
|
+
const number = node.attrs.ref ? counters[group] ?? 0 : counters[group] = (counters[group] ?? 0) + 1;
|
|
518
|
+
if (node.attrs.number !== number) {
|
|
519
|
+
tr.setNodeMarkup(pos, void 0, { ...node.attrs, number });
|
|
520
|
+
touched = true;
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
return touched;
|
|
524
|
+
}
|
|
525
|
+
function renumberPocTopics(editor) {
|
|
526
|
+
if (!editor || editor.isDestroyed)
|
|
527
|
+
return;
|
|
528
|
+
const tr = editor.state.tr;
|
|
529
|
+
if (renumberPocTopicsIn(tr))
|
|
530
|
+
editor.view.dispatch(tr);
|
|
531
|
+
}
|
|
532
|
+
const PocTopicRenumber = Extension.create({
|
|
533
|
+
name: "pocTopicRenumber",
|
|
534
|
+
addProseMirrorPlugins() {
|
|
535
|
+
return [new Plugin({
|
|
536
|
+
appendTransaction(transactions, _oldState, newState) {
|
|
537
|
+
if (!transactions.some((t) => t.docChanged))
|
|
538
|
+
return null;
|
|
539
|
+
const tr = newState.tr;
|
|
540
|
+
return renumberPocTopicsIn(tr) ? tr : null;
|
|
541
|
+
}
|
|
542
|
+
})];
|
|
543
|
+
}
|
|
544
|
+
});
|
|
475
545
|
const PocStyledDiv = Node$1.create({
|
|
476
546
|
name: "styledDiv",
|
|
477
547
|
group: "block",
|
|
@@ -601,6 +671,8 @@ function buildPocExtensions(pageConfig, options) {
|
|
|
601
671
|
PocVariableChip,
|
|
602
672
|
PocTemplateVariable.configure({ catalog: options?.variables ?? [] }),
|
|
603
673
|
PocFootnoteRef,
|
|
674
|
+
PocTopicNumber,
|
|
675
|
+
PocTopicRenumber,
|
|
604
676
|
PocStyledDiv,
|
|
605
677
|
PocInlineStyle,
|
|
606
678
|
PocUnderline,
|
|
@@ -2091,4 +2163,4 @@ function createMinutaEditor(element, opts) {
|
|
|
2091
2163
|
return api;
|
|
2092
2164
|
}
|
|
2093
2165
|
|
|
2094
|
-
export { A4_HEIGHT_PX, A4_WIDTH_PX, DEFAULT_MARGINS, DOC_FONTS, ICON_PATHS, PAGINATE_META, POC_ASSET_SWAP, PocDocument, PocFootnoteRef, PocHtmlIsland, PocInlineStyle, PocMinutaBlock, PocMissingImage, PocPaginationPlugin, PocStylePassthrough, PocStyledDiv, PocTemplateVariable, PocUnderline, PocVariableChip, breaksEqual, buildPocExtensions, collectVaultRefs, computePocBreaks, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, iconSvg, pocPageKey, refreshVaultImages, renewVaultImageTags, renumberPocFootnotes, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, swapVaultSrc, variableChipHtml, vaultImageHtml, vaultRefOf };
|
|
2166
|
+
export { A4_HEIGHT_PX, A4_WIDTH_PX, DEFAULT_MARGINS, DOC_FONTS, ICON_PATHS, PAGINATE_META, POC_ASSET_SWAP, PocDocument, PocFootnoteRef, PocHtmlIsland, PocInlineStyle, PocMinutaBlock, PocMissingImage, PocPaginationPlugin, PocStylePassthrough, PocStyledDiv, PocTemplateVariable, PocTopicNumber, PocTopicRenumber, PocUnderline, PocVariableChip, TOPIC_DEFAULT_GROUP, TOPIC_GROUP_ATTR, TOPIC_NUMBER_ATTR, TOPIC_REF_ATTR, TOPIC_ROMAN_ATTR, breaksEqual, buildPocExtensions, collectVaultRefs, computePocBreaks, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, formatTopicNumber, iconSvg, pocPageKey, readTopicNumber, refreshVaultImages, renewVaultImageTags, renumberPocFootnotes, renumberPocTopics, renumberPocTopicsIn, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, swapVaultSrc, variableChipHtml, vaultImageHtml, vaultRefOf };
|
|
@@ -75,6 +75,84 @@ function sanitizeRichHtml(html) {
|
|
|
75
75
|
return tpl.innerHTML;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const TOPIC_NUMBER_ATTR = "data-topic-number";
|
|
79
|
+
const TOPIC_GROUP_ATTR = "data-topic-group";
|
|
80
|
+
const TOPIC_ROMAN_ATTR = "data-topic-roman";
|
|
81
|
+
const TOPIC_REF_ATTR = "data-topic-ref";
|
|
82
|
+
const TOPIC_DEFAULT_GROUP = "default";
|
|
83
|
+
function toRoman(num) {
|
|
84
|
+
if (!Number.isFinite(num) || num <= 0)
|
|
85
|
+
return "";
|
|
86
|
+
const numerals = [
|
|
87
|
+
[1e3, "M"],
|
|
88
|
+
[900, "CM"],
|
|
89
|
+
[500, "D"],
|
|
90
|
+
[400, "CD"],
|
|
91
|
+
[100, "C"],
|
|
92
|
+
[90, "XC"],
|
|
93
|
+
[50, "L"],
|
|
94
|
+
[40, "XL"],
|
|
95
|
+
[10, "X"],
|
|
96
|
+
[9, "IX"],
|
|
97
|
+
[5, "V"],
|
|
98
|
+
[4, "IV"],
|
|
99
|
+
[1, "I"]
|
|
100
|
+
];
|
|
101
|
+
let result = "";
|
|
102
|
+
let rest = Math.floor(num);
|
|
103
|
+
for (const [value, numeral] of numerals) {
|
|
104
|
+
while (rest >= value) {
|
|
105
|
+
result += numeral;
|
|
106
|
+
rest -= value;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
function fromRoman(text) {
|
|
112
|
+
const upper = text.trim().toUpperCase();
|
|
113
|
+
if (!upper || !/^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/.test(upper))
|
|
114
|
+
return null;
|
|
115
|
+
const values = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1e3 };
|
|
116
|
+
let total = 0;
|
|
117
|
+
for (let i = 0; i < upper.length; i++) {
|
|
118
|
+
const current = values[upper[i]];
|
|
119
|
+
const next = values[upper[i + 1] ?? ""] ?? 0;
|
|
120
|
+
total += current < next ? -current : current;
|
|
121
|
+
}
|
|
122
|
+
return total;
|
|
123
|
+
}
|
|
124
|
+
function formatTopicNumber(number, roman) {
|
|
125
|
+
return roman ? toRoman(number) : String(number);
|
|
126
|
+
}
|
|
127
|
+
function escapeAttr(value) {
|
|
128
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
129
|
+
}
|
|
130
|
+
function topicNumberHtml(info) {
|
|
131
|
+
let attrs = `${TOPIC_NUMBER_ATTR}="${info.number}" ${TOPIC_GROUP_ATTR}="${escapeAttr(info.group || TOPIC_DEFAULT_GROUP)}"`;
|
|
132
|
+
if (info.roman)
|
|
133
|
+
attrs += ` ${TOPIC_ROMAN_ATTR}="true"`;
|
|
134
|
+
if (info.ref)
|
|
135
|
+
attrs += ` ${TOPIC_REF_ATTR}="true"`;
|
|
136
|
+
return `<span ${attrs}>${formatTopicNumber(info.number, info.roman)}</span>`;
|
|
137
|
+
}
|
|
138
|
+
function readTopicNumber(el) {
|
|
139
|
+
const roman = el.getAttribute(TOPIC_ROMAN_ATTR) === "true";
|
|
140
|
+
const raw = el.getAttribute(TOPIC_NUMBER_ATTR) ?? "";
|
|
141
|
+
let number = Number.parseInt(raw, 10);
|
|
142
|
+
if (!Number.isFinite(number)) {
|
|
143
|
+
const text = el.textContent?.trim() ?? "";
|
|
144
|
+
number = Number.parseInt(text, 10);
|
|
145
|
+
if (!Number.isFinite(number))
|
|
146
|
+
number = fromRoman(text) ?? 1;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
number,
|
|
150
|
+
group: el.getAttribute(TOPIC_GROUP_ATTR) || TOPIC_DEFAULT_GROUP,
|
|
151
|
+
roman,
|
|
152
|
+
ref: el.getAttribute(TOPIC_REF_ATTR) === "true"
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
78
156
|
const INLINE_TAGS = /* @__PURE__ */ new Set(["B", "STRONG", "I", "EM", "U", "SUP", "SUB", "BR"]);
|
|
79
157
|
function safeHref(value) {
|
|
80
158
|
const href = (value ?? "").trim();
|
|
@@ -819,4 +897,4 @@ function PocPaginationPlugin(cfg) {
|
|
|
819
897
|
});
|
|
820
898
|
}
|
|
821
899
|
|
|
822
|
-
export { PocPaginationPlugin as P,
|
|
900
|
+
export { shouldMoveBreakToHeading as A, toRoman as B, fromRoman as C, topicNumberHtml as D, PocPaginationPlugin as P, TOPIC_DEFAULT_GROUP as T, formatTopicNumber as a, pocLooksLikeTitle as b, TOPIC_NUMBER_ATTR as c, TOPIC_GROUP_ATTR as d, TOPIC_ROMAN_ATTR as e, footnoteHtmlToRuns as f, TOPIC_REF_ATTR as g, sanitizeFootnoteHtml as h, computePocBreaks as i, pocPageKey as j, breaksEqual as k, PAGINATE_META as l, pocChromeFlowHeight as m, isPocChromeCanvas as n, buildPocHeaderEl as o, pocLoneCellIndex as p, buildPocFooterEl as q, readTopicNumber as r, sanitizeRichHtml as s, buildPocNotesEl as t, pocDescendsInto as u, isPocFlexRow as v, pocNodeHasVisibleContent as w, pocNodePaintsBox as x, computePocLoneRows as y, footnoteSizePt as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meistrari/minuta-editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Editor de minuta do defesa.ai sem framework: folha A4 paginada, edição rica, placeholders de variável e export DOCX fiel ao preview — monta em qualquer app (React, Vue, vanilla)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|