@nerimity/html-embed 1.1.16 → 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.d.ts.map +1 -1
- package/dist/index.js +114 -5
- package/example.js +3 -11
- package/package.json +24 -23
- package/src/index.ts +123 -39
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiLA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM;;;;;;;;IAGtC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -6,10 +39,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
39
|
exports.htmlToJson = htmlToJson;
|
|
7
40
|
const htm_1 = __importDefault(require("htm"));
|
|
8
41
|
const css_1 = __importDefault(require("css"));
|
|
42
|
+
const htmlparser2 = __importStar(require("htmlparser2"));
|
|
9
43
|
const { validate } = require("csstree-validator");
|
|
10
|
-
const allowedTags = [
|
|
44
|
+
const allowedTags = [
|
|
45
|
+
"h1",
|
|
46
|
+
"h2",
|
|
47
|
+
"h3",
|
|
48
|
+
"h4",
|
|
49
|
+
"h5",
|
|
50
|
+
"h6",
|
|
51
|
+
"div",
|
|
52
|
+
"img",
|
|
53
|
+
"span",
|
|
54
|
+
"strong",
|
|
55
|
+
"a",
|
|
56
|
+
"style",
|
|
57
|
+
"p",
|
|
58
|
+
"ul",
|
|
59
|
+
"li",
|
|
60
|
+
"ol",
|
|
61
|
+
"table",
|
|
62
|
+
"thead",
|
|
63
|
+
"tbody",
|
|
64
|
+
"tr",
|
|
65
|
+
"td",
|
|
66
|
+
"th",
|
|
67
|
+
"blockquote",
|
|
68
|
+
"pre",
|
|
69
|
+
"br",
|
|
70
|
+
"b",
|
|
71
|
+
"i",
|
|
72
|
+
"u",
|
|
73
|
+
"em",
|
|
74
|
+
"small",
|
|
75
|
+
"mark",
|
|
76
|
+
"sub",
|
|
77
|
+
"sup",
|
|
78
|
+
"code",
|
|
79
|
+
"hr",
|
|
80
|
+
"section",
|
|
81
|
+
"article",
|
|
82
|
+
"header",
|
|
83
|
+
"footer",
|
|
84
|
+
"nav",
|
|
85
|
+
];
|
|
11
86
|
const allowedAttributes = ["href", "src", "color", "style", "class"];
|
|
12
87
|
const allowedCssProperties = [
|
|
88
|
+
"opacity",
|
|
13
89
|
"background-clip",
|
|
14
90
|
"-webkitBackgroundClip",
|
|
15
91
|
"-webkitTextFillColor",
|
|
@@ -66,7 +142,9 @@ const allowedCssProperties = [
|
|
|
66
142
|
"alignContent",
|
|
67
143
|
"alignSelf",
|
|
68
144
|
"whiteSpace",
|
|
145
|
+
"wordBreak",
|
|
69
146
|
"fontFamily",
|
|
147
|
+
"fontStyle",
|
|
70
148
|
"fontSize",
|
|
71
149
|
"fontWeight",
|
|
72
150
|
"zIndex",
|
|
@@ -91,7 +169,7 @@ function h(tag, props, ...children) {
|
|
|
91
169
|
}
|
|
92
170
|
// check if attributes are safe
|
|
93
171
|
if (props) {
|
|
94
|
-
const unsafeAttribute = Object.keys(props).find(prop => !allowedAttributes.includes(prop));
|
|
172
|
+
const unsafeAttribute = Object.keys(props).find((prop) => !allowedAttributes.includes(prop));
|
|
95
173
|
if (unsafeAttribute) {
|
|
96
174
|
throw new Error(unsafeAttribute + " attribute is not allowed!");
|
|
97
175
|
}
|
|
@@ -99,7 +177,7 @@ function h(tag, props, ...children) {
|
|
|
99
177
|
// check if styles are safe
|
|
100
178
|
if (props === null || props === void 0 ? void 0 : props.style) {
|
|
101
179
|
const styles = props.style.split(";");
|
|
102
|
-
const unsafeCssProperty = styles.find(style => {
|
|
180
|
+
const unsafeCssProperty = styles.find((style) => {
|
|
103
181
|
if (style === "")
|
|
104
182
|
return false;
|
|
105
183
|
const keyVal = style.split(":");
|
|
@@ -115,7 +193,8 @@ function h(tag, props, ...children) {
|
|
|
115
193
|
}
|
|
116
194
|
}
|
|
117
195
|
if (props === null || props === void 0 ? void 0 : props.href) {
|
|
118
|
-
if (!props.href.startsWith("http://") &&
|
|
196
|
+
if (!props.href.startsWith("http://") &&
|
|
197
|
+
!props.href.startsWith("https://")) {
|
|
119
198
|
throw new Error("href must start with http:// or https://");
|
|
120
199
|
}
|
|
121
200
|
}
|
|
@@ -126,8 +205,38 @@ function h(tag, props, ...children) {
|
|
|
126
205
|
}
|
|
127
206
|
const _html = htm_1.default.bind(h);
|
|
128
207
|
function htmlToJson(html) {
|
|
208
|
+
validateHtmlStructure(html);
|
|
129
209
|
return _html([html]);
|
|
130
210
|
}
|
|
211
|
+
function validateHtmlStructure(html) {
|
|
212
|
+
let isMalformed = false;
|
|
213
|
+
const voidElements = ["img", "br", "hr", "input", "meta", "link"];
|
|
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
|
+
},
|
|
223
|
+
onerror(error) {
|
|
224
|
+
isMalformed = true;
|
|
225
|
+
},
|
|
226
|
+
}, { decodeEntities: true, lowerCaseTags: true });
|
|
227
|
+
parser.write(html);
|
|
228
|
+
parser.end();
|
|
229
|
+
if (isMalformed) {
|
|
230
|
+
throw new Error("Invalid HTML structure detected.");
|
|
231
|
+
}
|
|
232
|
+
const openTags = (html.match(/<[a-zA-Z0-9]+/g) || []).length;
|
|
233
|
+
const closeTags = (html.match(/<\/[a-zA-Z0-9]+/g) || []).length;
|
|
234
|
+
const voidTagsFound = (html.match(/<(img|br|hr|input|meta|link)/g) || []).length;
|
|
235
|
+
const expectedCloseTags = openTags - (html.match(/<(img|br|hr)/g) || []).length;
|
|
236
|
+
if (openTags - voidTagsFound !== closeTags) {
|
|
237
|
+
throw new Error("Mismatched or unclosed HTML tags.");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
131
240
|
function checkCSS(cssVal) {
|
|
132
241
|
var _a;
|
|
133
242
|
if (validate(cssVal).length) {
|
|
@@ -156,7 +265,7 @@ function checkCSS(cssVal) {
|
|
|
156
265
|
}
|
|
157
266
|
}
|
|
158
267
|
function cssNameToJsName(name) {
|
|
159
|
-
var split = name.split("-").filter(n => n);
|
|
268
|
+
var split = name.split("-").filter((n) => n);
|
|
160
269
|
var output = "";
|
|
161
270
|
for (var i = 0; i < split.length; i++) {
|
|
162
271
|
if (i > 0 && split[i].length > 0 && !(i == 1 && split[i] == "ms")) {
|
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,23 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nerimity/html-embed",
|
|
3
|
-
"version": "1.1
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
}
|
|
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
|
@@ -1,11 +1,53 @@
|
|
|
1
|
-
import htm from
|
|
2
|
-
import css from
|
|
3
|
-
|
|
1
|
+
import htm from "htm";
|
|
2
|
+
import css from "css";
|
|
3
|
+
import * as htmlparser2 from "htmlparser2";
|
|
4
|
+
const { validate } = require("csstree-validator");
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const allowedTags = [
|
|
7
|
+
"h1",
|
|
8
|
+
"h2",
|
|
9
|
+
"h3",
|
|
10
|
+
"h4",
|
|
11
|
+
"h5",
|
|
12
|
+
"h6",
|
|
13
|
+
"div",
|
|
14
|
+
"img",
|
|
15
|
+
"span",
|
|
16
|
+
"strong",
|
|
17
|
+
"a",
|
|
18
|
+
"style",
|
|
19
|
+
"p",
|
|
20
|
+
"ul",
|
|
21
|
+
"li",
|
|
22
|
+
"ol",
|
|
23
|
+
"table",
|
|
24
|
+
"thead",
|
|
25
|
+
"tbody",
|
|
26
|
+
"tr",
|
|
27
|
+
"td",
|
|
28
|
+
"th",
|
|
29
|
+
"blockquote",
|
|
30
|
+
"pre",
|
|
31
|
+
"br",
|
|
32
|
+
"b",
|
|
33
|
+
"i",
|
|
34
|
+
"u",
|
|
35
|
+
"em",
|
|
36
|
+
"small",
|
|
37
|
+
"mark",
|
|
38
|
+
"sub",
|
|
39
|
+
"sup",
|
|
40
|
+
"code",
|
|
41
|
+
"hr",
|
|
42
|
+
"section",
|
|
43
|
+
"article",
|
|
44
|
+
"header",
|
|
45
|
+
"footer",
|
|
46
|
+
"nav",
|
|
47
|
+
];
|
|
48
|
+
const allowedAttributes = ["href", "src", "color", "style", "class"];
|
|
8
49
|
const allowedCssProperties = [
|
|
50
|
+
"opacity",
|
|
9
51
|
"background-clip",
|
|
10
52
|
"-webkitBackgroundClip",
|
|
11
53
|
"-webkitTextFillColor",
|
|
@@ -62,7 +104,9 @@ const allowedCssProperties = [
|
|
|
62
104
|
"alignContent",
|
|
63
105
|
"alignSelf",
|
|
64
106
|
"whiteSpace",
|
|
107
|
+
"wordBreak",
|
|
65
108
|
"fontFamily",
|
|
109
|
+
"fontStyle",
|
|
66
110
|
"fontSize",
|
|
67
111
|
"fontWeight",
|
|
68
112
|
"zIndex",
|
|
@@ -79,68 +123,111 @@ const allowedCssProperties = [
|
|
|
79
123
|
"overflowY",
|
|
80
124
|
"userSelect",
|
|
81
125
|
"pointerEvents",
|
|
82
|
-
]
|
|
83
|
-
|
|
126
|
+
];
|
|
84
127
|
|
|
85
128
|
function h(tag: string, props: any, ...children: any[]) {
|
|
86
129
|
// check if tag is safe
|
|
87
130
|
if (!allowedTags.includes(tag.toLowerCase())) {
|
|
88
|
-
throw new Error(tag+" tag is not allowed!")
|
|
131
|
+
throw new Error(tag + " tag is not allowed!");
|
|
89
132
|
}
|
|
90
133
|
// check if attributes are safe
|
|
91
134
|
if (props) {
|
|
92
|
-
const unsafeAttribute = Object.keys(props).find(
|
|
135
|
+
const unsafeAttribute = Object.keys(props).find(
|
|
136
|
+
(prop) => !allowedAttributes.includes(prop)
|
|
137
|
+
);
|
|
93
138
|
if (unsafeAttribute) {
|
|
94
|
-
throw new Error(unsafeAttribute+" attribute is not allowed!")
|
|
139
|
+
throw new Error(unsafeAttribute + " attribute is not allowed!");
|
|
95
140
|
}
|
|
96
141
|
}
|
|
97
142
|
// check if styles are safe
|
|
98
143
|
if (props?.style) {
|
|
99
144
|
const styles: string[] = props.style.split(";");
|
|
100
|
-
const unsafeCssProperty = styles.find(style => {
|
|
145
|
+
const unsafeCssProperty = styles.find((style) => {
|
|
101
146
|
if (style === "") return false;
|
|
102
|
-
const keyVal = style.split(":")
|
|
103
|
-
const key = keyVal[0].trim()
|
|
104
|
-
const value = keyVal[1].trim()
|
|
147
|
+
const keyVal = style.split(":");
|
|
148
|
+
const key = keyVal[0].trim();
|
|
149
|
+
const value = keyVal[1].trim();
|
|
105
150
|
if (key === "position" && value === "fixed") {
|
|
106
|
-
throw new Error(value + " value is not allowed for "+ key + "!")
|
|
151
|
+
throw new Error(value + " value is not allowed for " + key + "!");
|
|
107
152
|
}
|
|
108
|
-
return !allowedCssProperties.includes(cssNameToJsName(key))
|
|
109
|
-
})
|
|
153
|
+
return !allowedCssProperties.includes(cssNameToJsName(key));
|
|
154
|
+
});
|
|
110
155
|
if (unsafeCssProperty) {
|
|
111
|
-
throw new Error(
|
|
156
|
+
throw new Error(
|
|
157
|
+
unsafeCssProperty.split(":")[0].trim() + " property is not allowed!"
|
|
158
|
+
);
|
|
112
159
|
}
|
|
113
160
|
}
|
|
114
161
|
if (props?.href) {
|
|
115
|
-
if (
|
|
116
|
-
|
|
162
|
+
if (
|
|
163
|
+
!props.href.startsWith("http://") &&
|
|
164
|
+
!props.href.startsWith("https://")
|
|
165
|
+
) {
|
|
166
|
+
throw new Error("href must start with http:// or https://");
|
|
117
167
|
}
|
|
118
168
|
}
|
|
119
169
|
if (tag.toLowerCase() === "style" && children[0]) {
|
|
120
170
|
checkCSS(children[0]);
|
|
121
171
|
}
|
|
122
|
-
|
|
172
|
+
|
|
123
173
|
return { tag, attributes: props, content: children };
|
|
124
174
|
}
|
|
125
175
|
|
|
126
176
|
const _html = htm.bind(h);
|
|
127
177
|
|
|
128
|
-
|
|
129
|
-
|
|
130
178
|
export function htmlToJson(html: string) {
|
|
131
|
-
|
|
179
|
+
validateHtmlStructure(html);
|
|
180
|
+
return _html([html] as any);
|
|
132
181
|
}
|
|
133
182
|
|
|
183
|
+
function validateHtmlStructure(html: string) {
|
|
184
|
+
let isMalformed = false;
|
|
185
|
+
const voidElements = ["img", "br", "hr", "input", "meta", "link"];
|
|
186
|
+
const parser = new htmlparser2.Parser(
|
|
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
|
+
},
|
|
197
|
+
onerror(error) {
|
|
198
|
+
isMalformed = true;
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{ decodeEntities: true, lowerCaseTags: true }
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
parser.write(html);
|
|
205
|
+
parser.end();
|
|
134
206
|
|
|
207
|
+
if (isMalformed) {
|
|
208
|
+
throw new Error("Invalid HTML structure detected.");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const openTags = (html.match(/<[a-zA-Z0-9]+/g) || []).length;
|
|
212
|
+
const closeTags = (html.match(/<\/[a-zA-Z0-9]+/g) || []).length;
|
|
213
|
+
const voidTagsFound = (html.match(/<(img|br|hr|input|meta|link)/g) || []).length;
|
|
214
|
+
|
|
215
|
+
const expectedCloseTags =
|
|
216
|
+
openTags - (html.match(/<(img|br|hr)/g) || []).length;
|
|
217
|
+
|
|
218
|
+
if (openTags - voidTagsFound !== closeTags) {
|
|
219
|
+
throw new Error("Mismatched or unclosed HTML tags.");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
135
222
|
|
|
136
223
|
function checkCSS(cssVal: string) {
|
|
137
224
|
if (validate(cssVal).length) {
|
|
138
|
-
throw new Error("Invalid css!")
|
|
225
|
+
throw new Error("Invalid css!");
|
|
139
226
|
}
|
|
140
|
-
const openCurlyBracketCount = cssVal.match(/{/gi)
|
|
141
|
-
const closeCurlyBracketCount = cssVal.match(/}/gi)
|
|
227
|
+
const openCurlyBracketCount = cssVal.match(/{/gi);
|
|
228
|
+
const closeCurlyBracketCount = cssVal.match(/}/gi);
|
|
142
229
|
if (openCurlyBracketCount?.length !== closeCurlyBracketCount?.length) {
|
|
143
|
-
throw new Error("Extra curly or missing curly brackets found in css!")
|
|
230
|
+
throw new Error("Extra curly or missing curly brackets found in css!");
|
|
144
231
|
}
|
|
145
232
|
const rules = css.parse(cssVal).stylesheet?.rules;
|
|
146
233
|
if (!rules) return;
|
|
@@ -148,21 +235,19 @@ function checkCSS(cssVal: string) {
|
|
|
148
235
|
const rule = rules[i];
|
|
149
236
|
const declarations = (rule as any).declarations;
|
|
150
237
|
for (let x = 0; x < declarations.length; x++) {
|
|
151
|
-
const {property, value} = declarations[x];
|
|
238
|
+
const { property, value } = declarations[x];
|
|
152
239
|
if (!allowedCssProperties.includes(cssNameToJsName(property))) {
|
|
153
|
-
throw new Error(property + " style is not allowed!")
|
|
240
|
+
throw new Error(property + " style is not allowed!");
|
|
154
241
|
}
|
|
155
242
|
if (property === "position" && value === "fixed") {
|
|
156
|
-
throw new Error(value + " value is not allowed for "+ property + "!")
|
|
243
|
+
throw new Error(value + " value is not allowed for " + property + "!");
|
|
157
244
|
}
|
|
158
245
|
}
|
|
159
|
-
|
|
160
246
|
}
|
|
161
247
|
}
|
|
162
248
|
|
|
163
|
-
|
|
164
249
|
function cssNameToJsName(name: string) {
|
|
165
|
-
var split = name.split("-").filter(n => n);
|
|
250
|
+
var split = name.split("-").filter((n) => n);
|
|
166
251
|
var output = "";
|
|
167
252
|
for (var i = 0; i < split.length; i++) {
|
|
168
253
|
if (i > 0 && split[i].length > 0 && !(i == 1 && split[i] == "ms")) {
|
|
@@ -171,12 +256,11 @@ function cssNameToJsName(name: string) {
|
|
|
171
256
|
output += split[i];
|
|
172
257
|
}
|
|
173
258
|
if (name.startsWith("-")) {
|
|
174
|
-
output = "-" + output
|
|
259
|
+
output = "-" + output;
|
|
175
260
|
}
|
|
176
261
|
return output;
|
|
177
262
|
}
|
|
178
263
|
|
|
179
|
-
function jsNameToCssName(name: string)
|
|
180
|
-
|
|
181
|
-
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
264
|
+
function jsNameToCssName(name: string) {
|
|
265
|
+
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
182
266
|
}
|