create-html-element 5.0.0 → 6.0.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/index.d.ts +56 -2
- package/index.js +48 -15
- package/package.json +8 -8
- package/readme.md +34 -2
package/index.d.ts
CHANGED
|
@@ -29,7 +29,43 @@ export type TextOptions = {
|
|
|
29
29
|
readonly text?: string;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
export type
|
|
32
|
+
export type ChildrenOptions = {
|
|
33
|
+
/**
|
|
34
|
+
HTML tag children.
|
|
35
|
+
|
|
36
|
+
Strings are escaped, objects are passed to `createHtmlElement`.
|
|
37
|
+
|
|
38
|
+
This option is mutually exclusive with the `html` and `text` options.
|
|
39
|
+
|
|
40
|
+
@example
|
|
41
|
+
```
|
|
42
|
+
import createHtmlElement from 'create-html-element';
|
|
43
|
+
|
|
44
|
+
createHtmlElement({
|
|
45
|
+
name: 'div',
|
|
46
|
+
children: [
|
|
47
|
+
'<unsafe>',
|
|
48
|
+
{
|
|
49
|
+
name: 'iframe',
|
|
50
|
+
attributes: {
|
|
51
|
+
src: 'https://example.com'
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'span',
|
|
56
|
+
text: 'Label here <em>plz</em>'
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
//=> '<div><unsafe><iframe src="https://example.com"></iframe><span>Label here <em>plz</em></span></div>'
|
|
61
|
+
```
|
|
62
|
+
*/
|
|
63
|
+
readonly children?: readonly Child[];
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type Child = string | (Options & {readonly length?: never});
|
|
67
|
+
|
|
68
|
+
export type Options = BaseOptions & MergeExclusive<HtmlOptions, MergeExclusive<TextOptions, ChildrenOptions>>;
|
|
33
69
|
|
|
34
70
|
/**
|
|
35
71
|
Create a HTML element string.
|
|
@@ -56,8 +92,26 @@ createHtmlElement({
|
|
|
56
92
|
|
|
57
93
|
createHtmlElement({text: 'Hello <em>World</em>'});
|
|
58
94
|
//=> '<div>Hello <em>World</em></div>'
|
|
95
|
+
|
|
96
|
+
createHtmlElement({
|
|
97
|
+
name: 'div',
|
|
98
|
+
children: [
|
|
99
|
+
'<unsafe>',
|
|
100
|
+
{
|
|
101
|
+
name: 'iframe',
|
|
102
|
+
attributes: {
|
|
103
|
+
src: 'https://example.com'
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'span',
|
|
108
|
+
text: 'Label here <em>plz</em>'
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
});
|
|
112
|
+
//=> '<div><unsafe><iframe src="https://example.com"></iframe><span>Label here <em>plz</em></span></div>'
|
|
59
113
|
```
|
|
60
114
|
*/
|
|
61
115
|
export default function createHtmlElement(options?: Options): string;
|
|
62
116
|
|
|
63
|
-
export {HTMLAttributes} from 'stringify-attributes';
|
|
117
|
+
export type {HTMLAttributes} from 'stringify-attributes';
|
package/index.js
CHANGED
|
@@ -4,24 +4,57 @@ import {htmlEscape} from 'escape-goat';
|
|
|
4
4
|
|
|
5
5
|
const voidHtmlTags = new Set(voidHtmlTagsArray);
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
// Matches a valid HTML tag name (a letter followed by letters, digits, hyphens, underscores, or periods).
|
|
8
|
+
const tagNamePattern = /^[a-z][\w\-.]*$/iv;
|
|
9
|
+
|
|
10
|
+
export default function createHtmlElement({
|
|
11
|
+
name = 'div',
|
|
12
|
+
attributes = {},
|
|
13
|
+
html,
|
|
14
|
+
text,
|
|
15
|
+
children,
|
|
16
|
+
} = {}) {
|
|
17
|
+
if (!tagNamePattern.test(name)) {
|
|
18
|
+
throw new Error(`Invalid tag name: ${JSON.stringify(name)}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const hasHtml = html !== undefined;
|
|
22
|
+
const hasText = text !== undefined;
|
|
23
|
+
const hasChildren = children !== undefined;
|
|
24
|
+
|
|
25
|
+
if ([hasHtml, hasText, hasChildren].filter(Boolean).length > 1) {
|
|
26
|
+
throw new Error('The `html`, `text`, and `children` options are mutually exclusive');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (hasChildren && !Array.isArray(children)) {
|
|
30
|
+
throw new TypeError('The `children` option must be an array');
|
|
17
31
|
}
|
|
18
32
|
|
|
19
|
-
const
|
|
20
|
-
|
|
33
|
+
const openingTag = `<${name}${stringifyAttributes(attributes)}>`;
|
|
34
|
+
|
|
35
|
+
if (voidHtmlTags.has(name)) {
|
|
36
|
+
return openingTag;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let content = '';
|
|
40
|
+
|
|
41
|
+
if (hasChildren) {
|
|
42
|
+
content = children.map(child => {
|
|
43
|
+
if (typeof child === 'string') {
|
|
44
|
+
return htmlEscape(child);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof child === 'object' && child !== null && !Array.isArray(child)) {
|
|
48
|
+
return createHtmlElement(child);
|
|
49
|
+
}
|
|
21
50
|
|
|
22
|
-
|
|
23
|
-
|
|
51
|
+
throw new TypeError('Children must be strings or objects');
|
|
52
|
+
}).join('');
|
|
53
|
+
} else if (hasText) {
|
|
54
|
+
content = htmlEscape(text);
|
|
55
|
+
} else if (hasHtml) {
|
|
56
|
+
content = html;
|
|
24
57
|
}
|
|
25
58
|
|
|
26
|
-
return
|
|
59
|
+
return `${openingTag}${content}</${name}>`;
|
|
27
60
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-html-element",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Create a HTML element string",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/create-html-element",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": "
|
|
20
|
+
"node": ">=22"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
23
|
"test": "xo && ava && tsd"
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"escape-goat": "^4.0.0",
|
|
40
|
-
"html-tags": "^
|
|
41
|
-
"stringify-attributes": "^
|
|
42
|
-
"type-fest": "^
|
|
40
|
+
"html-tags": "^5.1.0",
|
|
41
|
+
"stringify-attributes": "^5.0.0",
|
|
42
|
+
"type-fest": "^5.7.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"ava": "^
|
|
46
|
-
"tsd": "^0.
|
|
47
|
-
"xo": "^0.
|
|
45
|
+
"ava": "^8.0.1",
|
|
46
|
+
"tsd": "^0.33.0",
|
|
47
|
+
"xo": "^3.0.2"
|
|
48
48
|
}
|
|
49
49
|
}
|
package/readme.md
CHANGED
|
@@ -58,13 +58,45 @@ HTML tag attributes.
|
|
|
58
58
|
|
|
59
59
|
HTML tag value in unescaped HTML.
|
|
60
60
|
|
|
61
|
-
This option is mutually exclusive with the `text`
|
|
61
|
+
This option is mutually exclusive with the `text` and `children` options.
|
|
62
62
|
|
|
63
63
|
##### text
|
|
64
64
|
|
|
65
65
|
HTML tag value in escaped HTML.
|
|
66
66
|
|
|
67
|
-
This option is mutually exclusive with the `html`
|
|
67
|
+
This option is mutually exclusive with the `html` and `children` options.
|
|
68
|
+
|
|
69
|
+
##### children
|
|
70
|
+
|
|
71
|
+
Type: `Array<string|object>`
|
|
72
|
+
|
|
73
|
+
HTML tag children.
|
|
74
|
+
|
|
75
|
+
Strings are escaped, objects are passed to `createHtmlElement`.
|
|
76
|
+
|
|
77
|
+
This option is mutually exclusive with the `html` and `text` options.
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import createHtmlElement from 'create-html-element';
|
|
81
|
+
|
|
82
|
+
createHtmlElement({
|
|
83
|
+
name: 'div',
|
|
84
|
+
children: [
|
|
85
|
+
'<unsafe>',
|
|
86
|
+
{
|
|
87
|
+
name: 'iframe',
|
|
88
|
+
attributes: {
|
|
89
|
+
src: 'https://example.com'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'span',
|
|
94
|
+
text: 'Label here <em>plz</em>'
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
});
|
|
98
|
+
//=> '<div><unsafe><iframe src="https://example.com"></iframe><span>Label here <em>plz</em></span></div>'
|
|
99
|
+
```
|
|
68
100
|
|
|
69
101
|
## Related
|
|
70
102
|
|