@wdprlib/render 1.0.0-rc.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +39 -22
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +39 -22
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -4209,8 +4209,8 @@ function renderGitlabSnippet(ctx, snippetId) {
|
|
|
4209
4209
|
}
|
|
4210
4210
|
|
|
4211
4211
|
// packages/render/src/elements/embed-block.ts
|
|
4212
|
-
var
|
|
4213
|
-
var
|
|
4212
|
+
var import_htmlparser2 = require("htmlparser2");
|
|
4213
|
+
var import_sanitize_html = __toESM(require("sanitize-html"));
|
|
4214
4214
|
var BOOLEAN_ATTRIBUTES = [
|
|
4215
4215
|
"allowfullscreen",
|
|
4216
4216
|
"async",
|
|
@@ -4244,21 +4244,42 @@ var DEFAULT_EMBED_ALLOWLIST = [
|
|
|
4244
4244
|
{ host: "w.soundcloud.com", pathPrefix: "/player/" },
|
|
4245
4245
|
{ host: "codepen.io" }
|
|
4246
4246
|
];
|
|
4247
|
-
var
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4247
|
+
var SANITIZE_CONFIG = {
|
|
4248
|
+
allowedTags: ["iframe"],
|
|
4249
|
+
allowedAttributes: {
|
|
4250
|
+
iframe: [
|
|
4251
|
+
"src",
|
|
4252
|
+
"allow",
|
|
4253
|
+
"allowfullscreen",
|
|
4254
|
+
"frameborder",
|
|
4255
|
+
"height",
|
|
4256
|
+
"loading",
|
|
4257
|
+
"referrerpolicy",
|
|
4258
|
+
"sandbox",
|
|
4259
|
+
"title",
|
|
4260
|
+
"width"
|
|
4261
|
+
]
|
|
4262
|
+
},
|
|
4263
|
+
allowedSchemes: ["https"]
|
|
4264
|
+
};
|
|
4265
|
+
function findIframes(html) {
|
|
4266
|
+
const doc = import_htmlparser2.parseDocument(html);
|
|
4267
|
+
const iframes = [];
|
|
4268
|
+
function walk(nodes) {
|
|
4269
|
+
for (const node of nodes) {
|
|
4270
|
+
if (node.type === "tag") {
|
|
4271
|
+
if (node.name === "iframe") {
|
|
4272
|
+
iframes.push(node);
|
|
4273
|
+
}
|
|
4274
|
+
if (node.children) {
|
|
4275
|
+
walk(node.children);
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4254
4278
|
}
|
|
4255
4279
|
}
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "loading", "referrerpolicy", "sandbox"],
|
|
4260
|
-
FORBID_ATTR: ["srcdoc", "onload", "onerror", "onclick"]
|
|
4261
|
-
};
|
|
4280
|
+
walk(doc.children);
|
|
4281
|
+
return iframes;
|
|
4282
|
+
}
|
|
4262
4283
|
function matchesHostPattern(hostname, pattern) {
|
|
4263
4284
|
const lowerHostname = hostname.toLowerCase();
|
|
4264
4285
|
const lowerPattern = pattern.toLowerCase();
|
|
@@ -4288,20 +4309,16 @@ function matchesAllowlistEntry(url, entry) {
|
|
|
4288
4309
|
return true;
|
|
4289
4310
|
}
|
|
4290
4311
|
function validateAndSanitizeEmbed(content, allowlist) {
|
|
4291
|
-
const sanitized =
|
|
4292
|
-
...DOMPURIFY_CONFIG,
|
|
4293
|
-
RETURN_TRUSTED_TYPE: false
|
|
4294
|
-
});
|
|
4312
|
+
const sanitized = import_sanitize_html.default(content.trim(), SANITIZE_CONFIG);
|
|
4295
4313
|
if (!sanitized.trim()) {
|
|
4296
4314
|
return null;
|
|
4297
4315
|
}
|
|
4298
|
-
const
|
|
4299
|
-
const iframes = dom.window.document.querySelectorAll("iframe");
|
|
4316
|
+
const iframes = findIframes(sanitized);
|
|
4300
4317
|
if (iframes.length !== 1) {
|
|
4301
4318
|
return null;
|
|
4302
4319
|
}
|
|
4303
4320
|
const iframe = iframes[0];
|
|
4304
|
-
const src = iframe.
|
|
4321
|
+
const src = iframe.attribs.src?.trim();
|
|
4305
4322
|
if (!src) {
|
|
4306
4323
|
return null;
|
|
4307
4324
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -15,7 +15,7 @@ interface EmbedAllowlistEntry {
|
|
|
15
15
|
* Only iframes with src matching these host+path patterns will be rendered.
|
|
16
16
|
*
|
|
17
17
|
* Note: Set to null to allow any HTTPS iframe (Wikidot's 'anyiframe' behavior).
|
|
18
|
-
*
|
|
18
|
+
* sanitize-html still enforces HTTPS-only and blocks dangerous attributes.
|
|
19
19
|
*/
|
|
20
20
|
declare const DEFAULT_EMBED_ALLOWLIST: EmbedAllowlistEntry[] | null;
|
|
21
21
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ interface EmbedAllowlistEntry {
|
|
|
15
15
|
* Only iframes with src matching these host+path patterns will be rendered.
|
|
16
16
|
*
|
|
17
17
|
* Note: Set to null to allow any HTTPS iframe (Wikidot's 'anyiframe' behavior).
|
|
18
|
-
*
|
|
18
|
+
* sanitize-html still enforces HTTPS-only and blocks dangerous attributes.
|
|
19
19
|
*/
|
|
20
20
|
declare const DEFAULT_EMBED_ALLOWLIST: EmbedAllowlistEntry[] | null;
|
|
21
21
|
/**
|
package/dist/index.js
CHANGED
|
@@ -4159,8 +4159,8 @@ function renderGitlabSnippet(ctx, snippetId) {
|
|
|
4159
4159
|
}
|
|
4160
4160
|
|
|
4161
4161
|
// packages/render/src/elements/embed-block.ts
|
|
4162
|
-
import
|
|
4163
|
-
import
|
|
4162
|
+
import { parseDocument } from "htmlparser2";
|
|
4163
|
+
import sanitizeHtml from "sanitize-html";
|
|
4164
4164
|
var BOOLEAN_ATTRIBUTES = [
|
|
4165
4165
|
"allowfullscreen",
|
|
4166
4166
|
"async",
|
|
@@ -4194,21 +4194,42 @@ var DEFAULT_EMBED_ALLOWLIST = [
|
|
|
4194
4194
|
{ host: "w.soundcloud.com", pathPrefix: "/player/" },
|
|
4195
4195
|
{ host: "codepen.io" }
|
|
4196
4196
|
];
|
|
4197
|
-
var
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4197
|
+
var SANITIZE_CONFIG = {
|
|
4198
|
+
allowedTags: ["iframe"],
|
|
4199
|
+
allowedAttributes: {
|
|
4200
|
+
iframe: [
|
|
4201
|
+
"src",
|
|
4202
|
+
"allow",
|
|
4203
|
+
"allowfullscreen",
|
|
4204
|
+
"frameborder",
|
|
4205
|
+
"height",
|
|
4206
|
+
"loading",
|
|
4207
|
+
"referrerpolicy",
|
|
4208
|
+
"sandbox",
|
|
4209
|
+
"title",
|
|
4210
|
+
"width"
|
|
4211
|
+
]
|
|
4212
|
+
},
|
|
4213
|
+
allowedSchemes: ["https"]
|
|
4214
|
+
};
|
|
4215
|
+
function findIframes(html) {
|
|
4216
|
+
const doc = parseDocument(html);
|
|
4217
|
+
const iframes = [];
|
|
4218
|
+
function walk(nodes) {
|
|
4219
|
+
for (const node of nodes) {
|
|
4220
|
+
if (node.type === "tag") {
|
|
4221
|
+
if (node.name === "iframe") {
|
|
4222
|
+
iframes.push(node);
|
|
4223
|
+
}
|
|
4224
|
+
if (node.children) {
|
|
4225
|
+
walk(node.children);
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4204
4228
|
}
|
|
4205
4229
|
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "loading", "referrerpolicy", "sandbox"],
|
|
4210
|
-
FORBID_ATTR: ["srcdoc", "onload", "onerror", "onclick"]
|
|
4211
|
-
};
|
|
4230
|
+
walk(doc.children);
|
|
4231
|
+
return iframes;
|
|
4232
|
+
}
|
|
4212
4233
|
function matchesHostPattern(hostname, pattern) {
|
|
4213
4234
|
const lowerHostname = hostname.toLowerCase();
|
|
4214
4235
|
const lowerPattern = pattern.toLowerCase();
|
|
@@ -4238,20 +4259,16 @@ function matchesAllowlistEntry(url, entry) {
|
|
|
4238
4259
|
return true;
|
|
4239
4260
|
}
|
|
4240
4261
|
function validateAndSanitizeEmbed(content, allowlist) {
|
|
4241
|
-
const sanitized =
|
|
4242
|
-
...DOMPURIFY_CONFIG,
|
|
4243
|
-
RETURN_TRUSTED_TYPE: false
|
|
4244
|
-
});
|
|
4262
|
+
const sanitized = sanitizeHtml(content.trim(), SANITIZE_CONFIG);
|
|
4245
4263
|
if (!sanitized.trim()) {
|
|
4246
4264
|
return null;
|
|
4247
4265
|
}
|
|
4248
|
-
const
|
|
4249
|
-
const iframes = dom.window.document.querySelectorAll("iframe");
|
|
4266
|
+
const iframes = findIframes(sanitized);
|
|
4250
4267
|
if (iframes.length !== 1) {
|
|
4251
4268
|
return null;
|
|
4252
4269
|
}
|
|
4253
4270
|
const iframe = iframes[0];
|
|
4254
|
-
const src = iframe.
|
|
4271
|
+
const src = iframe.attribs.src?.trim();
|
|
4255
4272
|
if (!src) {
|
|
4256
4273
|
return null;
|
|
4257
4274
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wdprlib/render",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "HTML renderer for Wikidot markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"html",
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@wdprlib/ast": "1.0.0
|
|
43
|
-
"
|
|
44
|
-
"
|
|
42
|
+
"@wdprlib/ast": "1.0.0",
|
|
43
|
+
"domhandler": "^5.0.3",
|
|
44
|
+
"htmlparser2": "^10.0.0",
|
|
45
|
+
"sanitize-html": "^2.14.0",
|
|
45
46
|
"temml": "^0.13.1"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"@types/
|
|
49
|
-
"@types/jsdom": "^27.0.0"
|
|
49
|
+
"@types/sanitize-html": "^2.13.0"
|
|
50
50
|
}
|
|
51
51
|
}
|