@nerimity/html-embed 1.2.0 → 1.2.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.js +11 -1
- package/example.js +3 -11
- package/package.json +24 -24
- package/src/index.ts +13 -2
package/dist/index.js
CHANGED
|
@@ -210,7 +210,16 @@ function htmlToJson(html) {
|
|
|
210
210
|
}
|
|
211
211
|
function validateHtmlStructure(html) {
|
|
212
212
|
let isMalformed = false;
|
|
213
|
+
const voidElements = ["img", "br", "hr", "input", "meta", "link"];
|
|
213
214
|
const parser = new htmlparser2.Parser({
|
|
215
|
+
onopentag(name) {
|
|
216
|
+
if (voidElements.includes(name.toLowerCase())) {
|
|
217
|
+
const tagClosing = html.substring(parser.startIndex, html.indexOf(">", parser.startIndex) + 1);
|
|
218
|
+
if (!tagClosing.endsWith("/>")) {
|
|
219
|
+
throw new Error(`The <${name}> tag must be self-closed with a slash (e.g., <${name} />).`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
},
|
|
214
223
|
onerror(error) {
|
|
215
224
|
isMalformed = true;
|
|
216
225
|
},
|
|
@@ -222,8 +231,9 @@ function validateHtmlStructure(html) {
|
|
|
222
231
|
}
|
|
223
232
|
const openTags = (html.match(/<[a-zA-Z0-9]+/g) || []).length;
|
|
224
233
|
const closeTags = (html.match(/<\/[a-zA-Z0-9]+/g) || []).length;
|
|
234
|
+
const voidTagsFound = (html.match(/<(img|br|hr|input|meta|link)/g) || []).length;
|
|
225
235
|
const expectedCloseTags = openTags - (html.match(/<(img|br|hr)/g) || []).length;
|
|
226
|
-
if (
|
|
236
|
+
if (openTags - voidTagsFound !== closeTags) {
|
|
227
237
|
throw new Error("Mismatched or unclosed HTML tags.");
|
|
228
238
|
}
|
|
229
239
|
}
|
package/example.js
CHANGED
|
@@ -4,16 +4,8 @@ const { htmlToJson } = require("./dist");
|
|
|
4
4
|
|
|
5
5
|
// throw error because invalid css
|
|
6
6
|
console.log(htmlToJson(`
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
</div>
|
|
7
|
+
<dIv class="owo" style="owo: lol"; onclick="Lol">
|
|
8
|
+
<br />
|
|
9
|
+
</dIv>
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
<style>
|
|
14
|
-
}
|
|
15
|
-
.owo {
|
|
16
|
-
color: red;
|
|
17
|
-
}
|
|
18
|
-
</style>
|
|
19
11
|
`))
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nerimity/html-embed",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build": "tsc",
|
|
8
|
-
"example": "tsc & node example.js"
|
|
9
|
-
},
|
|
10
|
-
"keywords": [],
|
|
11
|
-
"author": "",
|
|
12
|
-
"license": "ISC",
|
|
13
|
-
"devDependencies": {
|
|
14
|
-
"@types/css": "^0.0.37",
|
|
15
|
-
"@types/node": "^22.10.10",
|
|
16
|
-
"typescript": "^5.5.2"
|
|
17
|
-
},
|
|
18
|
-
"dependencies": {
|
|
19
|
-
"css": "^3.0.0",
|
|
20
|
-
"csstree-validator": "^4.0.1",
|
|
21
|
-
"htm": "^3.1.0",
|
|
22
|
-
"htmlparser2": "^10.0.0"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@nerimity/html-embed",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"example": "tsc & node example.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/css": "^0.0.37",
|
|
15
|
+
"@types/node": "^22.10.10",
|
|
16
|
+
"typescript": "^5.5.2"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"css": "^3.0.0",
|
|
20
|
+
"csstree-validator": "^4.0.1",
|
|
21
|
+
"htm": "^3.1.0",
|
|
22
|
+
"htmlparser2": "^10.0.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -182,8 +182,18 @@ export function htmlToJson(html: string) {
|
|
|
182
182
|
|
|
183
183
|
function validateHtmlStructure(html: string) {
|
|
184
184
|
let isMalformed = false;
|
|
185
|
+
const voidElements = ["img", "br", "hr", "input", "meta", "link"];
|
|
185
186
|
const parser = new htmlparser2.Parser(
|
|
186
187
|
{
|
|
188
|
+
onopentag(name) {
|
|
189
|
+
if (voidElements.includes(name.toLowerCase())) {
|
|
190
|
+
const tagClosing = html.substring(parser.startIndex, html.indexOf(">", parser.startIndex) + 1);
|
|
191
|
+
|
|
192
|
+
if (!tagClosing.endsWith("/>")) {
|
|
193
|
+
throw new Error(`The <${name}> tag must be self-closed with a slash (e.g., <${name} />).`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
187
197
|
onerror(error) {
|
|
188
198
|
isMalformed = true;
|
|
189
199
|
},
|
|
@@ -200,11 +210,12 @@ function validateHtmlStructure(html: string) {
|
|
|
200
210
|
|
|
201
211
|
const openTags = (html.match(/<[a-zA-Z0-9]+/g) || []).length;
|
|
202
212
|
const closeTags = (html.match(/<\/[a-zA-Z0-9]+/g) || []).length;
|
|
203
|
-
|
|
213
|
+
const voidTagsFound = (html.match(/<(img|br|hr|input|meta|link)/g) || []).length;
|
|
214
|
+
|
|
204
215
|
const expectedCloseTags =
|
|
205
216
|
openTags - (html.match(/<(img|br|hr)/g) || []).length;
|
|
206
217
|
|
|
207
|
-
if (
|
|
218
|
+
if (openTags - voidTagsFound !== closeTags) {
|
|
208
219
|
throw new Error("Mismatched or unclosed HTML tags.");
|
|
209
220
|
}
|
|
210
221
|
}
|