ghtml 3.0.8 → 3.0.9

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 CHANGED
@@ -1,13 +1,11 @@
1
1
  /* eslint-disable no-unused-vars */
2
-
3
- import { html } from "../src/index.js";
2
+ import { html } from "ghtml";
4
3
  import { Bench } from "tinybench";
5
4
  import { writeFileSync } from "node:fs";
6
5
  import { Buffer } from "node:buffer";
7
6
 
8
- let result = "";
9
-
10
7
  const bench = new Bench({ time: 500 });
8
+ let result = "";
11
9
 
12
10
  bench.add("simple HTML formatting", () => {
13
11
  result = html`<div>Hello, world!</div>`;
package/bin/README.md CHANGED
@@ -5,7 +5,7 @@ Append unique hashes to assets referenced in your views to aggressively cache th
5
5
  Running the following command will scan asset files found in the `roots` path(s) and replace their references in the `refs` path(s) with hashed versions:
6
6
 
7
7
  ```sh
8
- npx ghtml --roots="base/path/to/scan/assets/1/,base/path/to/scan/assets/2/" --refs="views/path/to/append/hashes/1/,views/path/to/append/hashes/2/"
8
+ npx ghtml --roots="base/path/to/scan/assets/1/,base/path/to/scan/assets/2/" --refs="views/path/to/append/hashes/1/,views/path/to/append/hashes/2/" --prefix="/optional/prefix/"
9
9
  ```
10
10
 
11
11
  ## Example (Fastify)
@@ -1 +1 @@
1
- globalThis.console.warn("Hello World!");
1
+ globalThis.console.log("Hello World!");
@@ -1,5 +1,3 @@
1
- /* eslint-disable n/no-missing-import, require-await */
2
-
3
1
  import { html } from "ghtml";
4
2
 
5
3
  export default async (fastify) => {
@@ -21,7 +19,7 @@ export default async (fastify) => {
21
19
  <body>
22
20
  !${inner}
23
21
  </body>
24
- </html> `;
22
+ </html>`;
25
23
  });
26
24
 
27
25
  fastify.get("/", async (request, reply) => {
@@ -1,5 +1,3 @@
1
- /* eslint-disable n/no-missing-import */
2
-
3
1
  import Fastify from "fastify";
4
2
 
5
3
  const fastify = Fastify();
@@ -17,10 +15,7 @@ await fastify.register(import("@fastify/static"), {
17
15
  // Routes
18
16
  fastify.register(import("./routes/index.js"));
19
17
 
20
- fastify.listen({ port: 5050 }, (err, address) => {
21
- if (err) {
22
- throw err;
23
- }
18
+ // Listen
19
+ const address = await fastify.listen({ port: 5050 });
24
20
 
25
- globalThis.console.warn(`Server listening at ${address}`);
26
- });
21
+ globalThis.console.log(`Server listening at ${address}`);
package/bin/src/index.js CHANGED
@@ -18,7 +18,7 @@ const parseArguments = (args) => {
18
18
  }
19
19
 
20
20
  if (!roots || !refs) {
21
- globalThis.console.error(
21
+ globalThis.console.log(
22
22
  'Usage: npx ghtml --roots="base/path/to/scan/assets/1/,base/path/to/scan/assets/2/" --refs="views/path/to/append/hashes/1/,views/path/to/append/hashes/2/" [--prefix="/optional/prefix/"]',
23
23
  );
24
24
  process.exit(1);
@@ -31,10 +31,10 @@ const main = async () => {
31
31
  const { roots, refs, prefix } = parseArguments(process.argv.slice(2));
32
32
 
33
33
  try {
34
- globalThis.console.warn(`Generating hashes and updating file paths...`);
35
- globalThis.console.warn(`Scanning files in: ${roots}`);
36
- globalThis.console.warn(`Updating files in: ${refs}`);
37
- globalThis.console.warn(`Using prefix: ${prefix}`);
34
+ globalThis.console.log(`Generating hashes and updating file paths...`);
35
+ globalThis.console.log(`Scanning files in: ${roots}`);
36
+ globalThis.console.log(`Updating files in: ${refs}`);
37
+ globalThis.console.log(`Using prefix: ${prefix}`);
38
38
 
39
39
  await generateHashesAndReplace({
40
40
  roots,
@@ -42,11 +42,11 @@ const main = async () => {
42
42
  prefix,
43
43
  });
44
44
 
45
- globalThis.console.warn(
45
+ globalThis.console.log(
46
46
  "Hash generation and file updates completed successfully.",
47
47
  );
48
48
  } catch (error) {
49
- globalThis.console.error(`Error occurred: ${error.message}`);
49
+ globalThis.console.log(`Error occurred: ${error.message}`);
50
50
  process.exit(1);
51
51
  }
52
52
  };
package/bin/src/utils.js CHANGED
@@ -1,5 +1,3 @@
1
- /* eslint-disable no-await-in-loop */
2
-
3
1
  import { Glob } from "glob";
4
2
  import { createHash } from "node:crypto";
5
3
  import { readFile, writeFile } from "node:fs/promises";
@@ -8,11 +6,13 @@ import { win32, posix } from "node:path";
8
6
  const generateFileHash = async (filePath) => {
9
7
  try {
10
8
  const fileBuffer = await readFile(filePath);
9
+
11
10
  return createHash("md5").update(fileBuffer).digest("hex").slice(0, 16);
12
11
  } catch (err) {
13
12
  if (err.code !== "ENOENT") {
14
13
  throw err;
15
14
  }
15
+
16
16
  return "";
17
17
  }
18
18
  };
@@ -26,6 +26,7 @@ const updateFilePathsWithHashes = async (
26
26
  ) => {
27
27
  for (let ref of refs) {
28
28
  ref = ref.replaceAll(win32.sep, posix.sep);
29
+
29
30
  if (!ref.endsWith("/")) {
30
31
  ref += "/";
31
32
  }
@@ -84,11 +85,13 @@ export const generateHashesAndReplace = async ({
84
85
  skipPatterns = ["**/node_modules/**"],
85
86
  }) => {
86
87
  const fileHashes = new Map();
88
+
87
89
  roots = Array.isArray(roots) ? roots : [roots];
88
90
  refs = Array.isArray(refs) ? refs : [refs];
89
91
 
90
92
  for (let root of roots) {
91
93
  root = root.replaceAll(win32.sep, posix.sep);
94
+
92
95
  if (!root.endsWith("/")) {
93
96
  root += "/";
94
97
  }
@@ -114,6 +117,7 @@ export const generateHashesAndReplace = async ({
114
117
 
115
118
  for (let i = 0; i < files.length; ++i) {
116
119
  const fileRelativePath = posix.relative(root, files[i]);
120
+
117
121
  fileHashes.set(fileRelativePath, hashes[i]);
118
122
  }
119
123
  }
package/eslint.config.js CHANGED
@@ -1,3 +1,14 @@
1
1
  import grules from "grules";
2
2
 
3
- export default [...grules];
3
+ export default [
4
+ ...grules,
5
+ {
6
+ rules: {
7
+ "no-await-in-loop": "off",
8
+ "require-unicode-regexp": "off",
9
+ },
10
+ },
11
+ {
12
+ ignores: ["bin/example/**/*.js"],
13
+ },
14
+ ];
package/package.json CHANGED
@@ -3,7 +3,7 @@
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.0.8",
6
+ "version": "3.0.9",
7
7
  "type": "module",
8
8
  "bin": "./bin/src/index.js",
9
9
  "main": "./src/index.js",
@@ -19,7 +19,7 @@
19
19
  "test": "npm run lint && c8 --100 node --test test/*.js",
20
20
  "lint": "eslint . && prettier --check .",
21
21
  "lint:fix": "eslint --fix . && prettier --write .",
22
- "typescript": "tsc src/*.js --allowJs --declaration --emitDeclarationOnly"
22
+ "typescript": "tsc src/*.js --allowJs --declaration --emitDeclarationOnly --skipLibCheck"
23
23
  },
24
24
  "dependencies": {
25
25
  "glob": "^10.4.5"
@@ -27,7 +27,7 @@
27
27
  "devDependencies": {
28
28
  "@fastify/pre-commit": "^2.1.0",
29
29
  "c8": "^10.1.2",
30
- "grules": "^0.25.0",
30
+ "grules": "^0.25.3",
31
31
  "tinybench": "^2.9.0",
32
32
  "typescript": ">=5.6.2"
33
33
  },
package/src/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export { html, htmlGenerator, htmlAsyncGenerator } from "./html.js";
1
+ export function html(literals: TemplateStringsArray, ...expressions: any[]): string;
2
+ export function htmlGenerator(literals: TemplateStringsArray, ...expressions: any[]): Generator<string, void, void>;
3
+ export function htmlAsyncGenerator(literals: TemplateStringsArray, ...expressions: any[]): AsyncGenerator<string, void, void>;
package/src/index.js CHANGED
@@ -1 +1,246 @@
1
- export { html, htmlGenerator, htmlAsyncGenerator } from "./html.js";
1
+ const escapeRegExp = /["&'<=>]/g;
2
+
3
+ const escapeFunction = (string) => {
4
+ let escaped = "";
5
+ let start = 0;
6
+
7
+ while (escapeRegExp.test(string)) {
8
+ const i = escapeRegExp.lastIndex - 1;
9
+
10
+ switch (string.charCodeAt(i)) {
11
+ case 34:
12
+ escaped += string.slice(start, i) + "&#34;"; // "
13
+ break;
14
+ case 38:
15
+ escaped += string.slice(start, i) + "&#38;"; // &
16
+ break;
17
+ case 39:
18
+ escaped += string.slice(start, i) + "&#39;"; // '
19
+ break;
20
+ case 60:
21
+ escaped += string.slice(start, i) + "&#60;"; // <
22
+ break;
23
+ case 61:
24
+ escaped += string.slice(start, i) + "&#61;"; // =
25
+ break;
26
+ default: {
27
+ escaped += string.slice(start, i) + "&#62;"; // >
28
+ }
29
+ }
30
+
31
+ start = escapeRegExp.lastIndex;
32
+ }
33
+
34
+ return escaped + string.slice(start);
35
+ };
36
+
37
+ /**
38
+ * @param {TemplateStringsArray} literals literals
39
+ * @param {...any} expressions expressions
40
+ * @returns {string} string
41
+ */
42
+ export const html = (literals, ...expressions) => {
43
+ let accumulator = "";
44
+
45
+ for (let i = 0; i !== expressions.length; ++i) {
46
+ let literal = literals.raw[i];
47
+ let string = Array.isArray(expressions[i])
48
+ ? expressions[i].join("")
49
+ : String(expressions[i] ?? "");
50
+
51
+ if (literal && literal.charCodeAt(literal.length - 1) === 33) {
52
+ literal = literal.slice(0, -1);
53
+ } else {
54
+ string &&= escapeFunction(string);
55
+ }
56
+
57
+ accumulator += literal + string;
58
+ }
59
+
60
+ return accumulator + literals.raw[expressions.length];
61
+ };
62
+
63
+ /**
64
+ * @param {TemplateStringsArray} literals literals
65
+ * @param {...any} expressions expressions
66
+ * @yields {string} string
67
+ * @returns {Generator<string, void, void>} Generator<string, void, void>
68
+ */
69
+ export const htmlGenerator = function* (literals, ...expressions) {
70
+ for (let i = 0; i !== expressions.length; ++i) {
71
+ let expression = expressions[i];
72
+ let literal = literals.raw[i];
73
+ let string;
74
+
75
+ if (typeof expression === "string") {
76
+ string = expression;
77
+ } else if (expression === undefined || expression === null) {
78
+ string = "";
79
+ } else {
80
+ if (expression[Symbol.iterator]) {
81
+ const isRaw =
82
+ Boolean(literal) && literal.charCodeAt(literal.length - 1) === 33;
83
+
84
+ if (isRaw) {
85
+ literal = literal.slice(0, -1);
86
+ }
87
+
88
+ if (literal) {
89
+ yield literal;
90
+ }
91
+
92
+ for (expression of expression) {
93
+ if (typeof expression === "string") {
94
+ string = expression;
95
+ } else {
96
+ if (expression === undefined || expression === null) {
97
+ continue;
98
+ }
99
+
100
+ if (expression[Symbol.iterator]) {
101
+ for (expression of expression) {
102
+ if (expression === undefined || expression === null) {
103
+ continue;
104
+ }
105
+
106
+ string = String(expression);
107
+
108
+ if (string) {
109
+ if (!isRaw) {
110
+ string = escapeFunction(string);
111
+ }
112
+
113
+ yield string;
114
+ }
115
+ }
116
+
117
+ continue;
118
+ }
119
+
120
+ string = String(expression);
121
+ }
122
+
123
+ if (string) {
124
+ if (!isRaw) {
125
+ string = escapeFunction(string);
126
+ }
127
+
128
+ yield string;
129
+ }
130
+ }
131
+
132
+ continue;
133
+ }
134
+
135
+ string = String(expression);
136
+ }
137
+
138
+ if (literal && literal.charCodeAt(literal.length - 1) === 33) {
139
+ literal = literal.slice(0, -1);
140
+ } else {
141
+ string &&= escapeFunction(string);
142
+ }
143
+
144
+ if (literal || string) {
145
+ yield literal + string;
146
+ }
147
+ }
148
+
149
+ if (literals.raw[expressions.length]) {
150
+ yield literals.raw[expressions.length];
151
+ }
152
+ };
153
+
154
+ /**
155
+ * @param {TemplateStringsArray} literals literals
156
+ * @param {...any} expressions expressions
157
+ * @yields {string} string
158
+ * @returns {AsyncGenerator<string, void, void>} AsyncGenerator<string, void, void>
159
+ */
160
+ export const htmlAsyncGenerator = async function* (literals, ...expressions) {
161
+ for (let i = 0; i !== expressions.length; ++i) {
162
+ let expression = await expressions[i];
163
+ let literal = literals.raw[i];
164
+ let string;
165
+
166
+ if (typeof expression === "string") {
167
+ string = expression;
168
+ } else if (expression === undefined || expression === null) {
169
+ string = "";
170
+ } else {
171
+ if (expression[Symbol.iterator] || expression[Symbol.asyncIterator]) {
172
+ const isRaw =
173
+ Boolean(literal) && literal.charCodeAt(literal.length - 1) === 33;
174
+
175
+ if (isRaw) {
176
+ literal = literal.slice(0, -1);
177
+ }
178
+
179
+ if (literal) {
180
+ yield literal;
181
+ }
182
+
183
+ for await (expression of expression) {
184
+ if (typeof expression === "string") {
185
+ string = expression;
186
+ } else {
187
+ if (expression === undefined || expression === null) {
188
+ continue;
189
+ }
190
+
191
+ if (
192
+ expression[Symbol.iterator] ||
193
+ expression[Symbol.asyncIterator]
194
+ ) {
195
+ for await (expression of expression) {
196
+ if (expression === undefined || expression === null) {
197
+ continue;
198
+ }
199
+
200
+ string = String(expression);
201
+
202
+ if (string) {
203
+ if (!isRaw) {
204
+ string = escapeFunction(string);
205
+ }
206
+
207
+ yield string;
208
+ }
209
+ }
210
+
211
+ continue;
212
+ }
213
+
214
+ string = String(expression);
215
+ }
216
+
217
+ if (string) {
218
+ if (!isRaw) {
219
+ string = escapeFunction(string);
220
+ }
221
+
222
+ yield string;
223
+ }
224
+ }
225
+
226
+ continue;
227
+ }
228
+
229
+ string = String(expression);
230
+ }
231
+
232
+ if (literal && literal.charCodeAt(literal.length - 1) === 33) {
233
+ literal = literal.slice(0, -1);
234
+ } else {
235
+ string &&= escapeFunction(string);
236
+ }
237
+
238
+ if (literal || string) {
239
+ yield literal + string;
240
+ }
241
+ }
242
+
243
+ if (literals.raw[expressions.length]) {
244
+ yield literals.raw[expressions.length];
245
+ }
246
+ };
package/src/html.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export function html(literals: TemplateStringsArray, ...expressions: any[]): string;
2
- export function htmlGenerator(literals: TemplateStringsArray, ...expressions: any[]): Generator<string, void, void>;
3
- export function htmlAsyncGenerator(literals: TemplateStringsArray, ...expressions: any[]): AsyncGenerator<string, void, void>;
package/src/html.js DELETED
@@ -1,248 +0,0 @@
1
- /* eslint-disable no-await-in-loop, require-unicode-regexp */
2
-
3
- const escapeRegExp = /["&'<=>]/g;
4
-
5
- const escapeFunction = (string) => {
6
- let escaped = "";
7
- let start = 0;
8
-
9
- while (escapeRegExp.test(string)) {
10
- const i = escapeRegExp.lastIndex - 1;
11
-
12
- switch (string.charCodeAt(i)) {
13
- case 34: // "
14
- escaped += string.slice(start, i) + "&#34;";
15
- break;
16
- case 38: // &
17
- escaped += string.slice(start, i) + "&#38;";
18
- break;
19
- case 39: // '
20
- escaped += string.slice(start, i) + "&#39;";
21
- break;
22
- case 60: // <
23
- escaped += string.slice(start, i) + "&#60;";
24
- break;
25
- case 61: // =
26
- escaped += string.slice(start, i) + "&#61;";
27
- break;
28
- case 62: // >
29
- escaped += string.slice(start, i) + "&#62;";
30
- break;
31
- }
32
-
33
- start = escapeRegExp.lastIndex;
34
- }
35
-
36
- return escaped + string.slice(start);
37
- };
38
-
39
- /**
40
- * @param {TemplateStringsArray} literals literals
41
- * @param {...any} expressions expressions
42
- * @returns {string} string
43
- */
44
- export const html = (literals, ...expressions) => {
45
- let accumulator = "";
46
-
47
- for (let i = 0; i !== expressions.length; ++i) {
48
- let literal = literals.raw[i];
49
- let string = Array.isArray(expressions[i])
50
- ? expressions[i].join("")
51
- : String(expressions[i] ?? "");
52
-
53
- if (literal && literal.charCodeAt(literal.length - 1) === 33) {
54
- literal = literal.slice(0, -1);
55
- } else {
56
- string &&= escapeFunction(string);
57
- }
58
-
59
- accumulator += literal + string;
60
- }
61
-
62
- return accumulator + literals.raw[expressions.length];
63
- };
64
-
65
- /**
66
- * @param {TemplateStringsArray} literals literals
67
- * @param {...any} expressions expressions
68
- * @yields {string} string
69
- * @returns {Generator<string, void, void>} Generator<string, void, void>
70
- */
71
- export const htmlGenerator = function* (literals, ...expressions) {
72
- for (let i = 0; i !== expressions.length; ++i) {
73
- let expression = expressions[i];
74
- let literal = literals.raw[i];
75
- let string;
76
-
77
- if (typeof expression === "string") {
78
- string = expression;
79
- } else if (expression === undefined || expression === null) {
80
- string = "";
81
- } else {
82
- if (expression[Symbol.iterator]) {
83
- const isRaw =
84
- Boolean(literal) && literal.charCodeAt(literal.length - 1) === 33;
85
-
86
- if (isRaw) {
87
- literal = literal.slice(0, -1);
88
- }
89
-
90
- if (literal) {
91
- yield literal;
92
- }
93
-
94
- for (expression of expression) {
95
- if (typeof expression === "string") {
96
- string = expression;
97
- } else {
98
- if (expression === undefined || expression === null) {
99
- continue;
100
- }
101
-
102
- if (expression[Symbol.iterator]) {
103
- for (expression of expression) {
104
- if (expression === undefined || expression === null) {
105
- continue;
106
- }
107
-
108
- string = String(expression);
109
-
110
- if (string) {
111
- if (!isRaw) {
112
- string = escapeFunction(string);
113
- }
114
-
115
- yield string;
116
- }
117
- }
118
-
119
- continue;
120
- }
121
-
122
- string = String(expression);
123
- }
124
-
125
- if (string) {
126
- if (!isRaw) {
127
- string = escapeFunction(string);
128
- }
129
-
130
- yield string;
131
- }
132
- }
133
-
134
- continue;
135
- }
136
-
137
- string = String(expression);
138
- }
139
-
140
- if (literal && literal.charCodeAt(literal.length - 1) === 33) {
141
- literal = literal.slice(0, -1);
142
- } else {
143
- string &&= escapeFunction(string);
144
- }
145
-
146
- if (literal || string) {
147
- yield literal + string;
148
- }
149
- }
150
-
151
- if (literals.raw[expressions.length]) {
152
- yield literals.raw[expressions.length];
153
- }
154
- };
155
-
156
- /**
157
- * @param {TemplateStringsArray} literals literals
158
- * @param {...any} expressions expressions
159
- * @yields {string} string
160
- * @returns {AsyncGenerator<string, void, void>} AsyncGenerator<string, void, void>
161
- */
162
- export const htmlAsyncGenerator = async function* (literals, ...expressions) {
163
- for (let i = 0; i !== expressions.length; ++i) {
164
- let expression = await expressions[i];
165
- let literal = literals.raw[i];
166
- let string;
167
-
168
- if (typeof expression === "string") {
169
- string = expression;
170
- } else if (expression === undefined || expression === null) {
171
- string = "";
172
- } else {
173
- if (expression[Symbol.iterator] || expression[Symbol.asyncIterator]) {
174
- const isRaw =
175
- Boolean(literal) && literal.charCodeAt(literal.length - 1) === 33;
176
-
177
- if (isRaw) {
178
- literal = literal.slice(0, -1);
179
- }
180
-
181
- if (literal) {
182
- yield literal;
183
- }
184
-
185
- for await (expression of expression) {
186
- if (typeof expression === "string") {
187
- string = expression;
188
- } else {
189
- if (expression === undefined || expression === null) {
190
- continue;
191
- }
192
-
193
- if (
194
- expression[Symbol.iterator] ||
195
- expression[Symbol.asyncIterator]
196
- ) {
197
- for await (expression of expression) {
198
- if (expression === undefined || expression === null) {
199
- continue;
200
- }
201
-
202
- string = String(expression);
203
-
204
- if (string) {
205
- if (!isRaw) {
206
- string = escapeFunction(string);
207
- }
208
-
209
- yield string;
210
- }
211
- }
212
-
213
- continue;
214
- }
215
-
216
- string = String(expression);
217
- }
218
-
219
- if (string) {
220
- if (!isRaw) {
221
- string = escapeFunction(string);
222
- }
223
-
224
- yield string;
225
- }
226
- }
227
-
228
- continue;
229
- }
230
-
231
- string = String(expression);
232
- }
233
-
234
- if (literal && literal.charCodeAt(literal.length - 1) === 33) {
235
- literal = literal.slice(0, -1);
236
- } else {
237
- string &&= escapeFunction(string);
238
- }
239
-
240
- if (literal || string) {
241
- yield literal + string;
242
- }
243
- }
244
-
245
- if (literals.raw[expressions.length]) {
246
- yield literals.raw[expressions.length];
247
- }
248
- };