documents.js 4.1.0 → 4.2.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 +4 -2
- package/dist/codecs/registry.cjs +1 -1
- package/dist/codecs/registry.js +1 -1
- package/dist/convert/composition.cjs +1 -1
- package/dist/convert/composition.js +1 -1
- package/dist/edit/docx/content.cjs +1 -0
- package/dist/edit/docx/content.js +1 -0
- package/dist/edit/docx/paragraph.cjs +18 -1
- package/dist/edit/docx/paragraph.d.cts +3 -0
- package/dist/edit/docx/paragraph.d.ts +3 -0
- package/dist/edit/docx/paragraph.js +18 -1
- package/dist/edit/docx/props.cjs +1 -0
- package/dist/edit/docx/props.js +1 -0
- package/dist/edit/markdown/editor.cjs +1 -1
- package/dist/edit/markdown/editor.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/layout/reconstruct.cjs +43 -10
- package/dist/layout/reconstruct.js +43 -10
- package/dist/markdown/read.cjs +15 -1
- package/dist/markdown/read.js +16 -2
- package/dist/markdown/write.cjs +7 -0
- package/dist/markdown/write.d.cts +2 -1
- package/dist/markdown/write.d.ts +2 -1
- package/dist/markdown/write.js +8 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ const pdfFromXlsx = xlsxToPdf(xlsxBytes); // composes xlsxToOds -> odsToPdf inte
|
|
|
116
116
|
const xlsxBytes2 = pdfToXlsx(pdfFromXlsx); // composes pdfToOds -> odsToXlsx internally
|
|
117
117
|
|
|
118
118
|
const pdfFromMarkdown = markdownToPdf(markdownBytes);
|
|
119
|
-
const markdownBytes2 = pdfToMarkdown(pdfFromMarkdown); // the lossiest conversion in the whole package -- see Fidelity
|
|
119
|
+
const markdownBytes2 = pdfToMarkdown(pdfFromMarkdown); // the lossiest conversion in the whole package -- see Fidelity; it does carry page boundaries (one '<!-- page break -->' marker per page) and rank-inferred heading levels
|
|
120
120
|
|
|
121
121
|
const pdfFromCsv = csvToPdf(csvBytes); // composes csvToOds -> odsToPdf internally
|
|
122
122
|
const csvBytes2 = pdfToCsv(pdfFromCsv); // composes pdfToOds -> odsToCsv internally; recovers what was printed, then heuristically re-types it
|
|
@@ -127,6 +127,8 @@ const svgBytes2 = pdfToSvg(pdfFromSvg); // readPdf -> reconstructDrawing -> buil
|
|
|
127
127
|
|
|
128
128
|
Each accepts an optional `signal` (`AbortSignal`) and either `onSubstitution` (X → PDF, called per character not representable in a standard-14 font) or `sink` (PDF → X, called per recoverable parse diagnostic). Every X → PDF conversion additionally accepts `fonts` (extra `ProvidedFont` faces) and `onFontSubstitution` (per family+weight+style that resolved to something else). Neither is needed for the common case — see [Fonts](#fonts).
|
|
129
129
|
|
|
130
|
+
**Cancellation granularity, for CPU-metered runtimes** (ExaDev/documents.js#585): every conversion here is synchronous end to end, and the `signal` is honoured at page boundaries — once per page in pdf-codec's `readPdf`/`writePdf` page loops and once per page in each of this package's four reconstructors (wordprocessing/presentation/drawing/spreadsheet). An abort arriving mid-conversion therefore takes effect at the next page boundary, not instantly: a single page's content-stream interpretation, pdf-codec's document-open phase, and the per-target build/encode stage after reconstruction are not interruptible, and parse cost is roughly linear in decompressed content length — budget for the worst single page, not the page count. A shared `AbortSignal` makes a deadline enforceable at that granularity on Cloudflare Workers; it cannot convert a synchronous conversion into a resumable or streaming one (an async page-at-a-time API is a deliberate non-goal of the current surface — see pdf-codec's README for the same statement from the codec side).
|
|
131
|
+
|
|
130
132
|
### Cross-format bridges
|
|
131
133
|
|
|
132
134
|
Twenty-four bridge functions across twelve pairs bypass the PDF pivot where a direct path exists. Eight same-variant direct-copy pairs (`odtToDocx`/`docxToOdt`, `odpToPptx`/`pptxToOdp`, `odsToXlsx`/`xlsxToOds`, `csvToOds`/`odsToCsv`, `csvToXlsx`/`xlsxToCsv`, `svgToOdg`/`odgToSvg`, `markdownToDocx`/`docxToMarkdown`, `markdownToOdt`/`odtToMarkdown`) compose a direct `readXContent` → `buildYPackage` pivot copy — the csv pairs are one hop to its spreadsheet siblings, so csv never needs PDF to reach ods or xlsx, and `svgToOdg`/`odgToSvg` bridge svg to its drawing sibling odg the same way. Two cross-variant semantic-transform pairs (`docxToPptx`/`pptxToDocx`, `odtToOdp`/`odpToOdt`) go through `src/convert/variant-bridges.ts`. Two PDF-composed pairs (`xlsxToMarkdown`/`markdownToXlsx`, `csvToMarkdown`/`markdownToCsv`) route through PDF internally — the lossiest conversions in the package.
|
|
@@ -716,7 +718,7 @@ Read as **row → column**. `✓` lossless, `~` bounded, `✗` lossy, `✗✗` s
|
|
|
716
718
|
|
|
717
719
|
**PDF → ods** recovers what was printed, not what was entered. The printed string always survives in `displayText`; re-typed `value` is explicitly probabilistic inference.
|
|
718
720
|
|
|
719
|
-
**`markdownToPdf`/`pdfToMarkdown`** is the lossiest round trip: `markdownToPdf` is faithful, but `pdfToMarkdown` stacks reconstruction lossiness PLUS markdown's coarser vocabulary (no colour, font, size, alignment). The PDF-composed markdown bridges (`xlsxToMarkdown`/`markdownToXlsx`, `csvToMarkdown`/`markdownToCsv`) stack the same two losses in both directions — hence their `✗✗` cells.
|
|
721
|
+
**`markdownToPdf`/`pdfToMarkdown`** is the lossiest round trip: `markdownToPdf` is faithful, but `pdfToMarkdown` stacks reconstruction lossiness PLUS markdown's coarser vocabulary (no colour, font, size, alignment). Two structure signals do survive it (ExaDev/documents.js#584): every page boundary arrives as an exact `<!-- page break -->` marker (one per boundary — the one fact a rendered PDF states precisely), and headings are inferred from font size — each distinct size at least 2pt above the document's modal body size is a heading, ranked largest-first into `Heading1..6`, which inverts this package's own heading render sizes exactly and is a heuristic (the well-worn "largest text is the title" reading) for any other producer. Tables reach markdown as GFM pipe tables wherever the gridline-lattice gate succeeds; a table rendered without drawn gridlines (which includes every `markdownToPdf`-authored one, markdown carrying no border concept) correctly comes back as tab-separated prose rather than invented structure. The PDF-composed markdown bridges (`xlsxToMarkdown`/`markdownToXlsx`, `csvToMarkdown`/`markdownToCsv`) stack the same two losses in both directions — hence their `✗✗` cells.
|
|
720
722
|
|
|
721
723
|
**The six same-variant bridge pairs** (odt⇄docx, odp⇄pptx, ods⇄xlsx, csv⇄ods, csv⇄xlsx, svg⇄odg) bypass PDF entirely — no layout engine, no reconstruction. Text, styling, tables, lists, rotated shapes survive completely. `ods⇄xlsx` has small format-boundary limits (time cells, formula dialects). Embedded formulas survive `odtToDocx` as real OOXML math. The csv pairs are bounded by what csv itself carries: toward ods/xlsx nothing the csv had is lost, while writing to csv collapses each cell to its `displayText` — formulas become their rendered values, formatting disappears, and a multi-sheet source must name the sheet it wants. The svg pair carries the six vector primitives losslessly in both directions; its one asymmetry is paint defaults — SVG's absent-fill-is-black versus a drawing frame's no-fill.
|
|
722
724
|
|
package/dist/codecs/registry.cjs
CHANGED
|
@@ -5,8 +5,8 @@ const require_edit_odt_content = require("../edit/odt/content.cjs");
|
|
|
5
5
|
const require_edit_odp_content = require("../edit/odp/content.cjs");
|
|
6
6
|
const require_edit_ods_content = require("../edit/ods/content.cjs");
|
|
7
7
|
const require_edit_odg_content = require("../edit/odg/content.cjs");
|
|
8
|
-
const require_markdown_read = require("../markdown/read.cjs");
|
|
9
8
|
const require_markdown_write = require("../markdown/write.cjs");
|
|
9
|
+
const require_markdown_read = require("../markdown/read.cjs");
|
|
10
10
|
const require_ooxml_docx_read = require("../ooxml/docx/read.cjs");
|
|
11
11
|
const require_ooxml_pptx_read = require("../ooxml/pptx/read.cjs");
|
|
12
12
|
const require_odf_formula_read = require("../odf/formula/read.cjs");
|
package/dist/codecs/registry.js
CHANGED
|
@@ -4,8 +4,8 @@ import { buildOdtPackage } from "../edit/odt/content.js";
|
|
|
4
4
|
import { buildOdpPackage } from "../edit/odp/content.js";
|
|
5
5
|
import { buildOdsPackage } from "../edit/ods/content.js";
|
|
6
6
|
import { buildOdgPackage } from "../edit/odg/content.js";
|
|
7
|
-
import { readMarkdownContent } from "../markdown/read.js";
|
|
8
7
|
import { buildMarkdownText } from "../markdown/write.js";
|
|
8
|
+
import { readMarkdownContent } from "../markdown/read.js";
|
|
9
9
|
import { readDocxContent as readDocxContent$1 } from "../ooxml/docx/read.js";
|
|
10
10
|
import { readPptxContent as readPptxContent$1 } from "../ooxml/pptx/read.js";
|
|
11
11
|
import { readOdfFormulaContent } from "../odf/formula/read.js";
|
|
@@ -5,8 +5,8 @@ const require_edit_odt_content = require("../edit/odt/content.cjs");
|
|
|
5
5
|
const require_edit_odp_content = require("../edit/odp/content.cjs");
|
|
6
6
|
const require_edit_ods_content = require("../edit/ods/content.cjs");
|
|
7
7
|
const require_edit_odg_content = require("../edit/odg/content.cjs");
|
|
8
|
-
const require_markdown_read = require("../markdown/read.cjs");
|
|
9
8
|
const require_markdown_write = require("../markdown/write.cjs");
|
|
9
|
+
const require_markdown_read = require("../markdown/read.cjs");
|
|
10
10
|
const require_ooxml_docx_read = require("../ooxml/docx/read.cjs");
|
|
11
11
|
const require_ooxml_pptx_read = require("../ooxml/pptx/read.cjs");
|
|
12
12
|
const require_odf_odt_read = require("../odf/odt/read.cjs");
|
|
@@ -4,8 +4,8 @@ import { buildOdtPackage } from "../edit/odt/content.js";
|
|
|
4
4
|
import { buildOdpPackage } from "../edit/odp/content.js";
|
|
5
5
|
import { buildOdsPackage } from "../edit/ods/content.js";
|
|
6
6
|
import { buildOdgPackage } from "../edit/odg/content.js";
|
|
7
|
-
import { readMarkdownContent as readMarkdownContent$1 } from "../markdown/read.js";
|
|
8
7
|
import { buildMarkdownText } from "../markdown/write.js";
|
|
8
|
+
import { readMarkdownContent as readMarkdownContent$1 } from "../markdown/read.js";
|
|
9
9
|
import { readDocxContent as readDocxContent$1 } from "../ooxml/docx/read.js";
|
|
10
10
|
import { readPptxContent as readPptxContent$1 } from "../ooxml/pptx/read.js";
|
|
11
11
|
import { readOdtContent as readOdtContent$1 } from "../odf/odt/read.js";
|
|
@@ -123,6 +123,7 @@ function populateParagraph(paragraph, block) {
|
|
|
123
123
|
paragraph.styleId = block.styleId;
|
|
124
124
|
paragraph.alignment = block.alignment;
|
|
125
125
|
paragraph.list = block.list;
|
|
126
|
+
if (block.headingLevel !== void 0) paragraph.headingLevel = block.headingLevel;
|
|
126
127
|
if (block.spacingBeforePt !== void 0) paragraph.spacingBeforePt = block.spacingBeforePt;
|
|
127
128
|
if (block.spacingAfterPt !== void 0) paragraph.spacingAfterPt = block.spacingAfterPt;
|
|
128
129
|
if (block.lineSpacing !== void 0) paragraph.lineSpacing = block.lineSpacing;
|
|
@@ -122,6 +122,7 @@ function populateParagraph(paragraph, block) {
|
|
|
122
122
|
paragraph.styleId = block.styleId;
|
|
123
123
|
paragraph.alignment = block.alignment;
|
|
124
124
|
paragraph.list = block.list;
|
|
125
|
+
if (block.headingLevel !== void 0) paragraph.headingLevel = block.headingLevel;
|
|
125
126
|
if (block.spacingBeforePt !== void 0) paragraph.spacingBeforePt = block.spacingBeforePt;
|
|
126
127
|
if (block.spacingAfterPt !== void 0) paragraph.spacingAfterPt = block.spacingAfterPt;
|
|
127
128
|
if (block.lineSpacing !== void 0) paragraph.lineSpacing = block.lineSpacing;
|
|
@@ -208,6 +208,22 @@ var DocxParagraph = class {
|
|
|
208
208
|
const numPr = require_xml_edit.getOrCreateChildElement(pPr, "w:numPr", require_edit_docx_props.PPR_ORDER, () => require_xml_fragment.el("w:numPr"));
|
|
209
209
|
numPr.children = [require_xml_fragment.el("w:ilvl", { "w:val": String(value.level) }), require_xml_fragment.el("w:numId", { "w:val": value.numId })];
|
|
210
210
|
}
|
|
211
|
+
get headingLevel() {
|
|
212
|
+
const pPr = this.pPr(false);
|
|
213
|
+
const outlineLvl = pPr === void 0 ? void 0 : directChild(pPr, "w:outlineLvl");
|
|
214
|
+
const val = outlineLvl === void 0 ? void 0 : (0, ooxml_js.attr)(outlineLvl, "w:val");
|
|
215
|
+
return val === void 0 ? void 0 : Number(val) + 1;
|
|
216
|
+
}
|
|
217
|
+
set headingLevel(value) {
|
|
218
|
+
if (value === void 0) {
|
|
219
|
+
const pPr = this.pPr(false);
|
|
220
|
+
const existing = pPr === void 0 ? void 0 : directChild(pPr, "w:outlineLvl");
|
|
221
|
+
if (existing !== void 0 && pPr !== void 0) require_xml_edit.removeChild(pPr.children, existing);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const outlineLvl = require_xml_edit.getOrCreateChildElement(this.pPr(true), "w:outlineLvl", require_edit_docx_props.PPR_ORDER, () => require_xml_fragment.el("w:outlineLvl"));
|
|
225
|
+
require_xml_edit.setAttr(outlineLvl, "w:val", String(value - 1));
|
|
226
|
+
}
|
|
211
227
|
appendOfficeMath(mathml) {
|
|
212
228
|
const node = this.live();
|
|
213
229
|
const result = require_omml_write.buildOfficeMathParagraph(mathml);
|
|
@@ -256,10 +272,11 @@ var DocxParagraph = class {
|
|
|
256
272
|
};
|
|
257
273
|
function buildParagraph(init = {}) {
|
|
258
274
|
const paragraph = require_xml_fragment.el("w:p");
|
|
259
|
-
if (init.styleId !== void 0 || init.alignment !== void 0) {
|
|
275
|
+
if (init.styleId !== void 0 || init.alignment !== void 0 || init.headingLevel !== void 0) {
|
|
260
276
|
const pPr = require_xml_fragment.el("w:pPr");
|
|
261
277
|
if (init.styleId !== void 0) pPr.children.push(require_xml_fragment.el("w:pStyle", { "w:val": init.styleId }));
|
|
262
278
|
if (init.alignment !== void 0) pPr.children.push(require_xml_fragment.el("w:jc", { "w:val": init.alignment === "justify" ? "both" : init.alignment }));
|
|
279
|
+
if (init.headingLevel !== void 0) pPr.children.push(require_xml_fragment.el("w:outlineLvl", { "w:val": String(init.headingLevel - 1) }));
|
|
263
280
|
paragraph.children.push(pPr);
|
|
264
281
|
}
|
|
265
282
|
if (init.text !== void 0) paragraph.children.push(require_edit_docx_run.buildRun({ text: init.text }));
|
|
@@ -8,6 +8,7 @@ import { Package, XmlElement, XmlNode } from "ooxml.js";
|
|
|
8
8
|
interface ParagraphInit {
|
|
9
9
|
readonly text?: string;
|
|
10
10
|
readonly styleId?: string;
|
|
11
|
+
readonly headingLevel?: number;
|
|
11
12
|
readonly alignment?: 'left' | 'center' | 'right' | 'justify';
|
|
12
13
|
}
|
|
13
14
|
interface ImageMediaContext {
|
|
@@ -47,6 +48,8 @@ declare class DocxParagraph {
|
|
|
47
48
|
set indentFirstLinePt(value: number | undefined);
|
|
48
49
|
get list(): ContentListMembership | undefined;
|
|
49
50
|
set list(value: ContentListMembership | undefined);
|
|
51
|
+
get headingLevel(): number | undefined;
|
|
52
|
+
set headingLevel(value: number | undefined);
|
|
50
53
|
appendOfficeMath(mathml: readonly MathMlNode$1[]): OmmlWriteResult & {
|
|
51
54
|
readonly written: boolean;
|
|
52
55
|
};
|
|
@@ -8,6 +8,7 @@ import { ContentListMembership, ContentVector } from "document-schema.js";
|
|
|
8
8
|
interface ParagraphInit {
|
|
9
9
|
readonly text?: string;
|
|
10
10
|
readonly styleId?: string;
|
|
11
|
+
readonly headingLevel?: number;
|
|
11
12
|
readonly alignment?: 'left' | 'center' | 'right' | 'justify';
|
|
12
13
|
}
|
|
13
14
|
interface ImageMediaContext {
|
|
@@ -47,6 +48,8 @@ declare class DocxParagraph {
|
|
|
47
48
|
set indentFirstLinePt(value: number | undefined);
|
|
48
49
|
get list(): ContentListMembership | undefined;
|
|
49
50
|
set list(value: ContentListMembership | undefined);
|
|
51
|
+
get headingLevel(): number | undefined;
|
|
52
|
+
set headingLevel(value: number | undefined);
|
|
50
53
|
appendOfficeMath(mathml: readonly MathMlNode$1[]): OmmlWriteResult & {
|
|
51
54
|
readonly written: boolean;
|
|
52
55
|
};
|
|
@@ -207,6 +207,22 @@ var DocxParagraph = class {
|
|
|
207
207
|
const numPr = getOrCreateChildElement(pPr, "w:numPr", PPR_ORDER, () => el("w:numPr"));
|
|
208
208
|
numPr.children = [el("w:ilvl", { "w:val": String(value.level) }), el("w:numId", { "w:val": value.numId })];
|
|
209
209
|
}
|
|
210
|
+
get headingLevel() {
|
|
211
|
+
const pPr = this.pPr(false);
|
|
212
|
+
const outlineLvl = pPr === void 0 ? void 0 : directChild(pPr, "w:outlineLvl");
|
|
213
|
+
const val = outlineLvl === void 0 ? void 0 : attr(outlineLvl, "w:val");
|
|
214
|
+
return val === void 0 ? void 0 : Number(val) + 1;
|
|
215
|
+
}
|
|
216
|
+
set headingLevel(value) {
|
|
217
|
+
if (value === void 0) {
|
|
218
|
+
const pPr = this.pPr(false);
|
|
219
|
+
const existing = pPr === void 0 ? void 0 : directChild(pPr, "w:outlineLvl");
|
|
220
|
+
if (existing !== void 0 && pPr !== void 0) removeChild(pPr.children, existing);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const outlineLvl = getOrCreateChildElement(this.pPr(true), "w:outlineLvl", PPR_ORDER, () => el("w:outlineLvl"));
|
|
224
|
+
setAttr(outlineLvl, "w:val", String(value - 1));
|
|
225
|
+
}
|
|
210
226
|
appendOfficeMath(mathml) {
|
|
211
227
|
const node = this.live();
|
|
212
228
|
const result = buildOfficeMathParagraph(mathml);
|
|
@@ -255,10 +271,11 @@ var DocxParagraph = class {
|
|
|
255
271
|
};
|
|
256
272
|
function buildParagraph(init = {}) {
|
|
257
273
|
const paragraph = el("w:p");
|
|
258
|
-
if (init.styleId !== void 0 || init.alignment !== void 0) {
|
|
274
|
+
if (init.styleId !== void 0 || init.alignment !== void 0 || init.headingLevel !== void 0) {
|
|
259
275
|
const pPr = el("w:pPr");
|
|
260
276
|
if (init.styleId !== void 0) pPr.children.push(el("w:pStyle", { "w:val": init.styleId }));
|
|
261
277
|
if (init.alignment !== void 0) pPr.children.push(el("w:jc", { "w:val": init.alignment === "justify" ? "both" : init.alignment }));
|
|
278
|
+
if (init.headingLevel !== void 0) pPr.children.push(el("w:outlineLvl", { "w:val": String(init.headingLevel - 1) }));
|
|
262
279
|
paragraph.children.push(pPr);
|
|
263
280
|
}
|
|
264
281
|
if (init.text !== void 0) paragraph.children.push(buildRun({ text: init.text }));
|
package/dist/edit/docx/props.cjs
CHANGED
package/dist/edit/docx/props.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_model_metadata = require("../../model/metadata.cjs");
|
|
3
3
|
const require_ports_clock = require("../../ports/clock.cjs");
|
|
4
|
-
const require_markdown_read = require("../../markdown/read.cjs");
|
|
5
4
|
const require_markdown_write = require("../../markdown/write.cjs");
|
|
5
|
+
const require_markdown_read = require("../../markdown/read.cjs");
|
|
6
6
|
const require_edit_markdown_paragraph = require("./paragraph.cjs");
|
|
7
7
|
const require_edit_markdown_list = require("./list.cjs");
|
|
8
8
|
const require_edit_markdown_table = require("./table.cjs");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveMetadataTimestamps } from "../../model/metadata.js";
|
|
2
2
|
import { systemClock } from "../../ports/clock.js";
|
|
3
|
-
import { readMarkdownContent as readMarkdownContent$1 } from "../../markdown/read.js";
|
|
4
3
|
import { buildMarkdownText } from "../../markdown/write.js";
|
|
4
|
+
import { readMarkdownContent as readMarkdownContent$1 } from "../../markdown/read.js";
|
|
5
5
|
import { MarkdownParagraph, buildParagraph } from "./paragraph.js";
|
|
6
6
|
import { MarkdownList } from "./list.js";
|
|
7
7
|
import { MarkdownTable, buildTable } from "./table.js";
|
package/dist/index.cjs
CHANGED
|
@@ -39,8 +39,8 @@ const require_edit_odg_editor = require("./edit/odg/editor.cjs");
|
|
|
39
39
|
const require_edit_odg_content = require("./edit/odg/content.cjs");
|
|
40
40
|
const require_latex_lower = require("./latex/lower.cjs");
|
|
41
41
|
const require_markdown_math = require("./markdown/math.cjs");
|
|
42
|
-
const require_markdown_read = require("./markdown/read.cjs");
|
|
43
42
|
const require_markdown_write = require("./markdown/write.cjs");
|
|
43
|
+
const require_markdown_read = require("./markdown/read.cjs");
|
|
44
44
|
const require_edit_markdown_run = require("./edit/markdown/run.cjs");
|
|
45
45
|
const require_edit_markdown_paragraph = require("./edit/markdown/paragraph.cjs");
|
|
46
46
|
const require_edit_markdown_list = require("./edit/markdown/list.cjs");
|
package/dist/index.js
CHANGED
|
@@ -38,8 +38,8 @@ import { OdgEditor, createOdg, openOdg } from "./edit/odg/editor.js";
|
|
|
38
38
|
import { buildOdgPackage } from "./edit/odg/content.js";
|
|
39
39
|
import { latexToFormula, lowerLatex } from "./latex/lower.js";
|
|
40
40
|
import { lowerMarkdownMath } from "./markdown/math.js";
|
|
41
|
-
import { readMarkdownContent } from "./markdown/read.js";
|
|
42
41
|
import { MarkdownConstructUnsupportedError, buildMarkdownText } from "./markdown/write.js";
|
|
42
|
+
import { readMarkdownContent } from "./markdown/read.js";
|
|
43
43
|
import { MarkdownRun } from "./edit/markdown/run.js";
|
|
44
44
|
import { MarkdownParagraph } from "./edit/markdown/paragraph.js";
|
|
45
45
|
import { MarkdownList } from "./edit/markdown/list.js";
|
|
@@ -42,8 +42,8 @@ function textItemVerticalExtent(item) {
|
|
|
42
42
|
function textItemToContentRun(item) {
|
|
43
43
|
return {
|
|
44
44
|
text: item.text,
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
...item.font.weight === "bold" ? { bold: true } : {},
|
|
46
|
+
...item.font.style === "italic" ? { italic: true } : {},
|
|
47
47
|
fontFamily: item.font.family,
|
|
48
48
|
sizePt: item.sizePt,
|
|
49
49
|
color: item.color
|
|
@@ -134,33 +134,55 @@ function estimateModalLineSpacing(lines) {
|
|
|
134
134
|
}
|
|
135
135
|
function reconstructWordprocessing(doc, options) {
|
|
136
136
|
const signal = options?.signal;
|
|
137
|
+
const headingLevels = headingSizeLevels(doc);
|
|
137
138
|
const sections = [];
|
|
138
139
|
let currentGroup = [];
|
|
139
140
|
let groupStartPageIndex = 0;
|
|
140
141
|
for (const page of doc.pages) {
|
|
141
142
|
require_ports_abort.throwIfAborted(signal);
|
|
142
143
|
if (currentGroup.length > 0 && !samePageSize(currentGroup[0], page)) {
|
|
143
|
-
sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images));
|
|
144
|
+
sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images, headingLevels));
|
|
144
145
|
groupStartPageIndex += currentGroup.length;
|
|
145
146
|
currentGroup = [];
|
|
146
147
|
}
|
|
147
148
|
currentGroup.push(page);
|
|
148
149
|
}
|
|
149
|
-
if (currentGroup.length > 0) sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images));
|
|
150
|
+
if (currentGroup.length > 0) sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images, headingLevels));
|
|
150
151
|
return {
|
|
151
152
|
kind: "wordprocessing",
|
|
152
153
|
metadata: doc.metadata,
|
|
153
154
|
sections
|
|
154
155
|
};
|
|
155
156
|
}
|
|
157
|
+
const HEADING_MIN_SIZE_DELTA_PT = 2;
|
|
158
|
+
const MAX_HEADING_LEVEL = 6;
|
|
159
|
+
function headingSizeLevels(doc) {
|
|
160
|
+
const sizes = [];
|
|
161
|
+
for (const page of doc.pages) for (const item of page.items) if (item.kind === "text") sizes.push(item.sizePt);
|
|
162
|
+
if (sizes.length === 0) return /* @__PURE__ */ new Map();
|
|
163
|
+
const bodySizePt = modeOf(sizes, .5);
|
|
164
|
+
const headingBuckets = /* @__PURE__ */ new Set();
|
|
165
|
+
for (const size of sizes) {
|
|
166
|
+
const bucket = Math.round(size / .5) * .5;
|
|
167
|
+
if (bucket - bodySizePt >= HEADING_MIN_SIZE_DELTA_PT) headingBuckets.add(bucket);
|
|
168
|
+
}
|
|
169
|
+
const levels = /* @__PURE__ */ new Map();
|
|
170
|
+
[...headingBuckets].sort((a, b) => b - a).forEach((bucket, index) => {
|
|
171
|
+
levels.set(bucket, Math.min(index + 1, MAX_HEADING_LEVEL));
|
|
172
|
+
});
|
|
173
|
+
return levels;
|
|
174
|
+
}
|
|
175
|
+
function headingLevelOf(paragraph, levels) {
|
|
176
|
+
return levels.get(modeOf(paragraph.lines.flatMap((line) => line.items.map((item) => item.sizePt)), .5));
|
|
177
|
+
}
|
|
156
178
|
function samePageSize(a, b) {
|
|
157
179
|
return a.widthPt === b.widthPt && a.heightPt === b.heightPt;
|
|
158
180
|
}
|
|
159
|
-
function buildSection(pages, startPageIndex, images) {
|
|
181
|
+
function buildSection(pages, startPageIndex, images, headingLevels) {
|
|
160
182
|
const blocks = [];
|
|
161
183
|
pages.forEach((page, i) => {
|
|
162
184
|
if (i > 0) blocks.push({ kind: "pageBreak" });
|
|
163
|
-
blocks.push(...reconstructPageBlocks(page, startPageIndex + i, images));
|
|
185
|
+
blocks.push(...reconstructPageBlocks(page, startPageIndex + i, images, headingLevels));
|
|
164
186
|
});
|
|
165
187
|
return {
|
|
166
188
|
pageSize: {
|
|
@@ -171,7 +193,7 @@ function buildSection(pages, startPageIndex, images) {
|
|
|
171
193
|
blocks
|
|
172
194
|
};
|
|
173
195
|
}
|
|
174
|
-
function reconstructPageBlocks(page, pageIndex, images) {
|
|
196
|
+
function reconstructPageBlocks(page, pageIndex, images, headingLevels) {
|
|
175
197
|
const recoveredTable = recoverTable(page, pageIndex);
|
|
176
198
|
const consumedText = recoveredTable?.consumedText;
|
|
177
199
|
const textItems = page.items.filter((i) => i.kind === "text" && consumedText?.has(i) !== true);
|
|
@@ -180,7 +202,7 @@ function reconstructPageBlocks(page, pageIndex, images) {
|
|
|
180
202
|
const positioned = [];
|
|
181
203
|
for (const paragraph of paragraphs) positioned.push({
|
|
182
204
|
yPt: paragraph.lines[0].baselineY,
|
|
183
|
-
block: paragraphToContentParagraph(paragraph, pageIndex)
|
|
205
|
+
block: paragraphToContentParagraph(paragraph, pageIndex, headingLevelOf(paragraph, headingLevels))
|
|
184
206
|
});
|
|
185
207
|
for (const img of imageItems) {
|
|
186
208
|
const asset = images[img.imageId];
|
|
@@ -231,6 +253,7 @@ function clusterIntoParagraphs(lines) {
|
|
|
231
253
|
}
|
|
232
254
|
function startsNewParagraph(prev, next, modalSpacing, dominantLeftX) {
|
|
233
255
|
if (prev.baselineY - next.baselineY > PARAGRAPH_GAP_MULTIPLIER * modalSpacing) return true;
|
|
256
|
+
if (!fontSizesClose(prev.items[0].sizePt, next.items[0].sizePt)) return true;
|
|
234
257
|
const nextLeft = next.items[0].xPt;
|
|
235
258
|
const prevLeft = prev.items[0].xPt;
|
|
236
259
|
const emPt = next.items[0].sizePt;
|
|
@@ -239,12 +262,16 @@ function startsNewParagraph(prev, next, modalSpacing, dominantLeftX) {
|
|
|
239
262
|
return nextIndented && prevAtMargin;
|
|
240
263
|
}
|
|
241
264
|
const LEFT_ALIGN_TOLERANCE_PT = 2;
|
|
242
|
-
function paragraphToContentParagraph(paragraph, pageIndex) {
|
|
265
|
+
function paragraphToContentParagraph(paragraph, pageIndex, headingLevel) {
|
|
243
266
|
const dominantLeftX = modeOf(paragraph.lines.map((l) => l.items[0].xPt), 1);
|
|
244
267
|
const result = {
|
|
245
268
|
kind: "paragraph",
|
|
246
269
|
runs: [],
|
|
247
|
-
alignment: paragraph.lines.every((l) => Math.abs(l.items[0].xPt - dominantLeftX) <= LEFT_ALIGN_TOLERANCE_PT) ? "left" : void 0
|
|
270
|
+
alignment: paragraph.lines.every((l) => Math.abs(l.items[0].xPt - dominantLeftX) <= LEFT_ALIGN_TOLERANCE_PT) ? "left" : void 0,
|
|
271
|
+
...headingLevel !== void 0 ? {
|
|
272
|
+
styleId: `Heading${String(headingLevel)}`,
|
|
273
|
+
headingLevel
|
|
274
|
+
} : {}
|
|
248
275
|
};
|
|
249
276
|
paragraph.lines.forEach((line, lineIndex) => {
|
|
250
277
|
require_layout_shared.stampFrame(result, pageIndex, lineBox(line, pageIndex));
|
|
@@ -254,6 +281,12 @@ function paragraphToContentParagraph(paragraph, pageIndex) {
|
|
|
254
281
|
}
|
|
255
282
|
pushRunsForLine(result.runs, line, pageIndex);
|
|
256
283
|
});
|
|
284
|
+
if (headingLevel !== void 0) result.runs = result.runs.map((run) => {
|
|
285
|
+
if (run.bold !== true) return run;
|
|
286
|
+
const withoutBold = { ...run };
|
|
287
|
+
delete withoutBold.bold;
|
|
288
|
+
return withoutBold;
|
|
289
|
+
});
|
|
257
290
|
return result;
|
|
258
291
|
}
|
|
259
292
|
function reconstructPresentation(doc, options) {
|
|
@@ -41,8 +41,8 @@ function textItemVerticalExtent(item) {
|
|
|
41
41
|
function textItemToContentRun(item) {
|
|
42
42
|
return {
|
|
43
43
|
text: item.text,
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
...item.font.weight === "bold" ? { bold: true } : {},
|
|
45
|
+
...item.font.style === "italic" ? { italic: true } : {},
|
|
46
46
|
fontFamily: item.font.family,
|
|
47
47
|
sizePt: item.sizePt,
|
|
48
48
|
color: item.color
|
|
@@ -133,33 +133,55 @@ function estimateModalLineSpacing(lines) {
|
|
|
133
133
|
}
|
|
134
134
|
function reconstructWordprocessing(doc, options) {
|
|
135
135
|
const signal = options?.signal;
|
|
136
|
+
const headingLevels = headingSizeLevels(doc);
|
|
136
137
|
const sections = [];
|
|
137
138
|
let currentGroup = [];
|
|
138
139
|
let groupStartPageIndex = 0;
|
|
139
140
|
for (const page of doc.pages) {
|
|
140
141
|
throwIfAborted(signal);
|
|
141
142
|
if (currentGroup.length > 0 && !samePageSize(currentGroup[0], page)) {
|
|
142
|
-
sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images));
|
|
143
|
+
sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images, headingLevels));
|
|
143
144
|
groupStartPageIndex += currentGroup.length;
|
|
144
145
|
currentGroup = [];
|
|
145
146
|
}
|
|
146
147
|
currentGroup.push(page);
|
|
147
148
|
}
|
|
148
|
-
if (currentGroup.length > 0) sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images));
|
|
149
|
+
if (currentGroup.length > 0) sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images, headingLevels));
|
|
149
150
|
return {
|
|
150
151
|
kind: "wordprocessing",
|
|
151
152
|
metadata: doc.metadata,
|
|
152
153
|
sections
|
|
153
154
|
};
|
|
154
155
|
}
|
|
156
|
+
const HEADING_MIN_SIZE_DELTA_PT = 2;
|
|
157
|
+
const MAX_HEADING_LEVEL = 6;
|
|
158
|
+
function headingSizeLevels(doc) {
|
|
159
|
+
const sizes = [];
|
|
160
|
+
for (const page of doc.pages) for (const item of page.items) if (item.kind === "text") sizes.push(item.sizePt);
|
|
161
|
+
if (sizes.length === 0) return /* @__PURE__ */ new Map();
|
|
162
|
+
const bodySizePt = modeOf(sizes, .5);
|
|
163
|
+
const headingBuckets = /* @__PURE__ */ new Set();
|
|
164
|
+
for (const size of sizes) {
|
|
165
|
+
const bucket = Math.round(size / .5) * .5;
|
|
166
|
+
if (bucket - bodySizePt >= HEADING_MIN_SIZE_DELTA_PT) headingBuckets.add(bucket);
|
|
167
|
+
}
|
|
168
|
+
const levels = /* @__PURE__ */ new Map();
|
|
169
|
+
[...headingBuckets].sort((a, b) => b - a).forEach((bucket, index) => {
|
|
170
|
+
levels.set(bucket, Math.min(index + 1, MAX_HEADING_LEVEL));
|
|
171
|
+
});
|
|
172
|
+
return levels;
|
|
173
|
+
}
|
|
174
|
+
function headingLevelOf(paragraph, levels) {
|
|
175
|
+
return levels.get(modeOf(paragraph.lines.flatMap((line) => line.items.map((item) => item.sizePt)), .5));
|
|
176
|
+
}
|
|
155
177
|
function samePageSize(a, b) {
|
|
156
178
|
return a.widthPt === b.widthPt && a.heightPt === b.heightPt;
|
|
157
179
|
}
|
|
158
|
-
function buildSection(pages, startPageIndex, images) {
|
|
180
|
+
function buildSection(pages, startPageIndex, images, headingLevels) {
|
|
159
181
|
const blocks = [];
|
|
160
182
|
pages.forEach((page, i) => {
|
|
161
183
|
if (i > 0) blocks.push({ kind: "pageBreak" });
|
|
162
|
-
blocks.push(...reconstructPageBlocks(page, startPageIndex + i, images));
|
|
184
|
+
blocks.push(...reconstructPageBlocks(page, startPageIndex + i, images, headingLevels));
|
|
163
185
|
});
|
|
164
186
|
return {
|
|
165
187
|
pageSize: {
|
|
@@ -170,7 +192,7 @@ function buildSection(pages, startPageIndex, images) {
|
|
|
170
192
|
blocks
|
|
171
193
|
};
|
|
172
194
|
}
|
|
173
|
-
function reconstructPageBlocks(page, pageIndex, images) {
|
|
195
|
+
function reconstructPageBlocks(page, pageIndex, images, headingLevels) {
|
|
174
196
|
const recoveredTable = recoverTable(page, pageIndex);
|
|
175
197
|
const consumedText = recoveredTable?.consumedText;
|
|
176
198
|
const textItems = page.items.filter((i) => i.kind === "text" && consumedText?.has(i) !== true);
|
|
@@ -179,7 +201,7 @@ function reconstructPageBlocks(page, pageIndex, images) {
|
|
|
179
201
|
const positioned = [];
|
|
180
202
|
for (const paragraph of paragraphs) positioned.push({
|
|
181
203
|
yPt: paragraph.lines[0].baselineY,
|
|
182
|
-
block: paragraphToContentParagraph(paragraph, pageIndex)
|
|
204
|
+
block: paragraphToContentParagraph(paragraph, pageIndex, headingLevelOf(paragraph, headingLevels))
|
|
183
205
|
});
|
|
184
206
|
for (const img of imageItems) {
|
|
185
207
|
const asset = images[img.imageId];
|
|
@@ -230,6 +252,7 @@ function clusterIntoParagraphs(lines) {
|
|
|
230
252
|
}
|
|
231
253
|
function startsNewParagraph(prev, next, modalSpacing, dominantLeftX) {
|
|
232
254
|
if (prev.baselineY - next.baselineY > PARAGRAPH_GAP_MULTIPLIER * modalSpacing) return true;
|
|
255
|
+
if (!fontSizesClose(prev.items[0].sizePt, next.items[0].sizePt)) return true;
|
|
233
256
|
const nextLeft = next.items[0].xPt;
|
|
234
257
|
const prevLeft = prev.items[0].xPt;
|
|
235
258
|
const emPt = next.items[0].sizePt;
|
|
@@ -238,12 +261,16 @@ function startsNewParagraph(prev, next, modalSpacing, dominantLeftX) {
|
|
|
238
261
|
return nextIndented && prevAtMargin;
|
|
239
262
|
}
|
|
240
263
|
const LEFT_ALIGN_TOLERANCE_PT = 2;
|
|
241
|
-
function paragraphToContentParagraph(paragraph, pageIndex) {
|
|
264
|
+
function paragraphToContentParagraph(paragraph, pageIndex, headingLevel) {
|
|
242
265
|
const dominantLeftX = modeOf(paragraph.lines.map((l) => l.items[0].xPt), 1);
|
|
243
266
|
const result = {
|
|
244
267
|
kind: "paragraph",
|
|
245
268
|
runs: [],
|
|
246
|
-
alignment: paragraph.lines.every((l) => Math.abs(l.items[0].xPt - dominantLeftX) <= LEFT_ALIGN_TOLERANCE_PT) ? "left" : void 0
|
|
269
|
+
alignment: paragraph.lines.every((l) => Math.abs(l.items[0].xPt - dominantLeftX) <= LEFT_ALIGN_TOLERANCE_PT) ? "left" : void 0,
|
|
270
|
+
...headingLevel !== void 0 ? {
|
|
271
|
+
styleId: `Heading${String(headingLevel)}`,
|
|
272
|
+
headingLevel
|
|
273
|
+
} : {}
|
|
247
274
|
};
|
|
248
275
|
paragraph.lines.forEach((line, lineIndex) => {
|
|
249
276
|
stampFrame(result, pageIndex, lineBox(line, pageIndex));
|
|
@@ -253,6 +280,12 @@ function paragraphToContentParagraph(paragraph, pageIndex) {
|
|
|
253
280
|
}
|
|
254
281
|
pushRunsForLine(result.runs, line, pageIndex);
|
|
255
282
|
});
|
|
283
|
+
if (headingLevel !== void 0) result.runs = result.runs.map((run) => {
|
|
284
|
+
if (run.bold !== true) return run;
|
|
285
|
+
const withoutBold = { ...run };
|
|
286
|
+
delete withoutBold.bold;
|
|
287
|
+
return withoutBold;
|
|
288
|
+
});
|
|
256
289
|
return result;
|
|
257
290
|
}
|
|
258
291
|
function reconstructPresentation(doc, options) {
|
package/dist/markdown/read.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_markdown_math = require("./math.cjs");
|
|
3
|
+
require("./write.cjs");
|
|
3
4
|
let markdown_codec = require("markdown-codec");
|
|
4
5
|
//#region src/markdown/read.ts
|
|
5
6
|
function readMarkdownContent(text, options, math) {
|
|
@@ -8,7 +9,20 @@ function readMarkdownContent(text, options, math) {
|
|
|
8
9
|
...options
|
|
9
10
|
});
|
|
10
11
|
if (document.kind !== "wordprocessing") throw new Error("readMarkdownContent returned a non-wordprocessing ContentDocument");
|
|
11
|
-
return require_markdown_math.lowerMarkdownMath(document, math);
|
|
12
|
+
return require_markdown_math.lowerMarkdownMath(promotePageBreakMarkers(document), math);
|
|
13
|
+
}
|
|
14
|
+
function promotePageBreakMarkers(document) {
|
|
15
|
+
return {
|
|
16
|
+
...document,
|
|
17
|
+
sections: document.sections.map((section) => ({
|
|
18
|
+
...section,
|
|
19
|
+
blocks: section.blocks.map(promoteBlock)
|
|
20
|
+
}))
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function promoteBlock(block) {
|
|
24
|
+
if (block.kind !== "paragraph" || block.styleId !== markdown_codec.HTML_PREFORMATTED_STYLE_ID) return block;
|
|
25
|
+
return block.runs.map((run) => run.text).join("") === "<!-- page break -->" ? { kind: "pageBreak" } : block;
|
|
12
26
|
}
|
|
13
27
|
//#endregion
|
|
14
28
|
exports.readMarkdownContent = readMarkdownContent;
|
package/dist/markdown/read.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { lowerMarkdownMath } from "./math.js";
|
|
2
|
-
import
|
|
2
|
+
import "./write.js";
|
|
3
|
+
import { HTML_PREFORMATTED_STYLE_ID, readMarkdownContent as readMarkdownContent$1 } from "markdown-codec";
|
|
3
4
|
//#region src/markdown/read.ts
|
|
4
5
|
function readMarkdownContent(text, options, math) {
|
|
5
6
|
const { document } = readMarkdownContent$1(text, {
|
|
@@ -7,7 +8,20 @@ function readMarkdownContent(text, options, math) {
|
|
|
7
8
|
...options
|
|
8
9
|
});
|
|
9
10
|
if (document.kind !== "wordprocessing") throw new Error("readMarkdownContent returned a non-wordprocessing ContentDocument");
|
|
10
|
-
return lowerMarkdownMath(document, math);
|
|
11
|
+
return lowerMarkdownMath(promotePageBreakMarkers(document), math);
|
|
12
|
+
}
|
|
13
|
+
function promotePageBreakMarkers(document) {
|
|
14
|
+
return {
|
|
15
|
+
...document,
|
|
16
|
+
sections: document.sections.map((section) => ({
|
|
17
|
+
...section,
|
|
18
|
+
blocks: section.blocks.map(promoteBlock)
|
|
19
|
+
}))
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function promoteBlock(block) {
|
|
23
|
+
if (block.kind !== "paragraph" || block.styleId !== HTML_PREFORMATTED_STYLE_ID) return block;
|
|
24
|
+
return block.runs.map((run) => run.text).join("") === "<!-- page break -->" ? { kind: "pageBreak" } : block;
|
|
11
25
|
}
|
|
12
26
|
//#endregion
|
|
13
27
|
export { readMarkdownContent };
|
package/dist/markdown/write.cjs
CHANGED
|
@@ -13,6 +13,7 @@ var MarkdownConstructUnsupportedError = class extends Error {
|
|
|
13
13
|
const MATH_BLOCK_STYLE_ID = "MathBlock";
|
|
14
14
|
const MATH_INLINE_FONT_MARKER = "Cambria Math";
|
|
15
15
|
const MATH_INLINE_SOURCE = "markdown:math-inline";
|
|
16
|
+
const PAGE_BREAK_MARKER = "<!-- page break -->";
|
|
16
17
|
function formulaParagraph(formula) {
|
|
17
18
|
const latex = formula.presentation?.latex;
|
|
18
19
|
if (latex === void 0) return {
|
|
@@ -34,6 +35,11 @@ function formulaParagraph(formula) {
|
|
|
34
35
|
}
|
|
35
36
|
function markdownBlock(block) {
|
|
36
37
|
if (block.kind === "constructStart" || block.kind === "constructEnd") throw new MarkdownConstructUnsupportedError(block);
|
|
38
|
+
if (block.kind === "pageBreak") return {
|
|
39
|
+
kind: "paragraph",
|
|
40
|
+
runs: [{ text: PAGE_BREAK_MARKER }],
|
|
41
|
+
styleId: markdown_codec.HTML_PREFORMATTED_STYLE_ID
|
|
42
|
+
};
|
|
37
43
|
if (block.kind === "table") return {
|
|
38
44
|
...block,
|
|
39
45
|
rows: block.rows.map((row) => ({
|
|
@@ -67,4 +73,5 @@ function buildMarkdownText(document, options) {
|
|
|
67
73
|
}
|
|
68
74
|
//#endregion
|
|
69
75
|
exports.MarkdownConstructUnsupportedError = MarkdownConstructUnsupportedError;
|
|
76
|
+
exports.PAGE_BREAK_MARKER = PAGE_BREAK_MARKER;
|
|
70
77
|
exports.buildMarkdownText = buildMarkdownText;
|
|
@@ -5,6 +5,7 @@ declare class MarkdownConstructUnsupportedError extends Error {
|
|
|
5
5
|
readonly descriptorKind: ContentConstructStart['descriptor']['kind'] | undefined;
|
|
6
6
|
constructor(block: ContentConstructStart | ContentConstructEnd);
|
|
7
7
|
}
|
|
8
|
+
declare const PAGE_BREAK_MARKER = "<!-- page break -->";
|
|
8
9
|
declare function buildMarkdownText(document: ContentDocument, options?: WriteMarkdownOptions): string;
|
|
9
10
|
//#endregion
|
|
10
|
-
export { MarkdownConstructUnsupportedError, buildMarkdownText };
|
|
11
|
+
export { MarkdownConstructUnsupportedError, PAGE_BREAK_MARKER, buildMarkdownText };
|
package/dist/markdown/write.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ declare class MarkdownConstructUnsupportedError extends Error {
|
|
|
5
5
|
readonly descriptorKind: ContentConstructStart['descriptor']['kind'] | undefined;
|
|
6
6
|
constructor(block: ContentConstructStart | ContentConstructEnd);
|
|
7
7
|
}
|
|
8
|
+
declare const PAGE_BREAK_MARKER = "<!-- page break -->";
|
|
8
9
|
declare function buildMarkdownText(document: ContentDocument, options?: WriteMarkdownOptions): string;
|
|
9
10
|
//#endregion
|
|
10
|
-
export { MarkdownConstructUnsupportedError, buildMarkdownText };
|
|
11
|
+
export { MarkdownConstructUnsupportedError, PAGE_BREAK_MARKER, buildMarkdownText };
|
package/dist/markdown/write.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formulaOfBlock, formulaPlaceholderText } from "../model/formula.js";
|
|
2
|
-
import { MarkdownUnsupportedDocumentKindError, writeMarkdownContent } from "markdown-codec";
|
|
2
|
+
import { HTML_PREFORMATTED_STYLE_ID, MarkdownUnsupportedDocumentKindError, writeMarkdownContent } from "markdown-codec";
|
|
3
3
|
//#region src/markdown/write.ts
|
|
4
4
|
var MarkdownConstructUnsupportedError = class extends Error {
|
|
5
5
|
descriptorKind;
|
|
@@ -12,6 +12,7 @@ var MarkdownConstructUnsupportedError = class extends Error {
|
|
|
12
12
|
const MATH_BLOCK_STYLE_ID = "MathBlock";
|
|
13
13
|
const MATH_INLINE_FONT_MARKER = "Cambria Math";
|
|
14
14
|
const MATH_INLINE_SOURCE = "markdown:math-inline";
|
|
15
|
+
const PAGE_BREAK_MARKER = "<!-- page break -->";
|
|
15
16
|
function formulaParagraph(formula) {
|
|
16
17
|
const latex = formula.presentation?.latex;
|
|
17
18
|
if (latex === void 0) return {
|
|
@@ -33,6 +34,11 @@ function formulaParagraph(formula) {
|
|
|
33
34
|
}
|
|
34
35
|
function markdownBlock(block) {
|
|
35
36
|
if (block.kind === "constructStart" || block.kind === "constructEnd") throw new MarkdownConstructUnsupportedError(block);
|
|
37
|
+
if (block.kind === "pageBreak") return {
|
|
38
|
+
kind: "paragraph",
|
|
39
|
+
runs: [{ text: PAGE_BREAK_MARKER }],
|
|
40
|
+
styleId: HTML_PREFORMATTED_STYLE_ID
|
|
41
|
+
};
|
|
36
42
|
if (block.kind === "table") return {
|
|
37
43
|
...block,
|
|
38
44
|
rows: block.rows.map((row) => ({
|
|
@@ -65,4 +71,4 @@ function buildMarkdownText(document, options) {
|
|
|
65
71
|
}, options);
|
|
66
72
|
}
|
|
67
73
|
//#endregion
|
|
68
|
-
export { MarkdownConstructUnsupportedError, buildMarkdownText };
|
|
74
|
+
export { MarkdownConstructUnsupportedError, PAGE_BREAK_MARKER, buildMarkdownText };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "documents.js",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -101,12 +101,12 @@
|
|
|
101
101
|
"packageManager": "pnpm@11.6.0",
|
|
102
102
|
"dependencies": {
|
|
103
103
|
"byte-codec": "^1.1.13",
|
|
104
|
-
"document-schema.js": "^4.
|
|
104
|
+
"document-schema.js": "^4.5.0",
|
|
105
105
|
"fflate": "^0.8.3",
|
|
106
|
-
"markdown-codec": "^4.0.
|
|
107
|
-
"odf.js": "^5.0.
|
|
108
|
-
"ooxml.js": "^4.
|
|
109
|
-
"pdf-codec": "^3.1.
|
|
106
|
+
"markdown-codec": "^4.0.13",
|
|
107
|
+
"odf.js": "^5.0.8",
|
|
108
|
+
"ooxml.js": "^4.3.0",
|
|
109
|
+
"pdf-codec": "^3.1.2",
|
|
110
110
|
"temml": "0.13.4",
|
|
111
111
|
"zod": "^4.4.3"
|
|
112
112
|
},
|