@meistrari/minuta-editor 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -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, a as sanitizeFootnoteHtml, c as computePocBreaks, b as pocPageKey, d as breaksEqual, e as PAGINATE_META } from './shared/minuta-editor.b2512170.mjs';
26
- export { j as buildPocFooterEl, h as buildPocHeaderEl, k as buildPocNotesEl, o as computePocLoneRows, f as footnoteHtmlToRuns, q as footnoteSizePt, i as isPocChromeCanvas, l as isPocFlexRow, g as pocChromeFlowHeight, p as pocLoneCellIndex, m as pocNodeHasVisibleContent, n as pocNodePaintsBox, r as shouldMoveBreakToHeading } from './shared/minuta-editor.b2512170.mjs';
25
+ import { s as sanitizeRichHtml, P as PocPaginationPlugin, b as sanitizeFootnoteHtml, c as computePocBreaks, d as pocPageKey, e as breaksEqual, g as PAGINATE_META } from './shared/minuta-editor.d9d0c0ce.mjs';
26
+ export { k as buildPocFooterEl, j as buildPocHeaderEl, l as buildPocNotesEl, r as computePocLoneRows, f as footnoteHtmlToRuns, t as footnoteSizePt, i as isPocChromeCanvas, n as isPocFlexRow, h as pocChromeFlowHeight, m as pocDescendsInto, p as pocLoneCellIndex, a as pocLooksLikeTitle, o as pocNodeHasVisibleContent, q as pocNodePaintsBox, u as shouldMoveBreakToHeading } from './shared/minuta-editor.d9d0c0ce.mjs';
27
27
  import '@tiptap/pm/view';
28
28
 
29
29
  const POC_ASSET_SWAP = "pocAssetSwap";
@@ -68,6 +68,11 @@ const PocMinutaBlock = Node$1.create({
68
68
  }), 0];
69
69
  }
70
70
  });
71
+ function dispatchVariableClick(editor, detail) {
72
+ if (!detail.variableId)
73
+ return;
74
+ editor.view.dom.dispatchEvent(new CustomEvent("poc:variable-click", { bubbles: true, detail }));
75
+ }
71
76
  const PocHtmlIsland = Node$1.create({
72
77
  name: "htmlIsland",
73
78
  group: "block",
@@ -95,6 +100,17 @@ const PocHtmlIsland = Node$1.create({
95
100
  dom.className = "poc-island";
96
101
  dom.contentEditable = "false";
97
102
  dom.innerHTML = sanitizeRichHtml(node.attrs.html);
103
+ dom.addEventListener("click", (event) => {
104
+ const target = event.target?.closest?.("img[data-variable-id]");
105
+ if (!target)
106
+ return;
107
+ dispatchVariableClick(editor, {
108
+ variableId: target.getAttribute("data-variable-id"),
109
+ parentBlockId: target.getAttribute("data-parent-block-id"),
110
+ text: "",
111
+ kind: "image"
112
+ });
113
+ });
98
114
  const img = dom.children.length === 1 && dom.firstElementChild instanceof HTMLImageElement ? dom.firstElementChild : null;
99
115
  if (img)
100
116
  dom.classList.add("poc-island--img");
@@ -206,11 +222,23 @@ const PocMissingImage = Node$1.create({
206
222
  const caixa = document.createElement("div");
207
223
  caixa.className = "missing-image-warning";
208
224
  caixa.setAttribute("style", MISSING_IMAGE_BOX_STYLE);
225
+ caixa.setAttribute("data-variable-id", node.attrs.variableId ?? "");
226
+ caixa.setAttribute("data-parent-block-id", node.attrs.parentBlockId ?? "");
209
227
  const linha = document.createElement("span");
210
228
  linha.setAttribute("style", MISSING_IMAGE_ROW_STYLE);
211
229
  linha.textContent = `\u26A0 A imagem ${node.attrs.variableId ?? ""} est\xE1 faltando`;
212
230
  caixa.appendChild(linha);
213
231
  dom.appendChild(caixa);
232
+ dom.addEventListener("click", (event) => {
233
+ if (event.target.closest(".poc-missing-image__remove"))
234
+ return;
235
+ dispatchVariableClick(editor, {
236
+ variableId: node.attrs.variableId,
237
+ parentBlockId: node.attrs.parentBlockId,
238
+ text: "",
239
+ kind: "missingImage"
240
+ });
241
+ });
214
242
  if (!editor.isEditable)
215
243
  return { dom };
216
244
  caixa.style.position = "relative";
@@ -280,14 +308,12 @@ const PocVariableChip = Node$1.create({
280
308
  dom.innerHTML = sanitizeRichHtml(node.attrs.html);
281
309
  dom.addEventListener("click", (event) => {
282
310
  event.preventDefault();
283
- editor.view.dom.dispatchEvent(new CustomEvent("poc:variable-click", {
284
- bubbles: true,
285
- detail: {
286
- variableId: node.attrs.variableId,
287
- parentBlockId: node.attrs.parentBlockId,
288
- text: node.attrs.text
289
- }
290
- }));
311
+ dispatchVariableClick(editor, {
312
+ variableId: node.attrs.variableId,
313
+ parentBlockId: node.attrs.parentBlockId,
314
+ text: node.attrs.text,
315
+ kind: "text"
316
+ });
291
317
  });
292
318
  return { dom };
293
319
  };
@@ -300,6 +326,10 @@ function variableChipHtml(currentHtml, text) {
300
326
  if (!el)
301
327
  return currentHtml;
302
328
  el.textContent = text;
329
+ if (el.hasAttribute("data-invalid-variable")) {
330
+ el.removeAttribute("data-invalid-variable");
331
+ el.removeAttribute("style");
332
+ }
303
333
  return el.outerHTML;
304
334
  }
305
335
  function readCatalog(catalog) {
@@ -636,7 +666,7 @@ function resolveTemplateVariables(html, values) {
636
666
  return { html: resolved, missing };
637
667
  }
638
668
 
639
- function escapeAttr(value) {
669
+ function escapeAttr$1(value) {
640
670
  return value.replace(/&/g, "&").replace(/"/g, """);
641
671
  }
642
672
  function escapeVaultAttr(value) {
@@ -646,7 +676,81 @@ function decodeVaultAttr(value) {
646
676
  return value.replace(/&quot;/g, '"').replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
647
677
  }
648
678
  function vaultImageHtml(src, vaultUrl) {
649
- return `<img src="${escapeAttr(src)}" data-vault-src="${escapeVaultAttr(vaultUrl)}" style="width: 420px; height: auto; max-width: 100%;">`;
679
+ return `<img src="${escapeAttr$1(src)}" data-vault-src="${escapeVaultAttr(vaultUrl)}" style="width: 420px; height: auto; max-width: 100%;">`;
680
+ }
681
+
682
+ function escapeAttr(value) {
683
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
684
+ }
685
+ function escapeRegExp(value) {
686
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
687
+ }
688
+ function swapSrcKeepRef(html, attrValue, freshUrl) {
689
+ const needle = `data-vault-src="${attrValue}"`;
690
+ if (!html.includes(needle))
691
+ return html;
692
+ const tagRe = new RegExp(`<img\\b[^>]*?${escapeRegExp(needle)}[^>]*?>`, "g");
693
+ return html.replace(tagRe, (tag) => tag.replace(/\ssrc="[^"]*"/, ` src="${escapeAttr(freshUrl)}"`));
694
+ }
695
+ async function refreshVaultImages(editor, resolveUrl, options = {}) {
696
+ if (!editor || editor.isDestroyed)
697
+ return 0;
698
+ const refs = /* @__PURE__ */ new Set();
699
+ editor.state.doc.descendants((node) => {
700
+ if (node.type.name !== "htmlIsland")
701
+ return;
702
+ for (const m of String(node.attrs.html ?? "").matchAll(/data-vault-src="([^"]+)"/g))
703
+ refs.add(m[1]);
704
+ });
705
+ if (!refs.size)
706
+ return 0;
707
+ const resolved = /* @__PURE__ */ new Map();
708
+ await Promise.all([...refs].map(async (attrValue) => {
709
+ try {
710
+ const fresh = await resolveUrl(decodeVaultAttr(attrValue));
711
+ if (!fresh)
712
+ return;
713
+ await new Promise((done) => {
714
+ const img = new Image();
715
+ const finish = () => done();
716
+ img.onload = finish;
717
+ img.onerror = finish;
718
+ setTimeout(finish, 4e3);
719
+ img.src = fresh;
720
+ });
721
+ resolved.set(attrValue, fresh);
722
+ } catch (error) {
723
+ console.error("minuta: falha ao resolver imagem do vault", attrValue, error);
724
+ }
725
+ }));
726
+ if (!resolved.size || editor.isDestroyed)
727
+ return 0;
728
+ const tr = editor.state.tr;
729
+ let touched = 0;
730
+ editor.state.doc.descendants((node, pos) => {
731
+ if (node.type.name !== "htmlIsland")
732
+ return;
733
+ let html = String(node.attrs.html ?? "");
734
+ let changed = false;
735
+ for (const [attrValue, freshUrl] of resolved) {
736
+ const next = swapSrcKeepRef(html, attrValue, freshUrl);
737
+ if (next !== html) {
738
+ html = next;
739
+ changed = true;
740
+ }
741
+ }
742
+ if (changed) {
743
+ tr.setNodeMarkup(pos, void 0, { ...node.attrs, html });
744
+ touched++;
745
+ }
746
+ });
747
+ if (!touched)
748
+ return 0;
749
+ tr.setMeta("addToHistory", false);
750
+ for (const [key, value] of Object.entries(options.meta ?? {}))
751
+ tr.setMeta(key, value);
752
+ editor.view.dispatch(tr);
753
+ return touched;
650
754
  }
651
755
 
652
756
  function h(tag, attrs = {}, children = []) {
@@ -1650,7 +1754,8 @@ function createMinutaEditor(element, opts) {
1650
1754
  opts.onVariableClick?.({
1651
1755
  variableId: detail.variableId,
1652
1756
  parentBlockId: detail.parentBlockId ?? null,
1653
- text: String(detail.text ?? "")
1757
+ text: String(detail.text ?? ""),
1758
+ kind: detail.kind === "image" || detail.kind === "missingImage" ? detail.kind : "text"
1654
1759
  });
1655
1760
  }
1656
1761
  function variableTargetElement(variableId) {
@@ -1661,18 +1766,7 @@ function createMinutaEditor(element, opts) {
1661
1766
  const img = sheet.querySelector(`img[data-variable-id="${id}"]`);
1662
1767
  if (img)
1663
1768
  return img;
1664
- const ed = tiptap;
1665
- if (!ed || ed.isDestroyed)
1666
- return null;
1667
- let found = null;
1668
- ed.state.doc.descendants((node, pos) => {
1669
- if (found || node.type.name !== "missingImage" || node.attrs.variableId !== variableId)
1670
- return;
1671
- const dom = ed.view.nodeDOM(pos);
1672
- if (dom instanceof HTMLElement)
1673
- found = dom;
1674
- });
1675
- return found;
1769
+ return sheet.querySelector(`.poc-missing-image [data-variable-id="${id}"]`);
1676
1770
  }
1677
1771
  function scrollToVariable(variableId) {
1678
1772
  const chip = variableTargetElement(variableId);
@@ -1939,6 +2033,12 @@ function createMinutaEditor(element, opts) {
1939
2033
  setVariableValue,
1940
2034
  setVariableImage,
1941
2035
  variablesInDocument,
2036
+ refreshVaultImages(resolveUrl) {
2037
+ const ed = tiptap;
2038
+ if (!ed || ed.isDestroyed)
2039
+ return Promise.resolve(0);
2040
+ return refreshVaultImages(ed, resolveUrl, { meta: { [POC_ASSET_SWAP]: true } });
2041
+ },
1942
2042
  schedulePaginate,
1943
2043
  refreshChrome,
1944
2044
  totalPages: () => totalPages,
@@ -1958,4 +2058,4 @@ function createMinutaEditor(element, opts) {
1958
2058
  return api;
1959
2059
  }
1960
2060
 
1961
- 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, computePocBreaks, createMinutaEditor, decodeVaultAttr, escapeHtml, escapeVaultAttr, extractTemplateVariables, iconSvg, pocPageKey, renumberPocFootnotes, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, variableChipHtml, vaultImageHtml };
2061
+ 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, computePocBreaks, createMinutaEditor, decodeVaultAttr, dispatchVariableClick, escapeHtml, escapeVaultAttr, extractTemplateVariables, iconSvg, pocPageKey, refreshVaultImages, renumberPocFootnotes, resolveTemplateVariables, sanitizeFootnoteHtml, sanitizeRichHtml, variableChipHtml, vaultImageHtml };
@@ -19,11 +19,15 @@ import { PluginKey, Plugin } from '@tiptap/pm/state';
19
19
  * algoritmo sempre enxerga o fluxo "sem paginação" e converge (recomputar
20
20
  * com chrome na tela produz os mesmos breaks → sem loop de layout).
21
21
  *
22
- * Regras de quebra:
23
- * - quebra somente entre nós (parágrafo/título/ilha) — nó mais alto que a
24
- * página flui e as páginas internas são contadas, sem chrome no meio;
25
- * - keep-with-next: título não fica órfão no fim da página (a quebra sobe
26
- * para antes do título).
22
+ * Regras de quebra (as mesmas que o Word aplica ao refluir o documento):
23
+ * - a unidade é o bloco-FOLHA: parágrafo, título, ilha (imagem/lista/svg),
24
+ * linha de colunas, linha de tabela. Citação, container simples e lista
25
+ * real são só recipientes — a quebra entra neles e cai entre os filhos;
26
+ * - parágrafo parte entre linhas (viúvas/órfãs de 2 linhas), como no Word;
27
+ * - nó-folha mais alto que a página flui e as páginas internas são contadas,
28
+ * sem chrome no meio;
29
+ * - keep-with-next: título (h1–h4 ou parágrafo curto em negrito/caixa alta)
30
+ * não fica órfão no fim da página — a quebra sobe para antes dele.
27
31
  */
28
32
  interface PocPageConfig {
29
33
  pageHeight: number;
@@ -74,6 +78,13 @@ interface PocPageBreak {
74
78
  * Word quebra naturalmente, e o preview só antecipa onde.
75
79
  */
76
80
  soft?: boolean;
81
+ /**
82
+ * quebra pedida pelo TEMPLATE (parágrafo-marcador "PAGEBREAK"). É a única
83
+ * que vira pageBreakBefore no DOCX: as demais são só a previsão do preview
84
+ * de onde o Word vai quebrar, e o Word decide sozinho — forçá-las deixava
85
+ * o pé da página vazio sempre que ele media o conteúdo diferente daqui.
86
+ */
87
+ manual?: boolean;
77
88
  /** notas cujos marcadores estão nesta página — desenhadas acima do rodapé */
78
89
  notes?: PocPageNote[];
79
90
  /** altura reservada pelas notas (já descontada do filler) */
@@ -100,6 +111,14 @@ declare function buildPocHeaderEl(cfg: PocPageConfig): HTMLElement;
100
111
  declare function buildPocFooterEl(cfg: PocPageConfig, pageNo: number, total: number): HTMLElement;
101
112
  /** área de notas de rodapé: filete + notas, no pé da área útil (como no Word) */
102
113
  declare function buildPocNotesEl(notes: PocPageNote[]): HTMLElement;
114
+ /**
115
+ * O bloco é um título, para efeito de keep-with-next? h1–h4, ou um parágrafo
116
+ * de UMA linha, curto, todo em negrito ou em caixa alta — é assim que os
117
+ * templates marcam seções ("PRELIMINARMENTE", "DO MÉRITO"): com `<p>`
118
+ * estilizado, não com heading. O export usa a mesma régua para pedir ao Word
119
+ * que mantenha o título junto do parágrafo seguinte (keepNext).
120
+ */
121
+ declare function pocLooksLikeTitle(dom: HTMLElement): boolean;
103
122
  declare function computePocBreaks(view: EditorView, cfg: PocPageConfig, sheet: HTMLElement): {
104
123
  breaks: PocPageBreak[];
105
124
  total: number;
@@ -109,6 +128,13 @@ declare function computePocBreaks(view: EditorView, cfg: PocPageConfig, sheet: H
109
128
  }[];
110
129
  lastNotes: PocPageNote[];
111
130
  };
131
+ /**
132
+ * O nó é só um RECIPIENTE para a paginação — a quebra entra nele e cai entre
133
+ * os filhos? Citação, lista real, tabela (entre linhas) e container simples
134
+ * sem borda nem fundo. Linha de colunas e caixa pintada (borda/fundo) são
135
+ * unidades visuais: partem só se forem mais altas que a página.
136
+ */
137
+ declare function pocDescendsInto(node: Node): boolean;
112
138
  declare function isPocFlexRow(node: Node): boolean;
113
139
  /** conteúdo visível = texto, imagem com src preenchido ou svg (imgs vazias do pipeline não contam) */
114
140
  declare function pocNodeHasVisibleContent(node: Node): boolean;
@@ -116,7 +142,7 @@ declare function pocNodeHasVisibleContent(node: Node): boolean;
116
142
  * A célula/linha PINTA alguma coisa (borda ou fundo)?
117
143
  *
118
144
  * Uma coluna sem texto mas com borda não é espaço sobrando: é estrutura. A
119
- * folha de rosto da Telefônica desenha uma timeline com `border-right` numa
145
+ * folha de rosto de um template desenha uma timeline com `border-right` numa
120
146
  * coluna VAZIA (o eixo central) e `border-bottom` alternando entre as duas —
121
147
  * colapsar a coluna "vazia" apaga o eixo e centraliza o que devia ficar
122
148
  * alternando esquerda/direita.
@@ -162,5 +188,5 @@ declare function pocExportDocx(editor: Editor, margins: {
162
188
  left: number;
163
189
  }, chrome?: PocDocxChrome, options?: PocDocxExportOptions): Promise<Blob>;
164
190
 
165
- export { PAGINATE_META as e, pocChromeFlowHeight as f, buildPocHeaderEl as g, buildPocFooterEl as h, isPocChromeCanvas as i, buildPocNotesEl as j, computePocBreaks as k, isPocFlexRow as l, pocNodeHasVisibleContent as m, pocNodePaintsBox as n, pocLoneCellIndex as o, pocPageKey as p, computePocLoneRows as r, breaksEqual as s, PocPaginationPlugin as t, pocExportDocx as u };
166
- export type { PocPageConfig as P, PocDocxChrome as a, PocDocxExportOptions as b, PocPageNote as c, PocPageBreak as d, PocLoneRow as q };
191
+ export { PAGINATE_META as e, pocChromeFlowHeight as f, buildPocHeaderEl as g, buildPocFooterEl as h, isPocChromeCanvas as i, buildPocNotesEl as j, pocLooksLikeTitle as k, computePocBreaks as l, pocDescendsInto as m, isPocFlexRow as n, pocNodeHasVisibleContent as o, pocPageKey as p, pocNodePaintsBox as q, pocLoneCellIndex as r, computePocLoneRows as t, breaksEqual as u, PocPaginationPlugin as v, pocExportDocx as w };
192
+ export type { PocPageConfig as P, PocDocxChrome as a, PocDocxExportOptions as b, PocPageNote as c, PocPageBreak as d, PocLoneRow as s };
@@ -19,11 +19,15 @@ import { PluginKey, Plugin } from '@tiptap/pm/state';
19
19
  * algoritmo sempre enxerga o fluxo "sem paginação" e converge (recomputar
20
20
  * com chrome na tela produz os mesmos breaks → sem loop de layout).
21
21
  *
22
- * Regras de quebra:
23
- * - quebra somente entre nós (parágrafo/título/ilha) — nó mais alto que a
24
- * página flui e as páginas internas são contadas, sem chrome no meio;
25
- * - keep-with-next: título não fica órfão no fim da página (a quebra sobe
26
- * para antes do título).
22
+ * Regras de quebra (as mesmas que o Word aplica ao refluir o documento):
23
+ * - a unidade é o bloco-FOLHA: parágrafo, título, ilha (imagem/lista/svg),
24
+ * linha de colunas, linha de tabela. Citação, container simples e lista
25
+ * real são só recipientes — a quebra entra neles e cai entre os filhos;
26
+ * - parágrafo parte entre linhas (viúvas/órfãs de 2 linhas), como no Word;
27
+ * - nó-folha mais alto que a página flui e as páginas internas são contadas,
28
+ * sem chrome no meio;
29
+ * - keep-with-next: título (h1–h4 ou parágrafo curto em negrito/caixa alta)
30
+ * não fica órfão no fim da página — a quebra sobe para antes dele.
27
31
  */
28
32
  interface PocPageConfig {
29
33
  pageHeight: number;
@@ -74,6 +78,13 @@ interface PocPageBreak {
74
78
  * Word quebra naturalmente, e o preview só antecipa onde.
75
79
  */
76
80
  soft?: boolean;
81
+ /**
82
+ * quebra pedida pelo TEMPLATE (parágrafo-marcador "PAGEBREAK"). É a única
83
+ * que vira pageBreakBefore no DOCX: as demais são só a previsão do preview
84
+ * de onde o Word vai quebrar, e o Word decide sozinho — forçá-las deixava
85
+ * o pé da página vazio sempre que ele media o conteúdo diferente daqui.
86
+ */
87
+ manual?: boolean;
77
88
  /** notas cujos marcadores estão nesta página — desenhadas acima do rodapé */
78
89
  notes?: PocPageNote[];
79
90
  /** altura reservada pelas notas (já descontada do filler) */
@@ -100,6 +111,14 @@ declare function buildPocHeaderEl(cfg: PocPageConfig): HTMLElement;
100
111
  declare function buildPocFooterEl(cfg: PocPageConfig, pageNo: number, total: number): HTMLElement;
101
112
  /** área de notas de rodapé: filete + notas, no pé da área útil (como no Word) */
102
113
  declare function buildPocNotesEl(notes: PocPageNote[]): HTMLElement;
114
+ /**
115
+ * O bloco é um título, para efeito de keep-with-next? h1–h4, ou um parágrafo
116
+ * de UMA linha, curto, todo em negrito ou em caixa alta — é assim que os
117
+ * templates marcam seções ("PRELIMINARMENTE", "DO MÉRITO"): com `<p>`
118
+ * estilizado, não com heading. O export usa a mesma régua para pedir ao Word
119
+ * que mantenha o título junto do parágrafo seguinte (keepNext).
120
+ */
121
+ declare function pocLooksLikeTitle(dom: HTMLElement): boolean;
103
122
  declare function computePocBreaks(view: EditorView, cfg: PocPageConfig, sheet: HTMLElement): {
104
123
  breaks: PocPageBreak[];
105
124
  total: number;
@@ -109,6 +128,13 @@ declare function computePocBreaks(view: EditorView, cfg: PocPageConfig, sheet: H
109
128
  }[];
110
129
  lastNotes: PocPageNote[];
111
130
  };
131
+ /**
132
+ * O nó é só um RECIPIENTE para a paginação — a quebra entra nele e cai entre
133
+ * os filhos? Citação, lista real, tabela (entre linhas) e container simples
134
+ * sem borda nem fundo. Linha de colunas e caixa pintada (borda/fundo) são
135
+ * unidades visuais: partem só se forem mais altas que a página.
136
+ */
137
+ declare function pocDescendsInto(node: Node): boolean;
112
138
  declare function isPocFlexRow(node: Node): boolean;
113
139
  /** conteúdo visível = texto, imagem com src preenchido ou svg (imgs vazias do pipeline não contam) */
114
140
  declare function pocNodeHasVisibleContent(node: Node): boolean;
@@ -116,7 +142,7 @@ declare function pocNodeHasVisibleContent(node: Node): boolean;
116
142
  * A célula/linha PINTA alguma coisa (borda ou fundo)?
117
143
  *
118
144
  * Uma coluna sem texto mas com borda não é espaço sobrando: é estrutura. A
119
- * folha de rosto da Telefônica desenha uma timeline com `border-right` numa
145
+ * folha de rosto de um template desenha uma timeline com `border-right` numa
120
146
  * coluna VAZIA (o eixo central) e `border-bottom` alternando entre as duas —
121
147
  * colapsar a coluna "vazia" apaga o eixo e centraliza o que devia ficar
122
148
  * alternando esquerda/direita.
@@ -162,5 +188,5 @@ declare function pocExportDocx(editor: Editor, margins: {
162
188
  left: number;
163
189
  }, chrome?: PocDocxChrome, options?: PocDocxExportOptions): Promise<Blob>;
164
190
 
165
- export { PAGINATE_META as e, pocChromeFlowHeight as f, buildPocHeaderEl as g, buildPocFooterEl as h, isPocChromeCanvas as i, buildPocNotesEl as j, computePocBreaks as k, isPocFlexRow as l, pocNodeHasVisibleContent as m, pocNodePaintsBox as n, pocLoneCellIndex as o, pocPageKey as p, computePocLoneRows as r, breaksEqual as s, PocPaginationPlugin as t, pocExportDocx as u };
166
- export type { PocPageConfig as P, PocDocxChrome as a, PocDocxExportOptions as b, PocPageNote as c, PocPageBreak as d, PocLoneRow as q };
191
+ export { PAGINATE_META as e, pocChromeFlowHeight as f, buildPocHeaderEl as g, buildPocFooterEl as h, isPocChromeCanvas as i, buildPocNotesEl as j, pocLooksLikeTitle as k, computePocBreaks as l, pocDescendsInto as m, isPocFlexRow as n, pocNodeHasVisibleContent as o, pocPageKey as p, pocNodePaintsBox as q, pocLoneCellIndex as r, computePocLoneRows as t, breaksEqual as u, PocPaginationPlugin as v, pocExportDocx as w };
192
+ export type { PocPageConfig as P, PocDocxChrome as a, PocDocxExportOptions as b, PocPageNote as c, PocPageBreak as d, PocLoneRow as s };