You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+20Lines changed: 20 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,26 @@ All notable changes to `officeParser` are documented in this file.
4
4
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
7
+
## [7.7.0] - 2026-08-17
8
+
### Added
9
+
-**`==text==` highlight round-trips through Markdown.** In a dialect that defines it (Obsidian/extended), a highlighted run now emits as `==text==` and `==text==` parses back to a highlight; other dialects keep the HTML `<mark>`/`<span>` fallback and leave `==` literal on parse. Import is purely additive; export of the default-yellow highlight becomes `==` under the `extended` dialect.
10
+
-**Inline link and image titles are preserved in both directions.**`[text](url "Title")` and `` now parse their title into `TextMetadata.title` / `ImageMetadata.title` - previously an *inline* destination swallowed `url "Title"` as one URL (reference-style links already parsed the title correctly) - and the generators emit it back as a Markdown title and an HTML `title=` attribute.
11
+
-**`MdGeneratorConfig.fallbackToHtml.itemLineBreaks`** (default on): multi-paragraph list-item content (an HTML `<li>` with several `<p>` children) is joined onto the item's single Markdown line with `<br>` instead of a space, mirroring `cellLineBreaks` for table cells.
12
+
-**Markdown dialect capabilities are typed by the syntax they select.**`mdConfig.dialect` now names each capability's syntax: `admonitions: 'blockquote' | 'fence' | 'fence-attribute' | 'none'`, and `strikethrough`/`definitionLists`/`footnotes`/`citations`/`wikilinks`/`attributeLists` as `'<marker>' | 'none'` (e.g. `strikethrough: 'tilde'`, `wikilinks: 'double-bracket'`). A new `highlight: 'equals' | 'none'` capability is added. `'none'` is the explicit off switch; an omitted field still inherits from `extends`. Naming each capability for its syntax (rather than a product flavour or a bare boolean) lets a shared convention be one value and lets a second syntax be added later without a breaking change.
13
+
14
+
### Deprecated
15
+
-**Boolean values for dialect capability fields, and the admonition flavour names.**`strikethrough: true`/`false` (and the same for `definitionLists`, `footnotes`, `citations`, `wikilinks`, `attributeLists`) and `admonitions: 'github' | 'gitlab' | 'pandoc'` still work - they coerce to the new syntax values (`true` to the marker, `false` to `'none'`; the flavour names to `'blockquote'`/`'fence'`/`'fence-attribute'`) - but are deprecated and will be removed in the next major. Output is byte-identical for existing configs.
16
+
17
+
### Fixed
18
+
-**Nested lists flattened on an HTML round trip.** An HTML list item wrapping its text in a block element (`<li><p>a</p><ul>…`, the shape rich-text editors built on ProseMirror/Tiptap emit) exported to Markdown as `- a\n\n\n - a1`: the paragraph's trailing blank line split the list into separate blocks and the child's indent was then stripped on reparse, so `a` and `a1` came back as flat siblings in one list. List items are now emitted as a single tight line (via `itemLineBreaks` above), a conservative parser pass re-joins a blank-line-split indented child back into its list, and `HtmlGenerator` places a nested list inside its parent's still-open `<li>` (spec-valid `<li>a<ul>…</ul></li>` instead of the invalid sibling `<li>a</li><ul>…`), which also makes generated EPUB XHTML valid. A bare-text `<li>` (no `<p>`) was never affected. **Behaviour change** to the shape of generated nested-list HTML.
19
+
- **GFM table column alignment was lost on import, non-standard on Markdown export, and dropped through HTML.** Import ignored the `:---`/`:---:`/`---:` separator markers; Markdown export emitted `| --- |` with a trailing non-standard table-level `{align=…}` rather than per-column markers; and the HTML generator emitted no cell alignment at all, so a table lost its alignment whenever it passed through HTML (the editor import path `md → HTML → editor`). Alignment now lives on per-column `CellMetadata.align`: the Markdown generator regenerates the standard `:---`/`:---:`/`---:` markers, and the HTML generator emits `style="text-align: …"` on each `<th>`/`<td>` which `HtmlParser` reads back (alongside the existing table-level `<table data-align>`), so alignment survives `md → HTML → md` losslessly. A uniform-alignment table additionally carries `data-align` on the `<table>` for editors that model one alignment per table. Unaligned tables are byte-identical. **Behaviour change** to generated table separators (Markdown) and cell styles (HTML).
20
+
-**Inline monospace text was emitted as a styled `<span>` in HTML.** Inline code (a monospace text node) rendered as a `font-family: monospace``<span>` rather than `<code>`, so it did not round-trip as inline code through HTML. It is now a `<code>` element (with bold/italic wrapping it), which the parser reads back to a monospace run.
21
+
-**A single-line code block carrying a language rendered inline in HTML.**`HtmlGenerator` chose `<pre><code>` vs an inline `<span>` purely by whether the code contained a newline, so a one-line code node with a language (`const x = 1;` tagged `js`, or a one-line mermaid diagram) rendered inline and lost its block-ness. A code node carrying a language now always renders as `<pre><code>`.
22
+
-**A plain `<blockquote>` was dropped on HTML → Markdown export.** Only the admonition `> [!NOTE]` path emitted a blockquote; a plain `<blockquote>` silently lost its `>` marker. It now round-trips as a `> quoted` blockquote.
23
+
-**An HTML `<br>` was read back as a soft wrapping break.**`HtmlParser` mapped `<br>` to a `textWrapping` break, which the Markdown generator emitted as a bare `\n` in a paragraph - reimporting as a space, so `<p>line1<br>line2</p>` collapsed to one line. `<br>` is now a `carriageReturn` hard line break, symmetric with the generator, so it survives the round trip in paragraphs as well as cells.
24
+
-**A single-line `$$…$$` imported as inline math with stray `$`.** A `$$\int_a^b$$` on its own line fell through to the inline `$…$` tokenizer, which matched the inner `$\int_a^b$` and leaked the outer pair as two literal `$`. An own-line `$$…$$` is now block math, matching the multi-line `$$` form. (`$$` inside a line of other text is left as-is.)
25
+
-**`npm test` failed on a cold run, and a CLI timeout masqueraded as a content mismatch.** The CLI parity test shells out to OCR the sample PDF (~27-30s, more on a cold cache), but the harness capped every CLI call at 30s and coerced `spawnSync`'s SIGTERM kill (`status: null`) to exit `0`. So a cold run clipped the PDF at the limit and then read the killed process as a clean exit with empty output, reporting `0.0% similarity ... Got: 0 words` - a phantom parser regression rather than the timeout it was. The OCR parity call now gets a 120s budget, and a timed-out CLI run is surfaced as a distinct non-zero status with a clear message. Test tooling only; the published package is unchanged. (#111)
26
+
7
27
## [7.6.2] - 2026-08-15
8
28
### Fixed
9
29
-**A generated table's header was invalid HTML and did not round-trip.**`generate('html')` emitted the header row's cells directly under `<thead>` (`<thead><th>…`) with no wrapping `<tr>`, which is invalid and which `HtmlParser` could not read back as a table - so a `md -> HTML -> md` round trip through officeParser alone lost the header (its cells came back empty). The header row is now wrapped in `<tr>` (`<thead><tr><th>…`), which is valid and self-idempotent.
| `data-align` on `<table>` | `TableMetadata.align` | |
800
+
| `data-align` on `<table>` | `TableMetadata.align` | Emitted/parsed as per-column GFM markers (`:---`, `:---:`, `---:`); alignment rides `CellMetadata.align` |
801
+
| `title` on `<a>` / `<img>` | `TextMetadata.title` / `ImageMetadata.title` | Survives both directions (`[text](url "Title")` in Markdown) |
799
802
| `colspan` / `rowspan` on `<td>`/`<th>` | `CellMetadata.colSpan` / `.rowSpan` | Previously dropped on HTML import — merged cells now survive a save→reload cycle |
@@ -1146,7 +1149,8 @@ Pass as `mdConfig` inside `GeneratorConfig`.
1146
1149
1147
1150
| Option | Type | Default | Description |
1148
1151
|--------|------|---------|-------------|
1149
-
|`fallbackToHtml`|`boolean \| FallbackToHtmlConfig`|`true`| Use HTML tags for features Markdown cannot represent (underlines, merged table cells, embeds, etc.). Pass an object for per-feature control. `inlineFormatting` (default `false`, opt-in even when the boolean is `true`) additionally round-trips inline color/highlight/font-size as `<span style="...">` runs. |
1152
+
|`fallbackToHtml`|`boolean \| FallbackToHtmlConfig`|`true`| Use HTML tags for features Markdown cannot represent (underlines, merged table cells, embeds, etc.). Pass an object for per-feature control. `cellLineBreaks`/`itemLineBreaks` (default on) join multi-line table-cell / multi-paragraph list-item content with `<br>` instead of a space. `inlineFormatting` (default `false`, opt-in even when the boolean is `true`) additionally round-trips inline color/highlight/font-size as `<span style="...">` runs. |
1153
+
|`dialect`|`MarkdownDialectPreset \| MarkdownDialectConfig`|`'extended'`| Which native syntax to emit for constructs that differ across targets (GitHub/GitLab/Obsidian/Pandoc/CommonMark). Each capability is typed by the syntax it selects (e.g. `strikethrough: 'tilde'`, `highlight: 'equals'`, `admonitions: 'blockquote'`), with `'none'` to turn it off. See [Markdown Dialect Support](#markdown-dialect-support). The old `boolean` toggles and admonition flavour names (`'github'`/`'gitlab'`/`'pandoc'`) still work but are deprecated. |
0 commit comments