ghtml 2.0.0 → 2.0.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/README.md +5 -5
- package/package.json +2 -2
- package/src/html.js +16 -8
package/README.md
CHANGED
|
@@ -20,11 +20,11 @@ The `htmlGenerator` function acts as the generator version of the `html` functio
|
|
|
20
20
|
|
|
21
21
|
**Note:**
|
|
22
22
|
|
|
23
|
-
Keep in mind that, in Node.js, all else being equal, streaming a response using synchronous generators
|
|
23
|
+
Keep in mind that, in Node.js, all else being equal, streaming a response using synchronous generators is **always** slower than processing everything directly and sending it at once — [this also applies to TTFB](https://github.com/mcollina/fastify-html/issues/11#issuecomment-2069385895). However, if a template includes promises that do asynchronous operations (I/O, etc.), then `htmlAsyncGenerator` can be used to stream the response as those promises get resolved, which does indeed improve TTFB.
|
|
24
24
|
|
|
25
25
|
### `htmlAsyncGenerator`
|
|
26
26
|
|
|
27
|
-
This version of HTML generator should be preferred for asynchronous and streaming use cases. The output
|
|
27
|
+
This version of HTML generator should be preferred for asynchronous and streaming use cases. The output is generated as the promise expressions resolve or stream expressions send data.
|
|
28
28
|
|
|
29
29
|
**Minor Note:**
|
|
30
30
|
|
|
@@ -42,7 +42,7 @@ Available in Node.js, the `includeFile` function is a wrapper around `readFileSy
|
|
|
42
42
|
import { html } from "ghtml";
|
|
43
43
|
|
|
44
44
|
const username = '<img src="https://example.com/pwned.png">';
|
|
45
|
-
const greeting = html`<h1>Hello, ${username}
|
|
45
|
+
const greeting = html`<h1>Hello, ${username}</h1>`;
|
|
46
46
|
|
|
47
47
|
console.log(greeting);
|
|
48
48
|
// Output: <h1>Hello, <img src="https://example.com/pwned.png"></h1>
|
|
@@ -58,7 +58,7 @@ console.log(container);
|
|
|
58
58
|
// Output: <div><img src="https://example.com/safe.png"></div>
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
When nesting multiple `html` expressions,
|
|
61
|
+
When nesting multiple `html` expressions, make sure to use `!` as the inner calls do their own escaping:
|
|
62
62
|
|
|
63
63
|
```js
|
|
64
64
|
const someCondition = Math.random() >= 0.5;
|
|
@@ -171,4 +171,4 @@ console.log(logo);
|
|
|
171
171
|
|
|
172
172
|
## Security
|
|
173
173
|
|
|
174
|
-
Like [similar](https://handlebarsjs.com/guide/#html-escaping) [tools](https://github.com/mde/ejs/blob/main/SECURITY.md#out-of-scope-vulnerabilities), `ghtml`
|
|
174
|
+
Like [similar](https://handlebarsjs.com/guide/#html-escaping) [tools](https://github.com/mde/ejs/blob/main/SECURITY.md#out-of-scope-vulnerabilities), `ghtml` does not prevent all kinds of XSS attacks. It is the responsibility of consumers to sanitize user inputs. Some inherently insecure uses include dynamically generating JavaScript, failing to quote HTML attribute values (especially when they contain expressions), and using unsanitized user-provided URLs.
|
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": "2.0.
|
|
6
|
+
"version": "2.0.1",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.js",
|
|
9
9
|
"exports": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@fastify/pre-commit": "^2.1.0",
|
|
24
|
-
"c8": "^
|
|
24
|
+
"c8": "^10.0.0",
|
|
25
25
|
"grules": "^0.17.2",
|
|
26
26
|
"tinybench": "^2.8.0"
|
|
27
27
|
},
|
package/src/html.js
CHANGED
|
@@ -107,11 +107,15 @@ const htmlGenerator = function* ({ raw: literals }, ...expressions) {
|
|
|
107
107
|
|
|
108
108
|
if (expression[Symbol.iterator]) {
|
|
109
109
|
for (expression of expression) {
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
}
|
|
110
|
+
if (typeof expression === "string") {
|
|
111
|
+
string = expression;
|
|
112
|
+
} else {
|
|
113
|
+
if (expression === undefined || expression === null) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
113
116
|
|
|
114
|
-
|
|
117
|
+
string = `${expression}`;
|
|
118
|
+
}
|
|
115
119
|
|
|
116
120
|
if (string) {
|
|
117
121
|
if (!isRaw && escapeRegExp.test(string)) {
|
|
@@ -203,11 +207,15 @@ const htmlAsyncGenerator = async function* ({ raw: literals }, ...expressions) {
|
|
|
203
207
|
expression[Symbol.asyncIterator]
|
|
204
208
|
) {
|
|
205
209
|
for await (expression of expression) {
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
}
|
|
210
|
+
if (typeof expression === "string") {
|
|
211
|
+
string = expression;
|
|
212
|
+
} else {
|
|
213
|
+
if (expression === undefined || expression === null) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
209
216
|
|
|
210
|
-
|
|
217
|
+
string = `${expression}`;
|
|
218
|
+
}
|
|
211
219
|
|
|
212
220
|
if (string) {
|
|
213
221
|
if (!isRaw && escapeRegExp.test(string)) {
|