page-markdown 0.1.5 → 0.3.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/ADDITIONAL_TERMS.md +122 -122
- package/CHANGELOG.md +353 -186
- package/LICENSE +694 -694
- package/README.md +113 -41
- package/THIRD_PARTY_NOTICES.md +264 -264
- package/dist/types/concealed.d.ts +59 -0
- package/dist/types/extract.d.ts +10 -4
- package/dist/types/facts.d.ts +1 -0
- package/dist/types/index.d.ts +20 -6
- package/dist/types/sanitize.d.ts +22 -3
- package/dist/types/standardize.d.ts +15 -1
- package/dist/types/types.d.ts +51 -2
- package/package.json +69 -68
- package/robots.txt +79 -79
- package/src/clean.js +1 -1
- package/src/concealed.js +418 -0
- package/src/convert.js +95 -13
- package/src/extract.js +178 -8
- package/src/facts.js +6 -3
- package/src/index.js +219 -178
- package/src/refine.js +9 -3
- package/src/sanitize.js +106 -57
- package/src/standardize.js +167 -3
- package/src/types.js +23 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,186 +1,353 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
- **
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- **
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- **
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
heading.
|
|
181
|
-
- **
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.3.0 — 2026-11-13
|
|
6
|
+
|
|
7
|
+
- Build the live-style report with `npm run report:build`, then open `.browser-test/concealment-report.html` in an already running browser.
|
|
8
|
+
|
|
9
|
+
- **Opt-in:** enable `detectConcealedText: true` to separate text concealed by
|
|
10
|
+
supported live source-document computed styles:
|
|
11
|
+
`display:none`, hidden/collapsed visibility, zero opacity, zero font size and
|
|
12
|
+
supported empty clips (including nonzero zero-area rects; legacy `clip`
|
|
13
|
+
requires absolute/fixed positioning), transparent text and text exactly
|
|
14
|
+
matching its own or nearest opaque background
|
|
15
|
+
into capped `concealedText`, with uncapped omission
|
|
16
|
+
counts and notices in both Markdown outputs. Detection is off by default;
|
|
17
|
+
HELIOS enables it explicitly. Default-on is withdrawn for 0.3.0 and will be
|
|
18
|
+
reconsidered after a real-site trial. Disabled detection makes no style calls.
|
|
19
|
+
Static documents retain previous output.
|
|
20
|
+
Whitespace-only groups are excluded from entries, totals, truncation and
|
|
21
|
+
notices, also correcting slice 1; substantive groups retain original
|
|
22
|
+
whitespace and UTF-16 counts.
|
|
23
|
+
Source whitespace is removed for display-none and zero-font-size runs; other
|
|
24
|
+
reasons retain whitespace-only runs and replace substantive runs with one
|
|
25
|
+
ordinary space only when their original text starts or ends with JavaScript
|
|
26
|
+
whitespace.
|
|
27
|
+
The check reports computed, static-only, disabled or incomplete capability.
|
|
28
|
+
Short tabs and existing answer/code exceptions remain; independent reasons
|
|
29
|
+
still lift text and can change extraction choice and tab omissions.
|
|
30
|
+
Opacity-applicable transitions and named animations with nonzero durations
|
|
31
|
+
retain text with a warning; this scroll-reveal rule remains provisional
|
|
32
|
+
pending real-site evidence and Astra review.
|
|
33
|
+
Colour detection handles computed sRGB rgb()/rgba() only, for own text.
|
|
34
|
+
OKLCH and Display P3 computed colours are not parsed, so even white text on
|
|
35
|
+
white in those forms can stay in the output.
|
|
36
|
+
Measured in Chrome 157 on Windows, on one machine, using synthetic pages
|
|
37
|
+
of 20,006 elements built from `95bf97d`, with five warmed alternating pairs
|
|
38
|
+
per page: full conversion with detection added a paired-median 100.5 ms
|
|
39
|
+
on the deep page and 108.5 ms on the shallow page, about 12.5% each.
|
|
40
|
+
Both full-conversion targets (at most 25% and at most 250 ms added) were met.
|
|
41
|
+
The sanitize stage with detection (including preparation and lift) added
|
|
42
|
+
about 127 ms on either page. The earlier candidate (`2a3b0b5`) added about
|
|
43
|
+
442 ms deep and 340 ms shallow by a difference of medians, which is not
|
|
44
|
+
directly comparable. This is not a general performance guarantee;
|
|
45
|
+
real-site cost is not yet measured.
|
|
46
|
+
Chrome is the only browser tested; Firefox and
|
|
47
|
+
Safari are untested.
|
|
48
|
+
Unknown colours, missing opaque backgrounds, intervening translucent layers
|
|
49
|
+
or images, text clipping, differing text fill, shadows and strokes prevent
|
|
50
|
+
equality detection. Fully transparent text fill is detected when no other
|
|
51
|
+
effect paints the text. Near-colour matches and partially transparent text
|
|
52
|
+
with non-zero alpha (including alpha 0.01) are not detected. White text on a
|
|
53
|
+
page with no declared
|
|
54
|
+
opaque background is not detected: the root background is unknown.
|
|
55
|
+
|
|
56
|
+
- Boxes a page marks as skippable are left out of the article: a box that opens with a
|
|
57
|
+
link to the end marker it closes with, as BBC's "most read" and podcast boxes do in
|
|
58
|
+
every language. Boxes holding a quote, embed, code or table stay.
|
|
59
|
+
- Malformed web links keep their text without a link even in browsers that accept spaces in hostnames.
|
|
60
|
+
- Table cells with `rowspan="0"` span to the end of their row group, including with `colspan`.
|
|
61
|
+
- Text-only output keeps image alt text without URL fragments from parentheses or titles.
|
|
62
|
+
- Captions survive in single-column, nested and code-bearing tables.
|
|
63
|
+
|
|
64
|
+
- **AP News linked names to impossible web addresses.** Malformed hrefs such as
|
|
65
|
+
`https://ron%20desantis/` now keep their text without a link when a base URL is
|
|
66
|
+
available.
|
|
67
|
+
- **Linked story headings stay headings.** On BBC News, card headlines appeared
|
|
68
|
+
inside link text and the logo left an empty heading. Headlines now link from
|
|
69
|
+
real headings, card text and images stay, and emptied headings are removed.
|
|
70
|
+
- **Note labels stay.** Readability removed Docker's `.admonition-header` because
|
|
71
|
+
its name holds "header", so its Warning, Note and Tip labels were lost. Each now
|
|
72
|
+
opens its blockquote in bold.
|
|
73
|
+
- **Spanned cells fill their columns.** A cell with `colspan` used to fill one
|
|
74
|
+
column and leave blanks, so Tailscale's "Unlimited" across all plans read as
|
|
75
|
+
Personal only. Its value now repeats in each column it covers, except when it
|
|
76
|
+
spans the whole row, as a caption does.
|
|
77
|
+
- **FAQ answers inside `<details>` survive.** Readability dropped a one-paragraph
|
|
78
|
+
answer wrapper with a link in it: Tailscale's answer on SSH check mode.
|
|
79
|
+
- **Ars Technica's MacBook Pro review repeated photo captions and left its kicker
|
|
80
|
+
as body text.** Matching lightbox captions and image descriptions now appear
|
|
81
|
+
once, distinct alt text and gallery images stay, and the kicker reads as a label.
|
|
82
|
+
|
|
83
|
+
## 0.2.0 — 2026-11-07
|
|
84
|
+
|
|
85
|
+
Fixes for silent content loss, found by live runs in a real extension (HELIOS, in
|
|
86
|
+
Brave): pages lost their main content and reported a normal extraction.
|
|
87
|
+
|
|
88
|
+
A minor version because results change in ways callers can see. `omissions` has two
|
|
89
|
+
new kinds, `inactive_tabs` and `comments`, so an exhaustive `switch` on `kind` in
|
|
90
|
+
TypeScript stops compiling. `extraction.method` can be `main_content` on pages that
|
|
91
|
+
used to report `readability`, those pages come out longer, and some outputs gain a
|
|
92
|
+
closing line.
|
|
93
|
+
|
|
94
|
+
- **Threads and product grids keep their content.** When Readability keeps less
|
|
95
|
+
than `minExtractShare` (default 0.4) of the page's main content and misses at
|
|
96
|
+
least 500 characters, the main content is used, without navigation, asides and
|
|
97
|
+
forms. `extraction.method` is then `main_content`, `fallbackReason` is
|
|
98
|
+
`extracted_small_share_of_page`, and `warnings` says so. Word recall on a Lobsters
|
|
99
|
+
thread goes from 36% to 100%, and on an IKEA category page from 50% to 95%. These
|
|
100
|
+
pages keep more clutter: IKEA's precision falls from 92% to 30%.
|
|
101
|
+
- **Layout class names no longer cost a block its place.** Readability's clutter
|
|
102
|
+
list matches "scroll" and "hidden" in Tailwind's `scroll-mt-2`, `overflow-hidden`
|
|
103
|
+
and `md:hidden`, and it removed what carried them: every code block in Docker's
|
|
104
|
+
install guide and the plan cards on Tailscale's pricing page. Proven live on both.
|
|
105
|
+
- **Icon-only table cells say something.** A cell holding only an SVG came out
|
|
106
|
+
empty, so a comparison table couldn't say which plan has what. It now shows the
|
|
107
|
+
icon's accessible name, else `✓`, `–` or `✗` for those simple shapes, else
|
|
108
|
+
`[icon]`. On Tailscale, 114 ticks and 25 dashes where there were empty cells.
|
|
109
|
+
- **More cases fall back to the main content,** and say so with their own
|
|
110
|
+
`fallbackReason`. `extracted_site_menu`: Readability chose a container above
|
|
111
|
+
`<main>` and kept the site's menu (BBC News). `extracted_few_sections_of_page`:
|
|
112
|
+
it kept under 1.5 times `minExtractShare` of the main content and lost most of the
|
|
113
|
+
page's h2 sections, as on Adafruit's product page, which lost its price, stock and
|
|
114
|
+
technical details. Headings that are a link to another page don't count, so story
|
|
115
|
+
cards around an article, as on The Register, don't trigger it. The product page
|
|
116
|
+
keeps more clutter this way, including its "May We Also Suggest" list. Proven live
|
|
117
|
+
on all three.
|
|
118
|
+
- **The fallback keeps collapsed answers.** Hidden text of 40 characters or more
|
|
119
|
+
straight after a button or summary is kept, so an FAQ isn't lost when a page
|
|
120
|
+
hides its answers with inline styles. Proven live on Allbirds' FAQ.
|
|
121
|
+
- **Tab panels hidden by a class name keep their text.** Readability removes
|
|
122
|
+
`class="hidden"`, so Docker's "Specific version" install tab was lost live with
|
|
123
|
+
no closing line. Inactive panels are now recognized by that class too, and Docker's
|
|
124
|
+
`aria-role` tab strips are read as tabs. Proven live on Docker.
|
|
125
|
+
- **Shadow limits no longer erase a whole host.** A host over the limit keeps what
|
|
126
|
+
fits, limits apply per host in the page's own tree so a large site header can't
|
|
127
|
+
use up the article's budget, and `warnings` now reports the cut.
|
|
128
|
+
- **Slotted page content no longer counts against the shadow limit.** Material Web
|
|
129
|
+
puts its whole article in one host's slot, so the limit cut it off partway
|
|
130
|
+
through. Proven live on Material Web, Adobe Spectrum and Red Hat (no cut), though
|
|
131
|
+
no live page has yet gone over the limit.
|
|
132
|
+
- **Headings survive clutter-like names.** Readability removed headings named like
|
|
133
|
+
Docusaurus's `anchorTargetHideOnScrollNavbar`. Permalink text ("Section titled",
|
|
134
|
+
"Direct link to") goes too.
|
|
135
|
+
- **Permalinks are recognised by where they point.** A link to a heading's own id,
|
|
136
|
+
inside or beside it, is removed whatever its class or wording. Short headings
|
|
137
|
+
beside one ("Types", "Usage") were being dropped by Readability as clutter:
|
|
138
|
+
five on Material Web's button page.
|
|
139
|
+
- **Page facts skip more junk:** headings inside or holding a link (another story's
|
|
140
|
+
teaser), values holding form controls, and cookie settings.
|
|
141
|
+
- **An article above its comments stays an article.** Comments outweighing the
|
|
142
|
+
article made the main-content fallback fire, four times the length on a real
|
|
143
|
+
page. Readability's result now stands when what it kept isn't itself a comment,
|
|
144
|
+
and `omissions` gets `comments`.
|
|
145
|
+
- **Hidden text no longer counts or comes through in the fallback,** except code
|
|
146
|
+
behind a "Show code" toggle.
|
|
147
|
+
- **Tabs read as one document.** Inactive panels are kept under their tab's name,
|
|
148
|
+
in place of a tab strip of dead links. A panel over 5,000 characters is left out
|
|
149
|
+
and named (`stats.standardization.omittedTabs`, `omissions` kind `inactive_tabs`).
|
|
150
|
+
- **Note asides survive,** as blockquotes: Readability removes every `<aside>`.
|
|
151
|
+
- **What changes the content says so in the Markdown too:** a fallback, a removed
|
|
152
|
+
JSON line, left-out tabs and comments each add a closing line, since a caller may
|
|
153
|
+
pass on only the Markdown. The shadow notice stays last.
|
|
154
|
+
- **Too little from Readability uses the page's `<main>`,** when it marks one with
|
|
155
|
+
enough text, before the full page.
|
|
156
|
+
- **`stats.pageTextChars`** counts the page's text. A capture is a snapshot of the
|
|
157
|
+
DOM at call time: a caller can re-capture until the number settles.
|
|
158
|
+
- **Headlines:** a site-wide `og:title` no longer replaces the page's H1, and a badge
|
|
159
|
+
after an H1's title is dropped. A heading that is wholly a link to itself becomes
|
|
160
|
+
plain text.
|
|
161
|
+
- A link around block content stays on one line, and `.ad-label` counts as an ad.
|
|
162
|
+
- The browser bundle grows to about 75.4 KB minified; the size ceiling is now
|
|
163
|
+
76 KB.
|
|
164
|
+
- **The browser run no longer launches by default.** Launching browsers from agent
|
|
165
|
+
sessions has crashed this machine. `npm run test:browser` now needs
|
|
166
|
+
`PAGE_MARKDOWN_ALLOW_BROWSER_LAUNCH=1`, set by a person in their own shell;
|
|
167
|
+
without it the run builds its page, launches nothing and exits with an error.
|
|
168
|
+
It is no longer part of `npm run ci` or `prepublishOnly`.
|
|
169
|
+
|
|
170
|
+
## 0.1.5 — 2026-11-04
|
|
171
|
+
|
|
172
|
+
Content-fidelity fixes, each with a new fixture run in Node and in the browser:
|
|
173
|
+
|
|
174
|
+
- **Code blocks keep their lines.** Lines marked up with `<br>` or block
|
|
175
|
+
elements (Docusaurus and similar highlighters) came out joined on one line.
|
|
176
|
+
- **Copy buttons stay out of code.** A `<button>` inside `<pre>` leaked its
|
|
177
|
+
label into the code and lost the language. Whitespace around the `<code>`
|
|
178
|
+
no longer loses the fence.
|
|
179
|
+
- **Text beside a heading is kept.** A `<div>` holding a heading and bare text
|
|
180
|
+
was replaced by the heading, deleting the text.
|
|
181
|
+
- **Row spans keep columns aligned.** Later cells shifted left. A spanned cell
|
|
182
|
+
now repeats in each row of a GFM table, and block-rendered tables label cells
|
|
183
|
+
by their true column.
|
|
184
|
+
- **Large tables no longer freeze the page.** Table checks ran once per cell,
|
|
185
|
+
so time grew with the square of the size: 500 rows took about 8 seconds in
|
|
186
|
+
Chrome.
|
|
187
|
+
- **Modes leave more code alone.** Fences in list items and blockquotes, and
|
|
188
|
+
inline code, were edited by `no_links`, `text_only` and blank-line cleanup.
|
|
189
|
+
- **A lead paragraph is no longer doubled** when it starts with a link or holds
|
|
190
|
+
an entity such as `<`.
|
|
191
|
+
- **Script links are caught however they are written.** `javascript:` with an
|
|
192
|
+
embedded newline, tab or control character got through, as did `vbscript:`
|
|
193
|
+
and `data:`. These links keep only their text. Images with such a source are
|
|
194
|
+
dropped.
|
|
195
|
+
- **`<base href>` is respected** for links and images.
|
|
196
|
+
- **A linked image with empty alt is kept.**
|
|
197
|
+
- **An ad marker on `<body>` no longer empties the page.** Sites put page-wide ad
|
|
198
|
+
settings there (`data-ad-unit` on heise.de), and the ad filter removed the whole
|
|
199
|
+
body. `<html>` and `<body>` are never treated as ads; ads inside them still are.
|
|
200
|
+
- `stats.markdownChars` now matches the returned Markdown.
|
|
201
|
+
- The browser bundle grows to about 67.2 KB minified; the size ceiling is now
|
|
202
|
+
68 KB.
|
|
203
|
+
|
|
204
|
+
- **TypeScript types.** Declarations for `pageToMarkdown`, its options, the full
|
|
205
|
+
result and every stage export are generated from the JSDoc in `src` into
|
|
206
|
+
`dist/types`, through a `types` condition in `exports`. The result is
|
|
207
|
+
documented in a README table. `npm run typecheck` is part of `npm run ci`: it
|
|
208
|
+
checks `src` against its JSDoc, checks a consumer file with `tsc`, and checks
|
|
209
|
+
the declarations against real output from every fixture, in both directions.
|
|
210
|
+
Only comments change in the existing modules; the bundle is the same size.
|
|
211
|
+
- **Bench.** `npm run bench` adds a Readability + Turndown baseline, word recall
|
|
212
|
+
and precision, and 11 held-out pages whose probes were committed before any
|
|
213
|
+
engine ran on them. The headline changes from 32/32 against 11/32 to 84/100
|
|
214
|
+
against 74/100 and 61/100 on the held-out pages; see `bench/RESULTS.md` for the
|
|
215
|
+
failures. `bench/fetch-pages.mjs` now decodes by declared charset and keeps the
|
|
216
|
+
last good copy when a fetch fails. `npm run bench:write` updates
|
|
217
|
+
`bench/RESULTS.md`; `npm run bench` only prints.
|
|
218
|
+
- **Licence summary.** The README now says in plain words who can use the package
|
|
219
|
+
free and who needs a commercial licence, and how to ask for one. The licence
|
|
220
|
+
itself is unchanged.
|
|
221
|
+
- **Browser run.** `npm run test:browser` runs the golden fixtures in
|
|
222
|
+
headless Chrome or Edge, with the browser's own DOM, and checks what Node
|
|
223
|
+
can't show:
|
|
224
|
+
- the live document is left unmodified;
|
|
225
|
+
- real open shadow roots are captured, nested roots and slotted children
|
|
226
|
+
included;
|
|
227
|
+
- closed shadow roots stay out.
|
|
228
|
+
|
|
229
|
+
It is part of `npm run ci` and needs no new dependencies. The package's output
|
|
230
|
+
in Chrome and Edge matches its Node output.
|
|
231
|
+
|
|
232
|
+
## 0.1.4 — 2026-11-02
|
|
233
|
+
|
|
234
|
+
- **text-sanctifier 1.3.8** (was 1.3.3). `removeHiddenText` now also removes
|
|
235
|
+
runs of reserved tag-plane code points (U+E0080–U+E00FF, U+E01F0–U+E0FFF),
|
|
236
|
+
which 1.3.3 did not find, and reports them as `hidden_reserved_tag_plane`.
|
|
237
|
+
The browser bundle grows to about 65.6 KB minified.
|
|
238
|
+
- A test checks that every run kind text-sanctifier can report has an
|
|
239
|
+
omission note, so a new kind fails `npm run ci` instead of reaching users
|
|
240
|
+
with no note.
|
|
241
|
+
- A test fails when any source, test, fixture or doc file holds a raw
|
|
242
|
+
invisible or control character. A test regex in 0.1.3 held four, written
|
|
243
|
+
by an editing tool that expanded `\u` escapes; they never shipped, since
|
|
244
|
+
tests are not in the package.
|
|
245
|
+
|
|
246
|
+
## 0.1.3 — 2026-10-30
|
|
247
|
+
|
|
248
|
+
First release on npm. `npm run ci` (contract suite and size check) is the
|
|
249
|
+
local gate before a commit; there is no cloud CI. The size ceiling is 66 KB
|
|
250
|
+
minified.
|
|
251
|
+
|
|
252
|
+
Content-fidelity fixes:
|
|
253
|
+
|
|
254
|
+
- **Title heading kept beside shell comments.** A `# comment` line in fenced
|
|
255
|
+
code no longer counts as the article's top-level heading, which had
|
|
256
|
+
suppressed the `# <headline>` line.
|
|
257
|
+
- **Every pipe in a table cell is escaped.** `a || b` escaped only its first
|
|
258
|
+
pipe, which added a column and broke the table.
|
|
259
|
+
- **Images beside a heading survive.** A heading wrapper that also holds an
|
|
260
|
+
image (or picture, video, audio) is no longer unwrapped to the bare heading.
|
|
261
|
+
- **`no_links` keeps linked images intact.** `[](href)` became
|
|
262
|
+
``, an image pointing at the link target; the image is now kept
|
|
263
|
+
as it was.
|
|
264
|
+
- **Code in tables stays fenced.** A GFM cell is one line, so a data table
|
|
265
|
+
holding `<pre>` code (Wikipedia's syntax examples) was flattened to inline
|
|
266
|
+
code, losing its line breaks and indentation. Such a table is now rendered
|
|
267
|
+
as blocks: each cell under a bold label from its column header (or its row
|
|
268
|
+
header, for infoboxes), with code as verbatim fences. Tables without code
|
|
269
|
+
are still GFM grids.
|
|
270
|
+
- Code language from MediaWiki's `mw-highlight-lang-*` class.
|
|
271
|
+
- At most one blank line beside a fenced block.
|
|
272
|
+
- Five new regression fixtures, one per fix.
|
|
273
|
+
|
|
274
|
+
Hidden text (opt-in):
|
|
275
|
+
|
|
276
|
+
- **`removeHiddenText: true`** removes runs of tag characters, variation
|
|
277
|
+
selectors and invisible operators, which people can't see but models read
|
|
278
|
+
(hidden prompt instructions). It applies to the Markdown, fenced code
|
|
279
|
+
included, and to `fullPageMarkdown` and `metadata`. The England, Scotland
|
|
280
|
+
and Wales flags and a lone emoji or text presentation selector are kept.
|
|
281
|
+
`omissions` gets `hidden_tag`, `hidden_variation_selector` and
|
|
282
|
+
`hidden_invisible_operator` entries with `count` (runs) and `chars` (code
|
|
283
|
+
points). `removeHiddenText` is exported. Default output is unchanged.
|
|
284
|
+
- New runtime dependency: text-sanctifier 1.3.3 (first-party, no
|
|
285
|
+
dependencies), for its `text-sanctifier/hidden` run finder. About 1.5 KB
|
|
286
|
+
minified in the browser bundle.
|
|
287
|
+
- New contract fixture `hidden-text.html`, written with character references
|
|
288
|
+
so it holds no raw hidden characters.
|
|
289
|
+
|
|
290
|
+
## 0.1.2 — 2026-10-23
|
|
291
|
+
|
|
292
|
+
- **Page facts (opt-in).** `pageFacts: true` appends a `## Page facts` list
|
|
293
|
+
of short label/value pairs that sit outside the extracted article: a
|
|
294
|
+
package sidebar's version, license and downloads, spec and price rows,
|
|
295
|
+
infobox rows. Readability drops these asides, which suits reading but
|
|
296
|
+
loses the answer to "which version?". Pairs come from a heading followed by
|
|
297
|
+
a short value, `<dt>`/`<dd>`, and two-cell table rows. Values already in
|
|
298
|
+
the article, sentences, link lists, lone non-data links and anything in
|
|
299
|
+
navigation, header, footer or forms are skipped. `extraction.pageFacts`
|
|
300
|
+
counts them; `collectPageFacts` is exported. Default output is unchanged.
|
|
301
|
+
- New regression fixture: a package page whose version lives only in the
|
|
302
|
+
sidebar.
|
|
303
|
+
|
|
304
|
+
## 0.1.1 — 2026-10-22
|
|
305
|
+
|
|
306
|
+
Fixes from the first in-browser comparison (MDN, Wikipedia, the Python docs,
|
|
307
|
+
GitHub):
|
|
308
|
+
|
|
309
|
+
- **Tables never come out as raw HTML.** Own GFM table rules replace the
|
|
310
|
+
plugin's:
|
|
311
|
+
- a header row is used even when the table has none;
|
|
312
|
+
- colspans are padded with empty cells;
|
|
313
|
+
- cell content is flattened to one line (code, lists, line breaks);
|
|
314
|
+
- pipes are escaped;
|
|
315
|
+
- layout and nested tables are rendered as blocks.
|
|
316
|
+
- **Dropped lead paragraph restored.** When the extractor leaves out a
|
|
317
|
+
paragraph that matches the meta description (MDN's heading-less first
|
|
318
|
+
section), it is put back first. `extraction.leadRecovered` reports it, and
|
|
319
|
+
`recoverLead: false` turns it off.
|
|
320
|
+
- **Clean title heading.** The page's own H1 (permalink sign removed) when
|
|
321
|
+
the title contains it, else `og:title` or the title, without a site-name
|
|
322
|
+
segment at either end. It is exposed as `metadata.headline`.
|
|
323
|
+
- **Smaller bundle.** Strikethrough and task-list rules are now built in, and
|
|
324
|
+
`@joplin/turndown-plugin-gfm` is no longer a dependency. The browser bundle
|
|
325
|
+
is 60.2 KB minified, down from 61.7 KB.
|
|
326
|
+
|
|
327
|
+
## 0.1.0 — 2026-10-22
|
|
328
|
+
|
|
329
|
+
First release.
|
|
330
|
+
|
|
331
|
+
- `pageToMarkdown(document, options)`: sanitize → standardize → extract →
|
|
332
|
+
convert → clean, returning Markdown, metadata, extraction details,
|
|
333
|
+
omissions, warnings and stats.
|
|
334
|
+
- **Sanitize.** Builds an inert clone and inlines open shadow DOM within node,
|
|
335
|
+
character and depth limits, with an omission notice past them. Removes
|
|
336
|
+
scripts, styles, `noscript`, meta and link tags, and ads, plus any
|
|
337
|
+
`extraStripSelectors`.
|
|
338
|
+
- **Standardize.**
|
|
339
|
+
- Turns `<pre>` into fenced code, with the language from
|
|
340
|
+
`language-`/`lang-`/`highlight-` classes or `data-lang`.
|
|
341
|
+
- Unwraps heading wrappers and removes edit and permalink widgets.
|
|
342
|
+
- Removes empty and `javascript:` links.
|
|
343
|
+
- Makes links and images absolute and resolves lazy images; drops inline
|
|
344
|
+
`data:` images.
|
|
345
|
+
- **Extract.** Mozilla Readability on a copy of the clone, falling back to the
|
|
346
|
+
full page when it finds nothing or too little. Optionally restores the title
|
|
347
|
+
heading.
|
|
348
|
+
- **Convert.** Turndown with GitHub-flavoured tables and strikethrough.
|
|
349
|
+
- **Clean.** Fence-safe. Keeps short lines and `<br>` hard breaks, removes only
|
|
350
|
+
verified single-line JSON documents, and offers `full`, `no_links` and
|
|
351
|
+
`text_only` modes.
|
|
352
|
+
- **Metadata.** Meta tags, JSON-LD (`@graph` included), canonical URL and
|
|
353
|
+
language.
|