@citation-media/html-parser 0.1.1 → 0.1.2
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/clean.js +2 -2
- package/dist/parse.js +28 -27
- package/dist/text.d.ts +5 -0
- package/dist/text.js +256 -25
- package/package.json +1 -1
package/dist/clean.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { looksBinary } from "./text.js";
|
|
1
|
+
import { looksBinary, readAttribute } from "./text.js";
|
|
2
2
|
import { absoluteUrl, isResource, linkKind } from "./urls.js";
|
|
3
3
|
const cookieConsent = [
|
|
4
4
|
"[id^='brlbs-cmpnt']",
|
|
@@ -126,7 +126,7 @@ export const cleanHtml = (input, options) => {
|
|
|
126
126
|
if (links) {
|
|
127
127
|
rewriter = rewriter.on("a", {
|
|
128
128
|
element(element) {
|
|
129
|
-
const href = element
|
|
129
|
+
const href = readAttribute(element, "href");
|
|
130
130
|
if (!href) {
|
|
131
131
|
return;
|
|
132
132
|
}
|
package/dist/parse.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MarkdownWriter } from "./markdown.js";
|
|
2
|
-
import { collapseWhitespace, decodeEntities, removeHyphenation, } from "./text.js";
|
|
2
|
+
import { collapseWhitespace, decodeEntities, readAttribute, removeHyphenation, } from "./text.js";
|
|
3
3
|
import { absoluteUrl, isResource, linkKind } from "./urls.js";
|
|
4
4
|
const blockTags = new Set([
|
|
5
5
|
"br",
|
|
@@ -56,7 +56,6 @@ const hiddenFromMarkdown = [
|
|
|
56
56
|
".visually-hidden",
|
|
57
57
|
];
|
|
58
58
|
const maxHeadings = 200;
|
|
59
|
-
const maxImages = 500;
|
|
60
59
|
const maxResources = 500;
|
|
61
60
|
/**
|
|
62
61
|
* Follows an element to its end tag. HTMLRewriter keeps only the last end-tag handler an element
|
|
@@ -138,7 +137,7 @@ const onStructure = (rewriter, pass) => {
|
|
|
138
137
|
if (!collecting(pass)) {
|
|
139
138
|
return;
|
|
140
139
|
}
|
|
141
|
-
const classes = element
|
|
140
|
+
const classes = readAttribute(element, "class")?.split(/\s+/u) ?? [];
|
|
142
141
|
for (const prefix of classPrefixes) {
|
|
143
142
|
if (classes.some((name) => name.startsWith(prefix))) {
|
|
144
143
|
pass.classCounts[prefix] = (pass.classCounts[prefix] ?? 0) + 1;
|
|
@@ -159,7 +158,7 @@ const onStructure = (rewriter, pass) => {
|
|
|
159
158
|
};
|
|
160
159
|
const onLinks = (rewriter, pass) => rewriter.on("a[href]", {
|
|
161
160
|
element(element) {
|
|
162
|
-
const href = element
|
|
161
|
+
const href = readAttribute(element, "href") ?? "";
|
|
163
162
|
if (!collecting(pass) || !href) {
|
|
164
163
|
return;
|
|
165
164
|
}
|
|
@@ -167,9 +166,9 @@ const onLinks = (rewriter, pass) => rewriter.on("a[href]", {
|
|
|
167
166
|
const text = [];
|
|
168
167
|
pass.link = text;
|
|
169
168
|
// Attributes are readable only while this handler runs, not in the end-tag handler.
|
|
170
|
-
const label = element
|
|
171
|
-
const rel = element
|
|
172
|
-
const target = element
|
|
169
|
+
const label = readAttribute(element, "aria-label") ?? undefined;
|
|
170
|
+
const rel = readAttribute(element, "rel") ?? undefined;
|
|
171
|
+
const target = readAttribute(element, "target") ?? undefined;
|
|
173
172
|
const written = writing(pass) &&
|
|
174
173
|
pass.markdownOptions?.links !== false &&
|
|
175
174
|
!href.startsWith("#");
|
|
@@ -189,23 +188,25 @@ const onLinks = (rewriter, pass) => rewriter.on("a[href]", {
|
|
|
189
188
|
});
|
|
190
189
|
const onImages = (rewriter, pass) => rewriter.on("img", {
|
|
191
190
|
element(element) {
|
|
192
|
-
// Lazy-loading scripts
|
|
193
|
-
const src =
|
|
194
|
-
|
|
191
|
+
// Lazy-loading scripts keep the real address in data-src and a placeholder in src.
|
|
192
|
+
const src = [
|
|
193
|
+
readAttribute(element, "src"),
|
|
194
|
+
readAttribute(element, "data-src"),
|
|
195
|
+
readAttribute(element, "data-lazy-src"),
|
|
196
|
+
].find((value) => value && !value.startsWith("data:"));
|
|
197
|
+
if (!collecting(pass) || !src) {
|
|
195
198
|
return;
|
|
196
199
|
}
|
|
197
200
|
const url = absoluteUrl(src, pass.base);
|
|
198
|
-
const alt = element
|
|
199
|
-
if (pass.options.images &&
|
|
200
|
-
pass.images.size < maxImages &&
|
|
201
|
-
!pass.images.has(url)) {
|
|
201
|
+
const alt = readAttribute(element, "alt");
|
|
202
|
+
if (pass.options.images && !pass.images.has(url)) {
|
|
202
203
|
pass.images.set(url, {
|
|
203
204
|
alt: alt === null ? null : clean(alt),
|
|
204
|
-
height: element
|
|
205
|
-
loading: element
|
|
205
|
+
height: readAttribute(element, "height") ?? undefined,
|
|
206
|
+
loading: readAttribute(element, "loading") ?? undefined,
|
|
206
207
|
srcset: element.hasAttribute("srcset"),
|
|
207
208
|
url,
|
|
208
|
-
width: element
|
|
209
|
+
width: readAttribute(element, "width") ?? undefined,
|
|
209
210
|
});
|
|
210
211
|
}
|
|
211
212
|
if (writing(pass) && pass.markdownOptions?.images) {
|
|
@@ -219,11 +220,11 @@ const onResources = (rewriter, pass) => {
|
|
|
219
220
|
.on("script", {
|
|
220
221
|
element(element) {
|
|
221
222
|
if (resources.scripts.length < maxResources) {
|
|
222
|
-
const src = element
|
|
223
|
+
const src = readAttribute(element, "src");
|
|
223
224
|
resources.scripts.push({
|
|
224
225
|
attributes: [...element.attributes].flatMap(([name]) => name ? [name] : []),
|
|
225
226
|
src: src ? absoluteUrl(src, base) : undefined,
|
|
226
|
-
type: element
|
|
227
|
+
type: readAttribute(element, "type") ?? undefined,
|
|
227
228
|
});
|
|
228
229
|
}
|
|
229
230
|
},
|
|
@@ -231,7 +232,7 @@ const onResources = (rewriter, pass) => {
|
|
|
231
232
|
.on("iframe[src]", {
|
|
232
233
|
element(element) {
|
|
233
234
|
if (resources.frames.length < maxResources) {
|
|
234
|
-
resources.frames.push(absoluteUrl(element
|
|
235
|
+
resources.frames.push(absoluteUrl(readAttribute(element, "src") ?? "", base));
|
|
235
236
|
}
|
|
236
237
|
},
|
|
237
238
|
})
|
|
@@ -239,8 +240,8 @@ const onResources = (rewriter, pass) => {
|
|
|
239
240
|
element(element) {
|
|
240
241
|
if (resources.links.length < maxResources) {
|
|
241
242
|
resources.links.push({
|
|
242
|
-
href: absoluteUrl(element
|
|
243
|
-
rel: element
|
|
243
|
+
href: absoluteUrl(readAttribute(element, "href") ?? "", base),
|
|
244
|
+
rel: readAttribute(element, "rel") ?? "",
|
|
244
245
|
});
|
|
245
246
|
}
|
|
246
247
|
},
|
|
@@ -256,7 +257,7 @@ const metaFields = new Map([
|
|
|
256
257
|
const onMeta = (rewriter, pass) => rewriter
|
|
257
258
|
.on("html", {
|
|
258
259
|
element(element) {
|
|
259
|
-
pass.meta.language = element
|
|
260
|
+
pass.meta.language = readAttribute(element, "lang") ?? undefined;
|
|
260
261
|
},
|
|
261
262
|
})
|
|
262
263
|
.on("title", {
|
|
@@ -270,18 +271,18 @@ const onMeta = (rewriter, pass) => rewriter
|
|
|
270
271
|
})
|
|
271
272
|
.on("meta", {
|
|
272
273
|
element(element) {
|
|
273
|
-
const name = element
|
|
274
|
-
element
|
|
274
|
+
const name = readAttribute(element, "name") ??
|
|
275
|
+
readAttribute(element, "property") ??
|
|
275
276
|
"";
|
|
276
277
|
const field = metaFields.get(name.toLowerCase());
|
|
277
278
|
if (field) {
|
|
278
|
-
pass.meta[field] = element
|
|
279
|
+
pass.meta[field] = readAttribute(element, "content") ?? undefined;
|
|
279
280
|
}
|
|
280
281
|
},
|
|
281
282
|
})
|
|
282
283
|
.on("link[rel='canonical']", {
|
|
283
284
|
element(element) {
|
|
284
|
-
const href = element
|
|
285
|
+
const href = readAttribute(element, "href");
|
|
285
286
|
pass.meta.canonical = href ? absoluteUrl(href, pass.base) : undefined;
|
|
286
287
|
},
|
|
287
288
|
});
|
package/dist/text.d.ts
CHANGED
|
@@ -14,3 +14,8 @@ export declare const collapseWhitespace: (text: string) => string;
|
|
|
14
14
|
* conservative so umlauts and other normal characters never trigger it.
|
|
15
15
|
*/
|
|
16
16
|
export declare const looksBinary: (text: string) => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* An attribute's value with its entities decoded. HTMLRewriter returns attributes as written in the
|
|
19
|
+
* source, so `href="?a=1&b=2"` would otherwise keep its `&`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const readAttribute: (element: Element, name: string) => string | null;
|
package/dist/text.js
CHANGED
|
@@ -3,38 +3,261 @@
|
|
|
3
3
|
* parser collects chunks per run of text and decodes them here, so an entity split across two
|
|
4
4
|
* chunks is still decoded correctly.
|
|
5
5
|
*/
|
|
6
|
+
// The named entities of HTML 4, which cover what pages use in practice; numeric ones work anyway.
|
|
6
7
|
const named = new Map(Object.entries({
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
AElig: "\u00C6",
|
|
9
|
+
Aacute: "\u00C1",
|
|
10
|
+
Acirc: "\u00C2",
|
|
11
|
+
Agrave: "\u00C0",
|
|
12
|
+
Alpha: "\u0391",
|
|
13
|
+
Aring: "\u00C5",
|
|
14
|
+
Atilde: "\u00C3",
|
|
15
|
+
Auml: "\u00C4",
|
|
16
|
+
Beta: "\u0392",
|
|
17
|
+
Ccedil: "\u00C7",
|
|
18
|
+
Chi: "\u03A7",
|
|
19
|
+
Dagger: "\u2021",
|
|
20
|
+
Delta: "\u0394",
|
|
21
|
+
ETH: "\u00D0",
|
|
22
|
+
Eacute: "\u00C9",
|
|
23
|
+
Ecirc: "\u00CA",
|
|
24
|
+
Egrave: "\u00C8",
|
|
25
|
+
Epsilon: "\u0395",
|
|
26
|
+
Eta: "\u0397",
|
|
27
|
+
Euml: "\u00CB",
|
|
28
|
+
Gamma: "\u0393",
|
|
29
|
+
Iacute: "\u00CD",
|
|
30
|
+
Icirc: "\u00CE",
|
|
31
|
+
Igrave: "\u00CC",
|
|
32
|
+
Iota: "\u0399",
|
|
33
|
+
Iuml: "\u00CF",
|
|
34
|
+
Kappa: "\u039A",
|
|
35
|
+
Lambda: "\u039B",
|
|
36
|
+
Mu: "\u039C",
|
|
37
|
+
Ntilde: "\u00D1",
|
|
38
|
+
Nu: "\u039D",
|
|
39
|
+
OElig: "\u0152",
|
|
40
|
+
Oacute: "\u00D3",
|
|
41
|
+
Ocirc: "\u00D4",
|
|
42
|
+
Ograve: "\u00D2",
|
|
43
|
+
Omega: "\u03A9",
|
|
44
|
+
Omicron: "\u039F",
|
|
45
|
+
Oslash: "\u00D8",
|
|
46
|
+
Otilde: "\u00D5",
|
|
47
|
+
Ouml: "\u00D6",
|
|
48
|
+
Phi: "\u03A6",
|
|
49
|
+
Pi: "\u03A0",
|
|
50
|
+
Prime: "\u2033",
|
|
51
|
+
Psi: "\u03A8",
|
|
52
|
+
Rho: "\u03A1",
|
|
53
|
+
Scaron: "\u0160",
|
|
54
|
+
Sigma: "\u03A3",
|
|
55
|
+
THORN: "\u00DE",
|
|
56
|
+
Tau: "\u03A4",
|
|
57
|
+
Theta: "\u0398",
|
|
58
|
+
Uacute: "\u00DA",
|
|
59
|
+
Ucirc: "\u00DB",
|
|
60
|
+
Ugrave: "\u00D9",
|
|
61
|
+
Upsilon: "\u03A5",
|
|
62
|
+
Uuml: "\u00DC",
|
|
63
|
+
Xi: "\u039E",
|
|
64
|
+
Yacute: "\u00DD",
|
|
65
|
+
Yuml: "\u0178",
|
|
66
|
+
Zeta: "\u0396",
|
|
67
|
+
aacute: "\u00E1",
|
|
68
|
+
acirc: "\u00E2",
|
|
69
|
+
acute: "\u00B4",
|
|
70
|
+
aelig: "\u00E6",
|
|
71
|
+
agrave: "\u00E0",
|
|
72
|
+
alefsym: "\u2135",
|
|
73
|
+
alpha: "\u03B1",
|
|
10
74
|
amp: "&",
|
|
75
|
+
and: "\u2227",
|
|
76
|
+
ang: "\u2220",
|
|
11
77
|
apos: "'",
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
78
|
+
aring: "\u00E5",
|
|
79
|
+
asymp: "\u2248",
|
|
80
|
+
atilde: "\u00E3",
|
|
81
|
+
auml: "\u00E4",
|
|
82
|
+
bdquo: "\u201E",
|
|
83
|
+
beta: "\u03B2",
|
|
84
|
+
brvbar: "\u00A6",
|
|
85
|
+
bull: "\u2022",
|
|
86
|
+
cap: "\u2229",
|
|
87
|
+
ccedil: "\u00E7",
|
|
88
|
+
cedil: "\u00B8",
|
|
89
|
+
cent: "\u00A2",
|
|
90
|
+
chi: "\u03C7",
|
|
91
|
+
circ: "\u02C6",
|
|
92
|
+
clubs: "\u2663",
|
|
93
|
+
cong: "\u2245",
|
|
94
|
+
copy: "\u00A9",
|
|
95
|
+
crarr: "\u21B5",
|
|
96
|
+
cup: "\u222A",
|
|
97
|
+
curren: "\u00A4",
|
|
98
|
+
dArr: "\u21D3",
|
|
99
|
+
dagger: "\u2020",
|
|
100
|
+
darr: "\u2193",
|
|
101
|
+
deg: "\u00B0",
|
|
102
|
+
delta: "\u03B4",
|
|
103
|
+
diams: "\u2666",
|
|
104
|
+
divide: "\u00F7",
|
|
105
|
+
eacute: "\u00E9",
|
|
106
|
+
ecirc: "\u00EA",
|
|
107
|
+
egrave: "\u00E8",
|
|
108
|
+
empty: "\u2205",
|
|
109
|
+
emsp: "\u2003",
|
|
110
|
+
ensp: "\u2002",
|
|
111
|
+
epsilon: "\u03B5",
|
|
112
|
+
equiv: "\u2261",
|
|
113
|
+
eta: "\u03B7",
|
|
114
|
+
eth: "\u00F0",
|
|
115
|
+
euml: "\u00EB",
|
|
116
|
+
euro: "\u20AC",
|
|
117
|
+
exist: "\u2203",
|
|
118
|
+
fnof: "\u0192",
|
|
119
|
+
forall: "\u2200",
|
|
120
|
+
frac12: "\u00BD",
|
|
121
|
+
frac14: "\u00BC",
|
|
122
|
+
frac34: "\u00BE",
|
|
123
|
+
frasl: "\u2044",
|
|
124
|
+
gamma: "\u03B3",
|
|
125
|
+
ge: "\u2265",
|
|
17
126
|
gt: ">",
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
127
|
+
hArr: "\u21D4",
|
|
128
|
+
harr: "\u2194",
|
|
129
|
+
hearts: "\u2665",
|
|
130
|
+
hellip: "\u2026",
|
|
131
|
+
iacute: "\u00ED",
|
|
132
|
+
icirc: "\u00EE",
|
|
133
|
+
iexcl: "\u00A1",
|
|
134
|
+
igrave: "\u00EC",
|
|
135
|
+
image: "\u2111",
|
|
136
|
+
infin: "\u221E",
|
|
137
|
+
int: "\u222B",
|
|
138
|
+
iota: "\u03B9",
|
|
139
|
+
iquest: "\u00BF",
|
|
140
|
+
isin: "\u2208",
|
|
141
|
+
iuml: "\u00EF",
|
|
142
|
+
kappa: "\u03BA",
|
|
143
|
+
lArr: "\u21D0",
|
|
144
|
+
lambda: "\u03BB",
|
|
145
|
+
lang: "\u2329",
|
|
146
|
+
laquo: "\u00AB",
|
|
147
|
+
larr: "\u2190",
|
|
148
|
+
lceil: "\u2308",
|
|
149
|
+
ldquo: "\u201C",
|
|
150
|
+
le: "\u2264",
|
|
151
|
+
lfloor: "\u230A",
|
|
152
|
+
lowast: "\u2217",
|
|
153
|
+
loz: "\u25CA",
|
|
154
|
+
lrm: "\u200E",
|
|
155
|
+
lsaquo: "\u2039",
|
|
156
|
+
lsquo: "\u2018",
|
|
22
157
|
lt: "<",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
158
|
+
macr: "\u00AF",
|
|
159
|
+
mdash: "\u2014",
|
|
160
|
+
micro: "\u00B5",
|
|
161
|
+
middot: "\u00B7",
|
|
162
|
+
minus: "\u2212",
|
|
163
|
+
mu: "\u03BC",
|
|
164
|
+
nabla: "\u2207",
|
|
165
|
+
nbsp: "\u00A0",
|
|
166
|
+
ndash: "\u2013",
|
|
167
|
+
ne: "\u2260",
|
|
168
|
+
ni: "\u220B",
|
|
169
|
+
not: "\u00AC",
|
|
170
|
+
notin: "\u2209",
|
|
171
|
+
nsub: "\u2284",
|
|
172
|
+
ntilde: "\u00F1",
|
|
173
|
+
nu: "\u03BD",
|
|
174
|
+
oacute: "\u00F3",
|
|
175
|
+
ocirc: "\u00F4",
|
|
176
|
+
oelig: "\u0153",
|
|
177
|
+
ograve: "\u00F2",
|
|
178
|
+
oline: "\u203E",
|
|
179
|
+
omega: "\u03C9",
|
|
180
|
+
omicron: "\u03BF",
|
|
181
|
+
oplus: "\u2295",
|
|
182
|
+
or: "\u2228",
|
|
183
|
+
ordf: "\u00AA",
|
|
184
|
+
ordm: "\u00BA",
|
|
185
|
+
oslash: "\u00F8",
|
|
186
|
+
otilde: "\u00F5",
|
|
187
|
+
otimes: "\u2297",
|
|
188
|
+
ouml: "\u00F6",
|
|
189
|
+
para: "\u00B6",
|
|
190
|
+
part: "\u2202",
|
|
191
|
+
permil: "\u2030",
|
|
192
|
+
perp: "\u22A5",
|
|
193
|
+
phi: "\u03C6",
|
|
194
|
+
pi: "\u03C0",
|
|
195
|
+
piv: "\u03D6",
|
|
196
|
+
plusmn: "\u00B1",
|
|
197
|
+
pound: "\u00A3",
|
|
198
|
+
prime: "\u2032",
|
|
199
|
+
prod: "\u220F",
|
|
200
|
+
prop: "\u221D",
|
|
201
|
+
psi: "\u03C8",
|
|
28
202
|
quot: '"',
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
203
|
+
rArr: "\u21D2",
|
|
204
|
+
radic: "\u221A",
|
|
205
|
+
rang: "\u232A",
|
|
206
|
+
raquo: "\u00BB",
|
|
207
|
+
rarr: "\u2192",
|
|
208
|
+
rceil: "\u2309",
|
|
209
|
+
rdquo: "\u201D",
|
|
210
|
+
real: "\u211C",
|
|
211
|
+
reg: "\u00AE",
|
|
212
|
+
rfloor: "\u230B",
|
|
213
|
+
rho: "\u03C1",
|
|
214
|
+
rlm: "\u200F",
|
|
215
|
+
rsaquo: "\u203A",
|
|
216
|
+
rsquo: "\u2019",
|
|
217
|
+
sbquo: "\u201A",
|
|
218
|
+
scaron: "\u0161",
|
|
219
|
+
sdot: "\u22C5",
|
|
220
|
+
sect: "\u00A7",
|
|
34
221
|
shy: "",
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
222
|
+
sigma: "\u03C3",
|
|
223
|
+
sigmaf: "\u03C2",
|
|
224
|
+
sim: "\u223C",
|
|
225
|
+
spades: "\u2660",
|
|
226
|
+
sub: "\u2282",
|
|
227
|
+
sube: "\u2286",
|
|
228
|
+
sum: "\u2211",
|
|
229
|
+
sup: "\u2283",
|
|
230
|
+
sup1: "\u00B9",
|
|
231
|
+
sup2: "\u00B2",
|
|
232
|
+
sup3: "\u00B3",
|
|
233
|
+
supe: "\u2287",
|
|
234
|
+
szlig: "\u00DF",
|
|
235
|
+
tau: "\u03C4",
|
|
236
|
+
there4: "\u2234",
|
|
237
|
+
theta: "\u03B8",
|
|
238
|
+
thetasym: "\u03D1",
|
|
239
|
+
thinsp: "\u2009",
|
|
240
|
+
thorn: "\u00FE",
|
|
241
|
+
tilde: "\u02DC",
|
|
242
|
+
times: "\u00D7",
|
|
243
|
+
trade: "\u2122",
|
|
244
|
+
uArr: "\u21D1",
|
|
245
|
+
uacute: "\u00FA",
|
|
246
|
+
uarr: "\u2191",
|
|
247
|
+
ucirc: "\u00FB",
|
|
248
|
+
ugrave: "\u00F9",
|
|
249
|
+
uml: "\u00A8",
|
|
250
|
+
upsih: "\u03D2",
|
|
251
|
+
upsilon: "\u03C5",
|
|
252
|
+
uuml: "\u00FC",
|
|
253
|
+
weierp: "\u2118",
|
|
254
|
+
xi: "\u03BE",
|
|
255
|
+
yacute: "\u00FD",
|
|
256
|
+
yen: "\u00A5",
|
|
257
|
+
yuml: "\u00FF",
|
|
258
|
+
zeta: "\u03B6",
|
|
259
|
+
zwj: "\u200D",
|
|
260
|
+
zwnj: "\u200C",
|
|
38
261
|
}));
|
|
39
262
|
const fromCodePoint = (value) => {
|
|
40
263
|
try {
|
|
@@ -75,3 +298,11 @@ export const looksBinary = (text) => {
|
|
|
75
298
|
const control = text.match(controlCharacters)?.length ?? 0;
|
|
76
299
|
return (text.includes("\u0000") || control > 20 || control / text.length > 0.05);
|
|
77
300
|
};
|
|
301
|
+
/**
|
|
302
|
+
* An attribute's value with its entities decoded. HTMLRewriter returns attributes as written in the
|
|
303
|
+
* source, so `href="?a=1&b=2"` would otherwise keep its `&`.
|
|
304
|
+
*/
|
|
305
|
+
export const readAttribute = (element, name) => {
|
|
306
|
+
const value = element.getAttribute(name);
|
|
307
|
+
return value === null ? null : decodeEntities(value);
|
|
308
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@citation-media/html-parser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Streaming HTML parser for Cloudflare Workers: links, images, resources, and Markdown without a DOM, built on HTMLRewriter.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare-workers",
|