@podium/podlet 5.2.0-next.2 → 5.2.0-next.3
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 +57 -10
- package/lib/podlet.js +61 -8
- package/package.json +1 -1
- package/types/podlet.d.ts +25 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [5.2.0-next.3](https://github.com/podium-lib/podlet/compare/v5.2.0-next.2...v5.2.0-next.3) (2024-09-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add DSD shadow DOM encapsulation support ([02c9a64](https://github.com/podium-lib/podlet/commit/02c9a64a6bb2f460c035416e43405ae380cb6d1c))
|
|
7
|
+
|
|
1
8
|
# [5.2.0-next.2](https://github.com/podium-lib/podlet/compare/v5.2.0-next.1...v5.2.0-next.2) (2024-09-06)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -79,16 +79,17 @@ const podlet = new Podlet(options);
|
|
|
79
79
|
|
|
80
80
|
### options
|
|
81
81
|
|
|
82
|
-
| option
|
|
83
|
-
|
|
|
84
|
-
| name
|
|
85
|
-
| version
|
|
86
|
-
| pathname
|
|
87
|
-
| manifest
|
|
88
|
-
| content
|
|
89
|
-
| fallback
|
|
90
|
-
| logger
|
|
91
|
-
| development
|
|
82
|
+
| option | type | default | required |
|
|
83
|
+
| ------------ | --------- | ---------------- | -------- |
|
|
84
|
+
| name | `string` | | ✓ |
|
|
85
|
+
| version | `string` | | ✓ |
|
|
86
|
+
| pathname | `string` | | ✓ |
|
|
87
|
+
| manifest | `string` | `/manifest.json` | |
|
|
88
|
+
| content | `string` | `/` | |
|
|
89
|
+
| fallback | `string` | | |
|
|
90
|
+
| logger | `object` | | |
|
|
91
|
+
| development | `boolean` | `false` | |
|
|
92
|
+
| useShadowDOM | `boolean` | `false` | |
|
|
92
93
|
|
|
93
94
|
#### name
|
|
94
95
|
|
|
@@ -257,6 +258,52 @@ further details.
|
|
|
257
258
|
|
|
258
259
|
Turns development mode on or off. See the section about development mode.
|
|
259
260
|
|
|
261
|
+
#### useShadowDOM
|
|
262
|
+
|
|
263
|
+
Turns declarative shadow DOM encapsulation on for the podlet. When enabled, the podlet content will be wrapped inside a declarative shadow DOM wrapper to isolate it from the rest of whichever
|
|
264
|
+
page it is being included on.
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
const podlet = new Podlet({ ..., useShadowDOM: true });
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Please note the following caveats when using this feature:
|
|
271
|
+
1. You must name your podlet following custom element naming conventions as explained here: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names
|
|
272
|
+
2. In order to style your content, you will need to include your CSS inside the shadow DOM wrapper. You can do this using one of the following 2 options:
|
|
273
|
+
|
|
274
|
+
You can include a `<style>` tag before your content
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
res.podiumSend(`
|
|
278
|
+
<style>
|
|
279
|
+
...styles here...
|
|
280
|
+
</style>
|
|
281
|
+
<div>...content here...</div>
|
|
282
|
+
`);
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
You can have your podlet CSS included for you by using the "shadow-dom" scope
|
|
286
|
+
|
|
287
|
+
```js
|
|
288
|
+
podlet.css({ value: '/path/to/css', scope: 'shadow-dom' });
|
|
289
|
+
res.podiumSend(`
|
|
290
|
+
<div>...content here...</div>
|
|
291
|
+
`);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
For more fine grained control, you can use the `podlet.wrapWithShadowDOM` method directly
|
|
295
|
+
|
|
296
|
+
```js
|
|
297
|
+
const podlet = new Podlet({ ..., useShadowDOM: false });
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
const wrapped = podlet.wrapWithShadowDOM(`<div>...content here...</div>`);
|
|
302
|
+
res.podiumSend(`
|
|
303
|
+
${wrapped}
|
|
304
|
+
`);
|
|
305
|
+
```
|
|
306
|
+
|
|
260
307
|
## Podlet Instance
|
|
261
308
|
|
|
262
309
|
The podlet instance has the following API:
|
package/lib/podlet.js
CHANGED
|
@@ -15,6 +15,10 @@ import { join, dirname } from 'node:path';
|
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
// @ts-ignore
|
|
17
17
|
import fs from 'node:fs';
|
|
18
|
+
import assert from 'node:assert';
|
|
19
|
+
|
|
20
|
+
const customElementRegex =
|
|
21
|
+
/^(?!(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.-]*$/;
|
|
18
22
|
|
|
19
23
|
const currentDirectory = dirname(fileURLToPath(import.meta.url));
|
|
20
24
|
const pkgJson = fs.readFileSync(
|
|
@@ -30,16 +34,17 @@ const { template } = utils;
|
|
|
30
34
|
* @property {string} name - (required) podlet name
|
|
31
35
|
* @property {string} version - (required) podlet version
|
|
32
36
|
* @property {string} pathname - (required) podlet pathname
|
|
33
|
-
* @property {string} [manifest] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
34
|
-
* @property {string} [content] - path where the podlet content HTML markup is served from (default '/')
|
|
35
|
-
* @property {string} [fallback] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
36
|
-
* @property {boolean} [development] - a boolean flag that, when true, enables additional development setup (default false)
|
|
37
|
+
* @property {string} [manifest='/manifest.json'] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
38
|
+
* @property {string} [content='/'] - path where the podlet content HTML markup is served from (default '/')
|
|
39
|
+
* @property {string} [fallback=''] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
40
|
+
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup (default false)
|
|
41
|
+
* @property {boolean} [useShadowDOM=false] - a boolean flag that, when true, enables the use of ShadowDOM (default false)
|
|
37
42
|
* @property {import('abslog').AbstractLoggerOptions} [logger] - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
|
|
38
43
|
* @property {import("@podium/proxy").PodiumProxyOptions} [proxy] - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details.
|
|
39
44
|
*
|
|
40
45
|
* @typedef {{ debug: 'true' | 'false', locale: string, deviceType: string, requestedBy: string, mountOrigin: string, mountPathname: string, publicPathname: string }} PodletContext
|
|
41
|
-
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetCssLike
|
|
42
|
-
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetJsLike
|
|
46
|
+
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetCssLike
|
|
47
|
+
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetJsLike
|
|
43
48
|
*/
|
|
44
49
|
|
|
45
50
|
export default class PodiumPodlet {
|
|
@@ -283,6 +288,11 @@ export default class PodiumPodlet {
|
|
|
283
288
|
*/
|
|
284
289
|
metrics = new Metrics();
|
|
285
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet.
|
|
293
|
+
*/
|
|
294
|
+
#useShadowDOM = false;
|
|
295
|
+
|
|
286
296
|
/**
|
|
287
297
|
* Creates a new instance of a Podium podlet which can be used in conjunction with your framework of choice to build podlet server apps.
|
|
288
298
|
* `name`, `version` and `pathname` constructor arguments are required. All other options are optional.
|
|
@@ -294,6 +304,7 @@ export default class PodiumPodlet {
|
|
|
294
304
|
* * `content` - path where the podlet content HTML markup is served from (**default** `'/'`)
|
|
295
305
|
* * `fallback` - path where the podlet fallback HTML markup is served from (**default** `'/fallback'`)
|
|
296
306
|
* * `development` - a boolean flag that, when true, enables additional development setup (**default** `false`)
|
|
307
|
+
* * `useShadowDOM` - a boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet (**default** `false`)
|
|
297
308
|
* * `logger` - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (**default** `null`)
|
|
298
309
|
* * `proxy` - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details. (**default**: `{}`)
|
|
299
310
|
*
|
|
@@ -317,6 +328,7 @@ export default class PodiumPodlet {
|
|
|
317
328
|
logger = undefined,
|
|
318
329
|
development = false,
|
|
319
330
|
proxy = {},
|
|
331
|
+
useShadowDOM = false,
|
|
320
332
|
}) {
|
|
321
333
|
if (schema.name(name).error)
|
|
322
334
|
throw new Error(
|
|
@@ -374,6 +386,7 @@ export default class PodiumPodlet {
|
|
|
374
386
|
this.name,
|
|
375
387
|
),
|
|
376
388
|
};
|
|
389
|
+
this.#useShadowDOM = useShadowDOM;
|
|
377
390
|
|
|
378
391
|
// Skip a tick to ensure the metric stream has been consumed
|
|
379
392
|
setImmediate(() => {
|
|
@@ -811,10 +824,50 @@ export default class PodiumPodlet {
|
|
|
811
824
|
* @returns {string}
|
|
812
825
|
*/
|
|
813
826
|
render(incoming, data, ...args) {
|
|
827
|
+
const markup = this.#useShadowDOM ? this.wrapWithShadowDOM(data) : data;
|
|
814
828
|
if (!incoming.development) {
|
|
815
|
-
return
|
|
829
|
+
return markup;
|
|
816
830
|
}
|
|
817
|
-
return this.#view(incoming,
|
|
831
|
+
return this.#view(incoming, markup, ...args);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Function that takes in the podlet content,wraps it in declarative shadow DOM and returns it.
|
|
836
|
+
* @param {string} data - the podlet content to wrap in declarative shadow DOM as an HTML markup string
|
|
837
|
+
*
|
|
838
|
+
* @example
|
|
839
|
+
* ```js
|
|
840
|
+
* const content = podlet.wrapWithShadowDOM('<div>content to render</div>');
|
|
841
|
+
* ```
|
|
842
|
+
*/
|
|
843
|
+
wrapWithShadowDOM(data) {
|
|
844
|
+
assert.ok(
|
|
845
|
+
customElementRegex.test(this.name),
|
|
846
|
+
'When using the constructor argument "useShadowDOM", podlet.name must conform to custom element naming conventions: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names',
|
|
847
|
+
);
|
|
848
|
+
|
|
849
|
+
const styles = this.cssRoute
|
|
850
|
+
.filter((css) => css.scope === 'shadow-dom')
|
|
851
|
+
.map((css) => css.toHTML());
|
|
852
|
+
|
|
853
|
+
const scripts = this.jsRoute
|
|
854
|
+
.filter((js) => js.scope === 'shadow-dom')
|
|
855
|
+
.map((js) => js.toHTML());
|
|
856
|
+
|
|
857
|
+
// Wrap the markup in DSD.
|
|
858
|
+
return `
|
|
859
|
+
<${this.name}>
|
|
860
|
+
<template shadowrootmode="open">
|
|
861
|
+
${styles.join('\n')}
|
|
862
|
+
${data}
|
|
863
|
+
${scripts.join('\n')}
|
|
864
|
+
</template>
|
|
865
|
+
</${this.name}>
|
|
866
|
+
<script>(()=>{function e(d){HTMLTemplateElement.prototype.hasOwnProperty("shadowRootMode")||d.querySelectorAll("template[shadowrootmode]").forEach(o=>{let
|
|
867
|
+
n=o.getAttribute("shadowrootmode"),s=o.hasAttribute("shadowrootdelegatesfocus"),t=o.parentNode.attachShadow({mode:n,delegatesFocus:s});t.appendChild(o.content),o.remove(),e(t)})}var
|
|
868
|
+
r;(r=document.currentScript)!=null&&r.previousElementSibling&&e(document.currentScript.previousElementSibling);})();
|
|
869
|
+
</script>
|
|
870
|
+
`;
|
|
818
871
|
}
|
|
819
872
|
|
|
820
873
|
/**
|
package/package.json
CHANGED
package/types/podlet.d.ts
CHANGED
|
@@ -30,16 +30,17 @@ declare global {
|
|
|
30
30
|
* @property {string} name - (required) podlet name
|
|
31
31
|
* @property {string} version - (required) podlet version
|
|
32
32
|
* @property {string} pathname - (required) podlet pathname
|
|
33
|
-
* @property {string} [manifest] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
34
|
-
* @property {string} [content] - path where the podlet content HTML markup is served from (default '/')
|
|
35
|
-
* @property {string} [fallback] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
36
|
-
* @property {boolean} [development] - a boolean flag that, when true, enables additional development setup (default false)
|
|
33
|
+
* @property {string} [manifest='/manifest.json'] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
34
|
+
* @property {string} [content='/'] - path where the podlet content HTML markup is served from (default '/')
|
|
35
|
+
* @property {string} [fallback=''] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
36
|
+
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup (default false)
|
|
37
|
+
* @property {boolean} [useShadowDOM=false] - a boolean flag that, when true, enables the use of ShadowDOM (default false)
|
|
37
38
|
* @property {import('abslog').AbstractLoggerOptions} [logger] - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
|
|
38
39
|
* @property {import("@podium/proxy").PodiumProxyOptions} [proxy] - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details.
|
|
39
40
|
*
|
|
40
41
|
* @typedef {{ debug: 'true' | 'false', locale: string, deviceType: string, requestedBy: string, mountOrigin: string, mountPathname: string, publicPathname: string }} PodletContext
|
|
41
|
-
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetCssLike
|
|
42
|
-
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetJsLike
|
|
42
|
+
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetCssLike
|
|
43
|
+
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetJsLike
|
|
43
44
|
*/
|
|
44
45
|
export default class PodiumPodlet {
|
|
45
46
|
/**
|
|
@@ -53,6 +54,7 @@ export default class PodiumPodlet {
|
|
|
53
54
|
* * `content` - path where the podlet content HTML markup is served from (**default** `'/'`)
|
|
54
55
|
* * `fallback` - path where the podlet fallback HTML markup is served from (**default** `'/fallback'`)
|
|
55
56
|
* * `development` - a boolean flag that, when true, enables additional development setup (**default** `false`)
|
|
57
|
+
* * `useShadowDOM` - a boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet (**default** `false`)
|
|
56
58
|
* * `logger` - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (**default** `null`)
|
|
57
59
|
* * `proxy` - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details. (**default**: `{}`)
|
|
58
60
|
*
|
|
@@ -66,7 +68,7 @@ export default class PodiumPodlet {
|
|
|
66
68
|
* const podlet = new Podlet({ name: 'foo', version: '1.0.0', pathname: '/' });
|
|
67
69
|
* ```
|
|
68
70
|
*/
|
|
69
|
-
constructor({ name, version, pathname, manifest, fallback, content, logger, development, proxy, }: PodletOptions);
|
|
71
|
+
constructor({ name, version, pathname, manifest, fallback, content, logger, development, proxy, useShadowDOM, }: PodletOptions);
|
|
70
72
|
/**
|
|
71
73
|
* The name that the podlet identifies itself by. (set in the constructor) This is used internally for things like metrics but can also be used by a layout server.
|
|
72
74
|
* This value must be in camelCase.
|
|
@@ -545,6 +547,16 @@ export default class PodiumPodlet {
|
|
|
545
547
|
render<T extends {
|
|
546
548
|
[key: string]: unknown;
|
|
547
549
|
}>(incoming: HttpIncoming<T>, data: string, ...args: any[]): string;
|
|
550
|
+
/**
|
|
551
|
+
* Function that takes in the podlet content,wraps it in declarative shadow DOM and returns it.
|
|
552
|
+
* @param {string} data - the podlet content to wrap in declarative shadow DOM as an HTML markup string
|
|
553
|
+
*
|
|
554
|
+
* @example
|
|
555
|
+
* ```js
|
|
556
|
+
* const content = podlet.wrapWithShadowDOM('<div>content to render</div>');
|
|
557
|
+
* ```
|
|
558
|
+
*/
|
|
559
|
+
wrapWithShadowDOM(data: string): string;
|
|
548
560
|
/**
|
|
549
561
|
* Method for processing an incoming HTTP request. This method is intended to be used to implement support for multiple HTTP frameworks and in most cases will not need to be used directly by podlet developers when creating podlet servers.
|
|
550
562
|
*
|
|
@@ -611,6 +623,10 @@ export type PodletOptions = {
|
|
|
611
623
|
* - a boolean flag that, when true, enables additional development setup (default false)
|
|
612
624
|
*/
|
|
613
625
|
development?: boolean;
|
|
626
|
+
/**
|
|
627
|
+
* - a boolean flag that, when true, enables the use of ShadowDOM (default false)
|
|
628
|
+
*/
|
|
629
|
+
useShadowDOM?: boolean;
|
|
614
630
|
/**
|
|
615
631
|
* - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
|
|
616
632
|
*/
|
|
@@ -640,7 +656,7 @@ export type AssetCssLike = {
|
|
|
640
656
|
type?: string | false | null;
|
|
641
657
|
value: string | false | null;
|
|
642
658
|
strategy?: "beforeInteractive" | "afterInteractive" | "lazy";
|
|
643
|
-
scope?: "content" | "fallback" | "all";
|
|
659
|
+
scope?: "content" | "fallback" | "all" | "shadow-dom";
|
|
644
660
|
[key: string]: any;
|
|
645
661
|
};
|
|
646
662
|
export type AssetJsLike = {
|
|
@@ -659,7 +675,7 @@ export type AssetJsLike = {
|
|
|
659
675
|
value: string;
|
|
660
676
|
}>;
|
|
661
677
|
strategy?: "beforeInteractive" | "afterInteractive" | "lazy";
|
|
662
|
-
scope?: "content" | "fallback" | "all";
|
|
678
|
+
scope?: "content" | "fallback" | "all" | "shadow-dom";
|
|
663
679
|
[key: string]: any;
|
|
664
680
|
};
|
|
665
681
|
import Proxy from '@podium/proxy';
|