@podium/podlet 5.2.4 → 5.3.0
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/CHANGELOG.md +7 -0
- package/README.md +50 -11
- package/lib/podlet.js +27 -3
- package/package.json +9 -9
- package/types/podlet.d.ts +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [5.3.0](https://github.com/podium-lib/podlet/compare/v5.2.4...v5.3.0) (2025-06-24)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add support for html tagged template literal ([#460](https://github.com/podium-lib/podlet/issues/460)) ([356244a](https://github.com/podium-lib/podlet/commit/356244a6d345f688037298830b05824487a12399))
|
|
7
|
+
|
|
1
8
|
## [5.2.4](https://github.com/podium-lib/podlet/compare/v5.2.3...v5.2.4) (2024-11-25)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -4,9 +4,7 @@ A Module for building page fragment servers in a micro frontend architecture.
|
|
|
4
4
|
|
|
5
5
|
See the [official Podium documentation](https://podium-lib.io/) site.
|
|
6
6
|
|
|
7
|
-
[](https://david-dm.org/podium-lib/podlet)
|
|
8
7
|
[](https://github.com/podium-lib/podlet/actions?query=workflow%3A%22Run+Lint+and+Tests%22)
|
|
9
|
-
[](https://snyk.io/test/github/podium-lib/podlet?targetFile=package.json)
|
|
10
8
|
|
|
11
9
|
This is a module for building a podlet server. A podlet server is responsible for
|
|
12
10
|
generating HTML fragments which can then be used in a [@podium/layout] server to compose a
|
|
@@ -22,8 +20,6 @@ convenience.
|
|
|
22
20
|
For writing podlet servers with other HTTP frameworks, the following modules also exist:
|
|
23
21
|
|
|
24
22
|
- [Fastify Podlet Plugin]
|
|
25
|
-
- [Hapi Podlet Plugin]
|
|
26
|
-
- [Koa Podlet Plugin]
|
|
27
23
|
|
|
28
24
|
## Installation
|
|
29
25
|
|
|
@@ -37,7 +33,7 @@ Building a simple podlet server using [Express].
|
|
|
37
33
|
|
|
38
34
|
```js
|
|
39
35
|
import express from 'express';
|
|
40
|
-
import Podlet from '@podium/podlet';
|
|
36
|
+
import Podlet, { html } from '@podium/podlet';
|
|
41
37
|
|
|
42
38
|
// create a new podlet instance
|
|
43
39
|
const podlet = new Podlet({
|
|
@@ -60,7 +56,7 @@ app.get(podlet.manifest(), (req, res) => {
|
|
|
60
56
|
|
|
61
57
|
// create a route to serve the podlet's content
|
|
62
58
|
app.get(podlet.content(), (req, res) => {
|
|
63
|
-
res.podiumSend(`<div>hello world</div>`);
|
|
59
|
+
res.podiumSend(html`<div>hello world</div>`);
|
|
64
60
|
});
|
|
65
61
|
|
|
66
62
|
// start the app on port 7100
|
|
@@ -277,7 +273,7 @@ Please note the following caveats when using this feature:
|
|
|
277
273
|
You can include a `<style>` tag before your content
|
|
278
274
|
|
|
279
275
|
```js
|
|
280
|
-
res.podiumSend(`
|
|
276
|
+
res.podiumSend(html`
|
|
281
277
|
<style>
|
|
282
278
|
...styles here...
|
|
283
279
|
</style>
|
|
@@ -289,7 +285,7 @@ You can have your podlet CSS included for you by using the "shadow-dom" scope
|
|
|
289
285
|
|
|
290
286
|
```js
|
|
291
287
|
podlet.css({ value: '/path/to/css', scope: 'shadow-dom' });
|
|
292
|
-
res.podiumSend(`
|
|
288
|
+
res.podiumSend(html`
|
|
293
289
|
<div>...content here...</div>
|
|
294
290
|
`);
|
|
295
291
|
```
|
|
@@ -872,7 +868,7 @@ app.post(podlet.proxy({ target: '/api', name: 'api' }), (req, res) => { ... });
|
|
|
872
868
|
// content route serving an HTML form
|
|
873
869
|
app.get(podlet.content(), (req, res) => {
|
|
874
870
|
const ctx = res.locals.podium.context;
|
|
875
|
-
res.podiumSend(`
|
|
871
|
+
res.podiumSend(html`
|
|
876
872
|
<form action="${ctx.mountOrigin}${ctx.publicPathname}/api" method="post">
|
|
877
873
|
[ ... ]
|
|
878
874
|
</form>
|
|
@@ -895,7 +891,7 @@ _Example of sending an HTML fragment:_
|
|
|
895
891
|
|
|
896
892
|
```js
|
|
897
893
|
app.get(podlet.content(), (req, res) => {
|
|
898
|
-
res.podiumSend(
|
|
894
|
+
res.podiumSend(html`<h1>Hello World</h1>`);
|
|
899
895
|
});
|
|
900
896
|
```
|
|
901
897
|
|
|
@@ -975,6 +971,49 @@ podlet.view(data => `<!doctype html>
|
|
|
975
971
|
);
|
|
976
972
|
```
|
|
977
973
|
|
|
974
|
+
## html
|
|
975
|
+
|
|
976
|
+
Tagged template literal that automatically escapes the different inputs to prevent XSS.
|
|
977
|
+
|
|
978
|
+
There are two exceptions that do not get escaped:
|
|
979
|
+
|
|
980
|
+
- [The result of a podlet `fetch`](https://github.com/podium-lib/client#fetchincoming-options) (relevant for layouts).
|
|
981
|
+
- [Strings wrapped in `DangerouslyIncludeUnescapedHTML`](#dangerouslyincludeunescapedhtml).
|
|
982
|
+
|
|
983
|
+
Use with [podiumSend](#respodiumsendfragment).
|
|
984
|
+
|
|
985
|
+
```js
|
|
986
|
+
import { html } from "@podium/podlet";
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
## escape
|
|
990
|
+
|
|
991
|
+
The same escape function used by [`html`](#html) in case you want to escape something manually, for example in APIs.
|
|
992
|
+
|
|
993
|
+
```js
|
|
994
|
+
import { escape } from "@podium/podlet";
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
## DangerouslyIncludeUnescapedHTML
|
|
998
|
+
|
|
999
|
+
Lets you opt a string you trust out of being escaped.
|
|
1000
|
+
|
|
1001
|
+
```js
|
|
1002
|
+
import { html, DangerouslyIncludeUnescapedHTML } from "@podium/podlet";
|
|
1003
|
+
|
|
1004
|
+
const greeting = new DangerouslyIncludeUnescapedHTML({ __content: "<em>Howdy</em>" });
|
|
1005
|
+
const result = html`<p>${greeting} partner!</p>`
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
## TemplateResult
|
|
1009
|
+
|
|
1010
|
+
This is the class type returned by the [`html`](#html) tagged template literal.
|
|
1011
|
+
You can use it for typing, or for advanced cases if `html` does not work for you.
|
|
1012
|
+
|
|
1013
|
+
```js
|
|
1014
|
+
import { TemplateResult } from "@podium/podlet";
|
|
1015
|
+
```
|
|
1016
|
+
|
|
978
1017
|
## Development mode
|
|
979
1018
|
|
|
980
1019
|
In most cases podlets are fragments of a whole HTML document. When a layout
|
|
@@ -1046,10 +1085,10 @@ SOFTWARE.
|
|
|
1046
1085
|
[@podium/layout]: https://github.com/podium-lib/layout '@podium/layout'
|
|
1047
1086
|
[@podium/proxy]: https://github.com/podium-lib/proxy '@podium/proxy'
|
|
1048
1087
|
[express]: https://expressjs.com/ 'Express'
|
|
1049
|
-
[hapi podlet plugin]: https://github.com/podium-lib/hapi-podlet 'Hapi Podlet Plugin'
|
|
1050
1088
|
[httpincoming]: https://github.com/podium-lib/utils/blob/main/lib/http-incoming.js 'HttpIncoming'
|
|
1051
1089
|
[publicpathname]: https://github.com/podium-lib/context#public-pathname '`publicPathname`'
|
|
1052
1090
|
[mountorigin]: https://github.com/podium-lib/context#mount-origin '`mountOrigin`'
|
|
1053
1091
|
[abslog]: https://github.com/trygve-lie/abslog 'abslog'
|
|
1054
1092
|
[pathname]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname 'pathname'
|
|
1055
1093
|
[url]: https://developer.mozilla.org/en-US/docs/Web/API/URL 'URL'
|
|
1094
|
+
[Fastify Podlet Plugin]: https://github.com/podium-lib/fastify-podlet 'Fastify Podlet Plugin'
|
package/lib/podlet.js
CHANGED
|
@@ -3,6 +3,10 @@ import {
|
|
|
3
3
|
pathnameBuilder,
|
|
4
4
|
AssetCss,
|
|
5
5
|
AssetJs,
|
|
6
|
+
html,
|
|
7
|
+
escape,
|
|
8
|
+
DangerouslyIncludeUnescapedHTML,
|
|
9
|
+
TemplateResult,
|
|
6
10
|
} from '@podium/utils';
|
|
7
11
|
import * as schema from '@podium/schemas';
|
|
8
12
|
import Metrics from '@metrics/client';
|
|
@@ -17,6 +21,8 @@ import { fileURLToPath } from 'node:url';
|
|
|
17
21
|
import fs from 'node:fs';
|
|
18
22
|
import assert from 'node:assert';
|
|
19
23
|
|
|
24
|
+
export { html, escape, DangerouslyIncludeUnescapedHTML, TemplateResult };
|
|
25
|
+
|
|
20
26
|
const customElementRegex =
|
|
21
27
|
/^(?!(annotation-xml|color-profile|font-face|font-face-src|font-face-uri|font-face-format|font-face-name|missing-glyph)$)[a-z][a-z0-9.-]*-[a-z0-9.-]*$/;
|
|
22
28
|
|
|
@@ -831,16 +837,34 @@ export default class PodiumPodlet {
|
|
|
831
837
|
*
|
|
832
838
|
* @template {{ [key: string]: unknown }} T
|
|
833
839
|
* @param {HttpIncoming<T>} incoming - Instance of Podium HttpIncoming object
|
|
834
|
-
* @param {string} data - the podlet content as an HTML markup string
|
|
840
|
+
* @param {string | TemplateResult} data - the podlet content as an HTML markup string
|
|
835
841
|
* @param {...any} args - additional args depending on the template and what values it accepts
|
|
836
842
|
* @returns {string}
|
|
837
843
|
*/
|
|
838
844
|
render(incoming, data, ...args) {
|
|
839
|
-
|
|
845
|
+
let dataString;
|
|
846
|
+
const tag = Object.prototype.toString.call(data);
|
|
847
|
+
if (tag === '[object TemplateResult]') {
|
|
848
|
+
dataString = /** @type {TemplateResult} */ (data).content;
|
|
849
|
+
} else {
|
|
850
|
+
dataString = /** @type {string} */ (data);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
const markup = this.#useShadowDOM
|
|
854
|
+
? this.wrapWithShadowDOM(dataString)
|
|
855
|
+
: dataString;
|
|
840
856
|
if (!incoming.development) {
|
|
841
857
|
return markup;
|
|
842
858
|
}
|
|
843
|
-
|
|
859
|
+
|
|
860
|
+
const newArgs = args.map((arg) => {
|
|
861
|
+
const tag = Object.prototype.toString.call(arg);
|
|
862
|
+
if (tag === '[object TemplateResult]') {
|
|
863
|
+
return /** @type {TemplateResult} */ (arg).content;
|
|
864
|
+
}
|
|
865
|
+
return arg;
|
|
866
|
+
});
|
|
867
|
+
return this.#view(incoming, markup, ...newArgs);
|
|
844
868
|
}
|
|
845
869
|
|
|
846
870
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@podium/podlet",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Module for building page fragment servers in a micro frontend architecture.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,24 +35,24 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@metrics/client": "2.5.4",
|
|
37
37
|
"@podium/schemas": "5.1.0",
|
|
38
|
-
"@podium/proxy": "5.0.
|
|
39
|
-
"@podium/utils": "5.
|
|
38
|
+
"@podium/proxy": "5.0.33",
|
|
39
|
+
"@podium/utils": "5.5.0",
|
|
40
40
|
"abslog": "2.4.4",
|
|
41
41
|
"ajv": "8.17.1",
|
|
42
42
|
"objobj": "1.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@podium/eslint-config": "1.0.
|
|
45
|
+
"@podium/eslint-config": "1.0.11",
|
|
46
46
|
"@podium/semantic-release-config": "2.0.0",
|
|
47
|
-
"@podium/test-utils": "3.0.
|
|
47
|
+
"@podium/test-utils": "3.0.17",
|
|
48
48
|
"@podium/typescript-config": "1.0.0",
|
|
49
|
-
"@types/node": "20.
|
|
50
|
-
"@types/readable-stream": "4.0.
|
|
51
|
-
"eslint": "9.
|
|
49
|
+
"@types/node": "20.17.57",
|
|
50
|
+
"@types/readable-stream": "4.0.20",
|
|
51
|
+
"eslint": "9.25.1",
|
|
52
52
|
"express": "4.20.0",
|
|
53
53
|
"json-stringify-safe": "5.0.1",
|
|
54
54
|
"npm-run-all2": "6.2.6",
|
|
55
|
-
"prettier": "3.
|
|
55
|
+
"prettier": "3.5.3",
|
|
56
56
|
"semantic-release": "24.1.2",
|
|
57
57
|
"tap": "18.8.0",
|
|
58
58
|
"typescript": "5.5.4",
|
package/types/podlet.d.ts
CHANGED
|
@@ -586,13 +586,13 @@ export default class PodiumPodlet {
|
|
|
586
586
|
*
|
|
587
587
|
* @template {{ [key: string]: unknown }} T
|
|
588
588
|
* @param {HttpIncoming<T>} incoming - Instance of Podium HttpIncoming object
|
|
589
|
-
* @param {string} data - the podlet content as an HTML markup string
|
|
589
|
+
* @param {string | TemplateResult} data - the podlet content as an HTML markup string
|
|
590
590
|
* @param {...any} args - additional args depending on the template and what values it accepts
|
|
591
591
|
* @returns {string}
|
|
592
592
|
*/
|
|
593
593
|
render<T extends {
|
|
594
594
|
[key: string]: unknown;
|
|
595
|
-
}>(incoming: HttpIncoming<T>, data: string, ...args: any[]): string;
|
|
595
|
+
}>(incoming: HttpIncoming<T>, data: string | TemplateResult, ...args: any[]): string;
|
|
596
596
|
/**
|
|
597
597
|
* Function that takes in the podlet content,wraps it in declarative shadow DOM and returns it.
|
|
598
598
|
* @param {string} data - the podlet content to wrap in declarative shadow DOM as an HTML markup string
|
|
@@ -724,8 +724,13 @@ export type AssetJsLike = {
|
|
|
724
724
|
scope?: "content" | "fallback" | "all" | "shadow-dom";
|
|
725
725
|
[key: string]: any;
|
|
726
726
|
};
|
|
727
|
+
import { html } from '@podium/utils';
|
|
728
|
+
import { escape } from '@podium/utils';
|
|
729
|
+
import { DangerouslyIncludeUnescapedHTML } from '@podium/utils';
|
|
730
|
+
import { TemplateResult } from '@podium/utils';
|
|
727
731
|
import Proxy from '@podium/proxy';
|
|
728
732
|
import { AssetCss } from '@podium/utils';
|
|
729
733
|
import { AssetJs } from '@podium/utils';
|
|
730
734
|
import Metrics from '@metrics/client';
|
|
731
735
|
import { HttpIncoming } from '@podium/utils';
|
|
736
|
+
export { html, escape, DangerouslyIncludeUnescapedHTML, TemplateResult };
|