ghtml 3.0.13 → 3.1.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/bench/index.js +20 -22
- package/bin/src/index.js +4 -2
- package/bin/src/utils.js +9 -5
- package/{eslint.config.js → eslint.config.mjs} +8 -0
- package/package.json +7 -6
- package/src/includeFile.d.ts +4 -0
- package/src/includeFile.js +6 -2
- package/src/index.d.ts +17 -0
- package/src/index.js +17 -15
- package/test/index.js +13 -21
package/bench/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { html } = require("..");
|
|
4
|
+
const { Bench } = require("tinybench");
|
|
5
|
+
const { writeFileSync } = require("node:fs");
|
|
6
6
|
|
|
7
7
|
const bench = new Bench({ time: 500 });
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line no-unused-vars
|
|
8
10
|
let result = "";
|
|
9
11
|
|
|
10
12
|
bench.add("simple HTML formatting", () => {
|
|
@@ -27,18 +29,14 @@ bench.add("multiple string expressions", () => {
|
|
|
27
29
|
const items1 = ["Item 1", undefined, "Item 2", null, 2000, 1500.5];
|
|
28
30
|
bench.add("array expressions", () => {
|
|
29
31
|
result = html`<ul>
|
|
30
|
-
${items1.map((item) => {
|
|
31
|
-
return html`<li>${item}</li>`;
|
|
32
|
-
})}
|
|
32
|
+
${items1.map((item) => html`<li>${item}</li>`)}
|
|
33
33
|
</ul>`;
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
const items2 = ["Item 1", "Item <1.5>", "Item 2", "Item <2.5>", "Item 3"];
|
|
37
37
|
bench.add("array expressions with escapable chars", () => {
|
|
38
38
|
result = html`<ul>
|
|
39
|
-
${items2.map((item) => {
|
|
40
|
-
return html`<li>"${item}" & '${item}'</li>`;
|
|
41
|
-
})}
|
|
39
|
+
${items2.map((item) => html`<li>"${item}" & '${item}'</li>`)}
|
|
42
40
|
</ul>`;
|
|
43
41
|
});
|
|
44
42
|
|
|
@@ -57,9 +55,7 @@ bench.add("multiple types of expressions", () => {
|
|
|
57
55
|
<div>Id: <span>${user.id}</span></div>
|
|
58
56
|
${null}${123}${456n}
|
|
59
57
|
<ul>
|
|
60
|
-
!${items2.map((item) => {
|
|
61
|
-
return html`<li>${item}</li>`;
|
|
62
|
-
})}
|
|
58
|
+
!${items2.map((item) => html`<li>${item}</li>`)}
|
|
63
59
|
</ul>
|
|
64
60
|
`;
|
|
65
61
|
});
|
|
@@ -108,13 +104,15 @@ bench.add("sparse escape", () => {
|
|
|
108
104
|
result = html`<p>${`${"noescape".repeat(250)}<>`.repeat(5)}</p>`;
|
|
109
105
|
});
|
|
110
106
|
|
|
111
|
-
|
|
112
|
-
await bench.
|
|
107
|
+
(async () => {
|
|
108
|
+
await bench.warmup();
|
|
109
|
+
await bench.run();
|
|
113
110
|
|
|
114
|
-
const table = bench.table();
|
|
115
|
-
globalThis.console.table(table);
|
|
111
|
+
const table = bench.table();
|
|
112
|
+
globalThis.console.table(table);
|
|
116
113
|
|
|
117
|
-
writeFileSync(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
);
|
|
114
|
+
writeFileSync(
|
|
115
|
+
"bench/results.json",
|
|
116
|
+
Buffer.from(JSON.stringify(table), "utf8").toString("base64"),
|
|
117
|
+
);
|
|
118
|
+
})();
|
package/bin/src/index.js
CHANGED
package/bin/src/utils.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { Glob } = require("glob");
|
|
4
|
+
const { createHash } = require("node:crypto");
|
|
5
|
+
const { readFile, writeFile } = require("node:fs/promises");
|
|
6
|
+
const { win32, posix } = require("node:path");
|
|
5
7
|
|
|
6
8
|
const generateFileHash = async (filePath) => {
|
|
7
9
|
try {
|
|
@@ -77,7 +79,7 @@ const updateFilePathsWithHashes = async (
|
|
|
77
79
|
}
|
|
78
80
|
};
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
const generateHashesAndReplace = async ({
|
|
81
83
|
roots,
|
|
82
84
|
refs,
|
|
83
85
|
prefix,
|
|
@@ -130,3 +132,5 @@ export const generateHashesAndReplace = async ({
|
|
|
130
132
|
skipPatterns,
|
|
131
133
|
);
|
|
132
134
|
};
|
|
135
|
+
|
|
136
|
+
module.exports.generateHashesAndReplace = generateHashesAndReplace;
|
package/package.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"description": "Replace your template engine with fast JavaScript by leveraging the power of tagged templates.",
|
|
4
4
|
"author": "Gürgün Dayıoğlu",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "3.
|
|
7
|
-
"type": "
|
|
6
|
+
"version": "3.1.1",
|
|
7
|
+
"type": "commonjs",
|
|
8
8
|
"bin": "./bin/src/index.js",
|
|
9
9
|
"main": "./src/index.js",
|
|
10
10
|
"exports": {
|
|
@@ -25,11 +25,12 @@
|
|
|
25
25
|
"glob": "^10.4.5"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@fastify/pre-commit": "^2.
|
|
28
|
+
"@fastify/pre-commit": "^2.2.0",
|
|
29
29
|
"c8": "^10.1.2",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
30
|
+
"globals": "^15.13.0",
|
|
31
|
+
"grules": "^0.26.1",
|
|
32
|
+
"tinybench": "^3.0.7",
|
|
33
|
+
"typescript": ">=5.7.2"
|
|
33
34
|
},
|
|
34
35
|
"repository": {
|
|
35
36
|
"type": "git",
|
package/src/includeFile.d.ts
CHANGED
package/src/includeFile.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { readFileSync } = require("node:fs");
|
|
2
4
|
|
|
3
5
|
const cache = new Map();
|
|
4
6
|
|
|
@@ -6,7 +8,7 @@ const cache = new Map();
|
|
|
6
8
|
* @param {string} path path
|
|
7
9
|
* @returns {string} string
|
|
8
10
|
*/
|
|
9
|
-
|
|
11
|
+
const includeFile = (path) => {
|
|
10
12
|
let file = cache.get(path);
|
|
11
13
|
|
|
12
14
|
if (file === undefined) {
|
|
@@ -16,3 +18,5 @@ export const includeFile = (path) => {
|
|
|
16
18
|
|
|
17
19
|
return file;
|
|
18
20
|
};
|
|
21
|
+
|
|
22
|
+
module.exports.includeFile = includeFile;
|
package/src/index.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {TemplateStringsArray} literals literals
|
|
3
|
+
* @param {...any} expressions expressions
|
|
4
|
+
* @returns {string} string
|
|
5
|
+
*/
|
|
1
6
|
export function html(literals: TemplateStringsArray, ...expressions: any[]): string;
|
|
7
|
+
/**
|
|
8
|
+
* @param {TemplateStringsArray} literals literals
|
|
9
|
+
* @param {...any} expressions expressions
|
|
10
|
+
* @yields {string} string
|
|
11
|
+
* @returns {Generator<string, void, void>} Generator<string, void, void>
|
|
12
|
+
*/
|
|
2
13
|
export function htmlGenerator(literals: TemplateStringsArray, ...expressions: any[]): Generator<string, void, void>;
|
|
14
|
+
/**
|
|
15
|
+
* @param {TemplateStringsArray} literals literals
|
|
16
|
+
* @param {...any} expressions expressions
|
|
17
|
+
* @yields {string} string
|
|
18
|
+
* @returns {AsyncGenerator<string, void, void>} AsyncGenerator<string, void, void>
|
|
19
|
+
*/
|
|
3
20
|
export function htmlAsyncGenerator(literals: TemplateStringsArray, ...expressions: any[]): AsyncGenerator<string, void, void>;
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const _iterator = Symbol.iterator;
|
|
4
|
-
const _asyncIterator = Symbol.asyncIterator;
|
|
1
|
+
"use strict";
|
|
5
2
|
|
|
6
3
|
const escapeRegExp = /["&'<=>]/g;
|
|
7
4
|
|
|
@@ -56,12 +53,13 @@ const escapeFunction = (string) => {
|
|
|
56
53
|
* @param {...any} expressions expressions
|
|
57
54
|
* @returns {string} string
|
|
58
55
|
*/
|
|
59
|
-
|
|
56
|
+
const html = (literals, ...expressions) => {
|
|
60
57
|
let accumulator = "";
|
|
58
|
+
let i = 0;
|
|
61
59
|
|
|
62
|
-
for (
|
|
60
|
+
for (; i !== expressions.length; ++i) {
|
|
63
61
|
let literal = literals.raw[i];
|
|
64
|
-
let string =
|
|
62
|
+
let string = Array.isArray(expressions[i])
|
|
65
63
|
? expressions[i].join("")
|
|
66
64
|
: `${expressions[i] ?? ""}`;
|
|
67
65
|
|
|
@@ -83,7 +81,7 @@ export const html = (literals, ...expressions) => {
|
|
|
83
81
|
* @yields {string} string
|
|
84
82
|
* @returns {Generator<string, void, void>} Generator<string, void, void>
|
|
85
83
|
*/
|
|
86
|
-
|
|
84
|
+
const htmlGenerator = function* (literals, ...expressions) {
|
|
87
85
|
for (let i = 0; i !== expressions.length; ++i) {
|
|
88
86
|
let expression = expressions[i];
|
|
89
87
|
let literal = literals.raw[i];
|
|
@@ -94,7 +92,7 @@ export const htmlGenerator = function* (literals, ...expressions) {
|
|
|
94
92
|
} else if (expression === undefined || expression === null) {
|
|
95
93
|
string = "";
|
|
96
94
|
} else {
|
|
97
|
-
if (typeof expression[
|
|
95
|
+
if (typeof expression[Symbol.iterator] === "function") {
|
|
98
96
|
const isRaw =
|
|
99
97
|
literal.length !== 0 && literal.charCodeAt(literal.length - 1) === 33;
|
|
100
98
|
|
|
@@ -114,7 +112,7 @@ export const htmlGenerator = function* (literals, ...expressions) {
|
|
|
114
112
|
continue;
|
|
115
113
|
}
|
|
116
114
|
|
|
117
|
-
if (typeof expression[
|
|
115
|
+
if (typeof expression[Symbol.iterator] === "function") {
|
|
118
116
|
for (expression of expression) {
|
|
119
117
|
if (expression === undefined || expression === null) {
|
|
120
118
|
continue;
|
|
@@ -174,7 +172,7 @@ export const htmlGenerator = function* (literals, ...expressions) {
|
|
|
174
172
|
* @yields {string} string
|
|
175
173
|
* @returns {AsyncGenerator<string, void, void>} AsyncGenerator<string, void, void>
|
|
176
174
|
*/
|
|
177
|
-
|
|
175
|
+
const htmlAsyncGenerator = async function* (literals, ...expressions) {
|
|
178
176
|
for (let i = 0; i !== expressions.length; ++i) {
|
|
179
177
|
let expression = await expressions[i];
|
|
180
178
|
let literal = literals.raw[i];
|
|
@@ -186,8 +184,8 @@ export const htmlAsyncGenerator = async function* (literals, ...expressions) {
|
|
|
186
184
|
string = "";
|
|
187
185
|
} else {
|
|
188
186
|
if (
|
|
189
|
-
typeof expression[
|
|
190
|
-
typeof expression[
|
|
187
|
+
typeof expression[Symbol.iterator] === "function" ||
|
|
188
|
+
typeof expression[Symbol.asyncIterator] === "function"
|
|
191
189
|
) {
|
|
192
190
|
const isRaw =
|
|
193
191
|
literal.length !== 0 && literal.charCodeAt(literal.length - 1) === 33;
|
|
@@ -209,8 +207,8 @@ export const htmlAsyncGenerator = async function* (literals, ...expressions) {
|
|
|
209
207
|
}
|
|
210
208
|
|
|
211
209
|
if (
|
|
212
|
-
typeof expression[
|
|
213
|
-
typeof expression[
|
|
210
|
+
typeof expression[Symbol.iterator] === "function" ||
|
|
211
|
+
typeof expression[Symbol.asyncIterator] === "function"
|
|
214
212
|
) {
|
|
215
213
|
for await (expression of expression) {
|
|
216
214
|
if (expression === undefined || expression === null) {
|
|
@@ -264,3 +262,7 @@ export const htmlAsyncGenerator = async function* (literals, ...expressions) {
|
|
|
264
262
|
yield literals.raw[expressions.length];
|
|
265
263
|
}
|
|
266
264
|
};
|
|
265
|
+
|
|
266
|
+
module.exports.html = html;
|
|
267
|
+
module.exports.htmlGenerator = htmlGenerator;
|
|
268
|
+
module.exports.htmlAsyncGenerator = htmlAsyncGenerator;
|
package/test/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { html, htmlGenerator, htmlAsyncGenerator } = require("..");
|
|
4
|
+
const { readFile } = require("node:fs/promises");
|
|
5
|
+
const { readFileSync } = require("node:fs");
|
|
6
|
+
const test = require("node:test");
|
|
7
|
+
const assert = require("node:assert/strict");
|
|
6
8
|
|
|
7
9
|
const conditionTrue = true;
|
|
8
10
|
const conditionFalse = false;
|
|
@@ -137,9 +139,7 @@ test("renders multiple html calls", () => {
|
|
|
137
139
|
|
|
138
140
|
test("renders multiple html calls with different expression types", () => {
|
|
139
141
|
const obj = {};
|
|
140
|
-
obj.toString = () =>
|
|
141
|
-
return "description of the object";
|
|
142
|
-
};
|
|
142
|
+
obj.toString = () => "description of the object";
|
|
143
143
|
|
|
144
144
|
// prettier-ignore
|
|
145
145
|
assert.strictEqual(
|
|
@@ -149,7 +149,7 @@ test("renders multiple html calls with different expression types", () => {
|
|
|
149
149
|
!${conditionFalse
|
|
150
150
|
? ""
|
|
151
151
|
:
|
|
152
|
-
html`<em> ${array1.map((i) =>
|
|
152
|
+
html`<em> ${array1.map((i) => i + 1)} </em>`}<br />
|
|
153
153
|
And also, ${false} ${null}${undefined}${obj} is ${true}
|
|
154
154
|
</p>
|
|
155
155
|
`,
|
|
@@ -192,9 +192,7 @@ test("htmlGenerator renders unsafe content", () => {
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
test("htmlGenerator works with nested htmlGenerator calls in an array", () => {
|
|
195
|
-
const generator = htmlGenerator`<ul>!${[1, 2, 3].map((index) => {
|
|
196
|
-
return htmlGenerator`<li>${index}</li>`;
|
|
197
|
-
})}</ul>`;
|
|
195
|
+
const generator = htmlGenerator`<ul>!${[1, 2, 3].map((index) => htmlGenerator`<li>${index}</li>`)}</ul>`;
|
|
198
196
|
let accumulator = "";
|
|
199
197
|
|
|
200
198
|
for (const value of generator) {
|
|
@@ -345,9 +343,7 @@ test("htmlAsyncGenerator works with other generators (escaped)", async () => {
|
|
|
345
343
|
});
|
|
346
344
|
|
|
347
345
|
test("htmlAsyncGenerator works with nested htmlAsyncGenerator calls in an array", async () => {
|
|
348
|
-
const generator = htmlAsyncGenerator`!${[1, 2, 3].map((i) => {
|
|
349
|
-
return htmlAsyncGenerator`${i}: <p>${readFile("test/test.md", "utf8")}</p>`;
|
|
350
|
-
})}`;
|
|
346
|
+
const generator = htmlAsyncGenerator`!${[1, 2, 3].map((i) => htmlAsyncGenerator`${i}: <p>${readFile("test/test.md", "utf8")}</p>`)}`;
|
|
351
347
|
let accumulator = "";
|
|
352
348
|
|
|
353
349
|
for await (const value of generator) {
|
|
@@ -361,9 +357,7 @@ test("htmlAsyncGenerator works with nested htmlAsyncGenerator calls in an array"
|
|
|
361
357
|
});
|
|
362
358
|
|
|
363
359
|
test("htmlAsyncGenerator renders chunks with promises (escaped)", async () => {
|
|
364
|
-
const generator = htmlAsyncGenerator`<ul>!${[1, 2].map((i) => {
|
|
365
|
-
return htmlAsyncGenerator`${i}: ${readFile("test/test.md", "utf8")}`;
|
|
366
|
-
})}</ul>`;
|
|
360
|
+
const generator = htmlAsyncGenerator`<ul>!${[1, 2].map((i) => htmlAsyncGenerator`${i}: ${readFile("test/test.md", "utf8")}`)}</ul>`;
|
|
367
361
|
const fileContent = readFileSync("test/test.md", "utf8").replaceAll(
|
|
368
362
|
">",
|
|
369
363
|
">",
|
|
@@ -392,9 +386,7 @@ test("htmlAsyncGenerator renders chunks with promises (escaped)", async () => {
|
|
|
392
386
|
});
|
|
393
387
|
|
|
394
388
|
test("htmlAsyncGenerator renders chunks with promises (raw)", async () => {
|
|
395
|
-
const generator = htmlAsyncGenerator`<ul>!${[1, 2].map((i) => {
|
|
396
|
-
return htmlAsyncGenerator`${i}: !${readFile("test/test.md", "utf8")}`;
|
|
397
|
-
})}</ul>`;
|
|
389
|
+
const generator = htmlAsyncGenerator`<ul>!${[1, 2].map((i) => htmlAsyncGenerator`${i}: !${readFile("test/test.md", "utf8")}`)}</ul>`;
|
|
398
390
|
const fileContent = readFileSync("test/test.md", "utf8");
|
|
399
391
|
|
|
400
392
|
let value = await generator.next();
|