ghtml 3.0.6 → 3.0.8

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Gürgün Dayıoğlu
3
+ Copyright (c) 2023 Gürgün Dayıoğlu
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/bench/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  /* eslint-disable no-unused-vars */
2
+
2
3
  import { html } from "../src/index.js";
3
4
  import { Bench } from "tinybench";
4
5
  import { writeFileSync } from "node:fs";
5
6
  import { Buffer } from "node:buffer";
6
7
 
7
8
  let result = "";
9
+
8
10
  const bench = new Bench({ time: 500 });
9
11
 
10
12
  bench.add("simple HTML formatting", () => {
@@ -112,7 +114,7 @@ await bench.warmup();
112
114
  await bench.run();
113
115
 
114
116
  const table = bench.table();
115
- console.table(table);
117
+ globalThis.console.table(table);
116
118
 
117
119
  writeFileSync(
118
120
  "bench/results.json",
@@ -1 +1 @@
1
- console.warn("Hello World!");
1
+ globalThis.console.warn("Hello World!");
@@ -6,8 +6,8 @@
6
6
  "build": "ghtml --roots=assets/ --refs=routes/ --prefix=/p/assets/"
7
7
  },
8
8
  "dependencies": {
9
- "@fastify/static": "^7.0.1",
10
- "fastify": "^4.26.1",
9
+ "@fastify/static": "^8.0.1",
10
+ "fastify": "^5.0.0",
11
11
  "ghtml": "file:../../"
12
12
  }
13
13
  }
@@ -1,3 +1,5 @@
1
+ /* eslint-disable n/no-missing-import, require-await */
2
+
1
3
  import { html } from "ghtml";
2
4
 
3
5
  export default async (fastify) => {
@@ -1,10 +1,12 @@
1
+ /* eslint-disable n/no-missing-import */
2
+
1
3
  import Fastify from "fastify";
2
4
 
3
5
  const fastify = Fastify();
4
6
 
5
7
  // Plugins
6
8
  await fastify.register(import("@fastify/static"), {
7
- root: new URL("assets/", import.meta.url).pathname,
9
+ root: new globalThis.URL("assets/", import.meta.url).pathname,
8
10
  prefix: "/p/assets/",
9
11
  wildcard: false,
10
12
  index: false,
@@ -20,5 +22,5 @@ fastify.listen({ port: 5050 }, (err, address) => {
20
22
  throw err;
21
23
  }
22
24
 
23
- console.warn(`Server listening at ${address}`);
25
+ globalThis.console.warn(`Server listening at ${address}`);
24
26
  });
package/bin/src/index.js CHANGED
@@ -18,7 +18,7 @@ const parseArguments = (args) => {
18
18
  }
19
19
 
20
20
  if (!roots || !refs) {
21
- console.error(
21
+ globalThis.console.error(
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
- console.warn(`Generating hashes and updating file paths...`);
35
- console.warn(`Scanning files in: ${roots}`);
36
- console.warn(`Updating files in: ${refs}`);
37
- console.warn(`Using prefix: ${prefix}`);
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}`);
38
38
 
39
39
  await generateHashesAndReplace({
40
40
  roots,
@@ -42,9 +42,11 @@ const main = async () => {
42
42
  prefix,
43
43
  });
44
44
 
45
- console.warn("Hash generation and file updates completed successfully.");
45
+ globalThis.console.warn(
46
+ "Hash generation and file updates completed successfully.",
47
+ );
46
48
  } catch (error) {
47
- console.error(`Error occurred: ${error.message}`);
49
+ globalThis.console.error(`Error occurred: ${error.message}`);
48
50
  process.exit(1);
49
51
  }
50
52
  };
package/bin/src/utils.js CHANGED
@@ -1,3 +1,5 @@
1
+ /* eslint-disable no-await-in-loop */
2
+
1
3
  import { Glob } from "glob";
2
4
  import { createHash } from "node:crypto";
3
5
  import { readFile, writeFile } from "node:fs/promises";
@@ -44,12 +46,12 @@ const updateFilePathsWithHashes = async (
44
46
  for (const [path, hash] of fileHashes) {
45
47
  const fullPath = prefix + path;
46
48
  const escapedPath = fullPath.replace(
47
- /[$()*+.?[\\\]^{|}]/g,
49
+ /[$()*+.?[\\\]^{|}]/gu,
48
50
  String.raw`\$&`,
49
51
  );
50
52
  const regex = new RegExp(
51
53
  `(?<path>${escapedPath})(\\?(?<queryString>[^#"'\`]*))?`,
52
- "g",
54
+ "gu",
53
55
  );
54
56
 
55
57
  content = content.replace(
@@ -74,7 +76,7 @@ const updateFilePathsWithHashes = async (
74
76
  }
75
77
  };
76
78
 
77
- const generateHashesAndReplace = async ({
79
+ export const generateHashesAndReplace = async ({
78
80
  roots,
79
81
  refs,
80
82
  prefix,
@@ -124,5 +126,3 @@ const generateHashesAndReplace = async ({
124
126
  skipPatterns,
125
127
  );
126
128
  };
127
-
128
- export { generateHashesAndReplace };
@@ -0,0 +1,3 @@
1
+ import grules from "grules";
2
+
3
+ export default [...grules];
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.6",
6
+ "version": "3.0.8",
7
7
  "type": "module",
8
8
  "bin": "./bin/src/index.js",
9
9
  "main": "./src/index.js",
@@ -27,9 +27,9 @@
27
27
  "devDependencies": {
28
28
  "@fastify/pre-commit": "^2.1.0",
29
29
  "c8": "^10.1.2",
30
- "grules": "^0.23.3",
30
+ "grules": "^0.25.0",
31
31
  "tinybench": "^2.9.0",
32
- "typescript": ">=5.5.4"
32
+ "typescript": ">=5.6.2"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",
package/src/html.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export function html({ raw: literals }: TemplateStringsArray, ...expressions: any[]): string;
2
- export function htmlGenerator({ raw: literals }: TemplateStringsArray, ...expressions: any[]): Generator<string, void, void>;
3
- export function htmlAsyncGenerator({ raw: literals }: TemplateStringsArray, ...expressions: any[]): AsyncGenerator<string, void, void>;
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 CHANGED
@@ -1,14 +1,12 @@
1
+ /* eslint-disable no-await-in-loop, require-unicode-regexp */
2
+
1
3
  const escapeRegExp = /["&'<=>]/g;
2
4
 
3
5
  const escapeFunction = (string) => {
4
- if (!string || !escapeRegExp.test(string)) {
5
- return string;
6
- }
7
-
8
6
  let escaped = "";
9
7
  let start = 0;
10
8
 
11
- do {
9
+ while (escapeRegExp.test(string)) {
12
10
  const i = escapeRegExp.lastIndex - 1;
13
11
 
14
12
  switch (string.charCodeAt(i)) {
@@ -33,62 +31,57 @@ const escapeFunction = (string) => {
33
31
  }
34
32
 
35
33
  start = escapeRegExp.lastIndex;
36
- } while (escapeRegExp.test(string));
34
+ }
37
35
 
38
36
  return escaped + string.slice(start);
39
37
  };
40
38
 
41
39
  /**
42
- * @param {TemplateStringsArray} literals Tagged template literals.
43
- * @param {...any} expressions Expressions to interpolate.
44
- * @returns {string} The processed HTML string.
40
+ * @param {TemplateStringsArray} literals literals
41
+ * @param {...any} expressions expressions
42
+ * @returns {string} string
45
43
  */
46
- export const html = ({ raw: literals }, ...expressions) => {
44
+ export const html = (literals, ...expressions) => {
47
45
  let accumulator = "";
48
46
 
49
47
  for (let i = 0; i !== expressions.length; ++i) {
50
- let literal = literals[i];
51
- let string =
52
- typeof expressions[i] === "string"
53
- ? expressions[i]
54
- : expressions[i] == null
55
- ? ""
56
- : Array.isArray(expressions[i])
57
- ? expressions[i].join("")
58
- : `${expressions[i]}`;
48
+ let literal = literals.raw[i];
49
+ let string = Array.isArray(expressions[i])
50
+ ? expressions[i].join("")
51
+ : String(expressions[i] ?? "");
59
52
 
60
53
  if (literal && literal.charCodeAt(literal.length - 1) === 33) {
61
54
  literal = literal.slice(0, -1);
62
55
  } else {
63
- string = escapeFunction(string);
56
+ string &&= escapeFunction(string);
64
57
  }
65
58
 
66
59
  accumulator += literal + string;
67
60
  }
68
61
 
69
- return accumulator + literals[expressions.length];
62
+ return accumulator + literals.raw[expressions.length];
70
63
  };
71
64
 
72
65
  /**
73
- * @param {TemplateStringsArray} literals Tagged template literals.
74
- * @param {...any} expressions Expressions to interpolate.
75
- * @yields Processed HTML strings.
76
- * @returns {Generator<string, void, void>} The HTML generator.
66
+ * @param {TemplateStringsArray} literals literals
67
+ * @param {...any} expressions expressions
68
+ * @yields {string} string
69
+ * @returns {Generator<string, void, void>} Generator<string, void, void>
77
70
  */
78
- export const htmlGenerator = function* ({ raw: literals }, ...expressions) {
71
+ export const htmlGenerator = function* (literals, ...expressions) {
79
72
  for (let i = 0; i !== expressions.length; ++i) {
80
73
  let expression = expressions[i];
81
- let literal = literals[i];
74
+ let literal = literals.raw[i];
82
75
  let string;
83
76
 
84
77
  if (typeof expression === "string") {
85
78
  string = expression;
86
- } else if (expression == null) {
79
+ } else if (expression === undefined || expression === null) {
87
80
  string = "";
88
81
  } else {
89
82
  if (expression[Symbol.iterator]) {
90
83
  const isRaw =
91
- literal !== "" && literal.charCodeAt(literal.length - 1) === 33;
84
+ Boolean(literal) && literal.charCodeAt(literal.length - 1) === 33;
92
85
 
93
86
  if (isRaw) {
94
87
  literal = literal.slice(0, -1);
@@ -102,27 +95,23 @@ export const htmlGenerator = function* ({ raw: literals }, ...expressions) {
102
95
  if (typeof expression === "string") {
103
96
  string = expression;
104
97
  } else {
105
- if (expression == null) {
98
+ if (expression === undefined || expression === null) {
106
99
  continue;
107
100
  }
108
101
 
109
102
  if (expression[Symbol.iterator]) {
110
103
  for (expression of expression) {
111
- if (typeof expression === "string") {
112
- string = expression;
113
- } else {
114
- if (expression == null) {
115
- continue;
116
- }
117
-
118
- string = `${expression}`;
104
+ if (expression === undefined || expression === null) {
105
+ continue;
119
106
  }
120
107
 
121
- if (!isRaw) {
122
- string = escapeFunction(string);
123
- }
108
+ string = String(expression);
124
109
 
125
110
  if (string) {
111
+ if (!isRaw) {
112
+ string = escapeFunction(string);
113
+ }
114
+
126
115
  yield string;
127
116
  }
128
117
  }
@@ -130,14 +119,14 @@ export const htmlGenerator = function* ({ raw: literals }, ...expressions) {
130
119
  continue;
131
120
  }
132
121
 
133
- string = `${expression}`;
134
- }
135
-
136
- if (!isRaw) {
137
- string = escapeFunction(string);
122
+ string = String(expression);
138
123
  }
139
124
 
140
125
  if (string) {
126
+ if (!isRaw) {
127
+ string = escapeFunction(string);
128
+ }
129
+
141
130
  yield string;
142
131
  }
143
132
  }
@@ -145,13 +134,13 @@ export const htmlGenerator = function* ({ raw: literals }, ...expressions) {
145
134
  continue;
146
135
  }
147
136
 
148
- string = `${expression}`;
137
+ string = String(expression);
149
138
  }
150
139
 
151
140
  if (literal && literal.charCodeAt(literal.length - 1) === 33) {
152
141
  literal = literal.slice(0, -1);
153
142
  } else {
154
- string = escapeFunction(string);
143
+ string &&= escapeFunction(string);
155
144
  }
156
145
 
157
146
  if (literal || string) {
@@ -159,34 +148,31 @@ export const htmlGenerator = function* ({ raw: literals }, ...expressions) {
159
148
  }
160
149
  }
161
150
 
162
- if (literals[expressions.length]) {
163
- yield literals[expressions.length];
151
+ if (literals.raw[expressions.length]) {
152
+ yield literals.raw[expressions.length];
164
153
  }
165
154
  };
166
155
 
167
156
  /**
168
- * @param {TemplateStringsArray} literals Tagged template literals.
169
- * @param {...any} expressions Expressions to interpolate.
170
- * @yields Processed HTML strings.
171
- * @returns {AsyncGenerator<string, void, void>} The HTML generator.
157
+ * @param {TemplateStringsArray} literals literals
158
+ * @param {...any} expressions expressions
159
+ * @yields {string} string
160
+ * @returns {AsyncGenerator<string, void, void>} AsyncGenerator<string, void, void>
172
161
  */
173
- export const htmlAsyncGenerator = async function* (
174
- { raw: literals },
175
- ...expressions
176
- ) {
162
+ export const htmlAsyncGenerator = async function* (literals, ...expressions) {
177
163
  for (let i = 0; i !== expressions.length; ++i) {
178
164
  let expression = await expressions[i];
179
- let literal = literals[i];
165
+ let literal = literals.raw[i];
180
166
  let string;
181
167
 
182
168
  if (typeof expression === "string") {
183
169
  string = expression;
184
- } else if (expression == null) {
170
+ } else if (expression === undefined || expression === null) {
185
171
  string = "";
186
172
  } else {
187
173
  if (expression[Symbol.iterator] || expression[Symbol.asyncIterator]) {
188
174
  const isRaw =
189
- literal !== "" && literal.charCodeAt(literal.length - 1) === 33;
175
+ Boolean(literal) && literal.charCodeAt(literal.length - 1) === 33;
190
176
 
191
177
  if (isRaw) {
192
178
  literal = literal.slice(0, -1);
@@ -200,7 +186,7 @@ export const htmlAsyncGenerator = async function* (
200
186
  if (typeof expression === "string") {
201
187
  string = expression;
202
188
  } else {
203
- if (expression == null) {
189
+ if (expression === undefined || expression === null) {
204
190
  continue;
205
191
  }
206
192
 
@@ -209,21 +195,17 @@ export const htmlAsyncGenerator = async function* (
209
195
  expression[Symbol.asyncIterator]
210
196
  ) {
211
197
  for await (expression of expression) {
212
- if (typeof expression === "string") {
213
- string = expression;
214
- } else {
215
- if (expression == null) {
216
- continue;
217
- }
218
-
219
- string = `${expression}`;
198
+ if (expression === undefined || expression === null) {
199
+ continue;
220
200
  }
221
201
 
222
- if (!isRaw) {
223
- string = escapeFunction(string);
224
- }
202
+ string = String(expression);
225
203
 
226
204
  if (string) {
205
+ if (!isRaw) {
206
+ string = escapeFunction(string);
207
+ }
208
+
227
209
  yield string;
228
210
  }
229
211
  }
@@ -231,14 +213,14 @@ export const htmlAsyncGenerator = async function* (
231
213
  continue;
232
214
  }
233
215
 
234
- string = `${expression}`;
235
- }
236
-
237
- if (!isRaw) {
238
- string = escapeFunction(string);
216
+ string = String(expression);
239
217
  }
240
218
 
241
219
  if (string) {
220
+ if (!isRaw) {
221
+ string = escapeFunction(string);
222
+ }
223
+
242
224
  yield string;
243
225
  }
244
226
  }
@@ -246,13 +228,13 @@ export const htmlAsyncGenerator = async function* (
246
228
  continue;
247
229
  }
248
230
 
249
- string = `${expression}`;
231
+ string = String(expression);
250
232
  }
251
233
 
252
234
  if (literal && literal.charCodeAt(literal.length - 1) === 33) {
253
235
  literal = literal.slice(0, -1);
254
236
  } else {
255
- string = escapeFunction(string);
237
+ string &&= escapeFunction(string);
256
238
  }
257
239
 
258
240
  if (literal || string) {
@@ -260,7 +242,7 @@ export const htmlAsyncGenerator = async function* (
260
242
  }
261
243
  }
262
244
 
263
- if (literals[expressions.length]) {
264
- yield literals[expressions.length];
245
+ if (literals.raw[expressions.length]) {
246
+ yield literals.raw[expressions.length];
265
247
  }
266
248
  };
@@ -3,8 +3,8 @@ import { readFileSync } from "node:fs";
3
3
  const cache = new Map();
4
4
 
5
5
  /**
6
- * @param {string} path The path to the file to render.
7
- * @returns {string} The content of the file.
6
+ * @param {string} path path
7
+ * @returns {string} string
8
8
  */
9
9
  export const includeFile = (path) => {
10
10
  let file = cache.get(path);
package/test/index.js CHANGED
@@ -22,6 +22,11 @@ const generatorExample = function* () {
22
22
  yield "</p>";
23
23
  };
24
24
 
25
+ const generatorExample2 = function* () {
26
+ yield ["", "<p>"];
27
+ yield "";
28
+ };
29
+
25
30
  const generatorPromiseExample = function* () {
26
31
  yield [
27
32
  new Promise((resolve) => {
@@ -33,6 +38,17 @@ const generatorPromiseExample = function* () {
33
38
  yield;
34
39
  };
35
40
 
41
+ const generatorPromiseExample2 = function* () {
42
+ yield [
43
+ new Promise((resolve) => {
44
+ resolve("<p>");
45
+ }),
46
+ null,
47
+ "",
48
+ ];
49
+ yield "";
50
+ };
51
+
36
52
  test("renders empty input", () => {
37
53
  assert.strictEqual(html({ raw: [""] }), "");
38
54
  });
@@ -204,6 +220,18 @@ test("htmlGenerator works with other generators (raw)", () => {
204
220
  assert.strictEqual(generator.next().done, true);
205
221
  });
206
222
 
223
+ test("htmlGenerator works with other generators (raw) /2", () => {
224
+ const generator = htmlGenerator`<div>!${generatorExample2()}</div>`;
225
+ let accumulator = "";
226
+
227
+ for (const value of generator) {
228
+ accumulator += value;
229
+ }
230
+
231
+ assert.strictEqual(accumulator, "<div><p></div>");
232
+ assert.strictEqual(generator.next().done, true);
233
+ });
234
+
207
235
  test("htmlGenerator works with other generators (escaped)", () => {
208
236
  const generator = htmlGenerator`<div>${generatorExample()}</div>`;
209
237
  let accumulator = "";
@@ -291,6 +319,17 @@ test("htmlAsyncGenerator works with other generators (raw)", async () => {
291
319
  );
292
320
  });
293
321
 
322
+ test("htmlAsyncGenerator works with other generators (raw) /2", async () => {
323
+ const generator = htmlAsyncGenerator`<div>!${generatorPromiseExample2()}</div>`;
324
+ let accumulator = "";
325
+
326
+ for await (const value of generator) {
327
+ accumulator += value;
328
+ }
329
+
330
+ assert.strictEqual(accumulator, "<div><p></div>");
331
+ });
332
+
294
333
  test("htmlAsyncGenerator works with other generators (escaped)", async () => {
295
334
  const generator = htmlAsyncGenerator`<div>${generatorExample()}</div>`;
296
335
  let accumulator = "";
package/.eslintrc.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": ["plugin:grules/all"],
4
- "rules": {
5
- "no-await-in-loop": "off",
6
- "require-unicode-regexp": "off"
7
- }
8
- }
@@ -1,6 +0,0 @@
1
- {
2
- "rules": {
3
- "require-await": "off",
4
- "n/no-missing-import": "off"
5
- }
6
- }