@joist/ssr 4.0.1-next.0 → 4.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/package.json CHANGED
@@ -1,16 +1,13 @@
1
1
  {
2
2
  "name": "@joist/ssr",
3
- "version": "4.0.1-next.0",
3
+ "version": "4.0.1",
4
4
  "type": "module",
5
5
  "main": "./target/lib.js",
6
6
  "module": "./target/lib.js",
7
7
  "exports": {
8
- ".": {
9
- "import": "./target/lib.js"
10
- },
11
- "./*": {
12
- "import": "./target/lib/*.js"
13
- }
8
+ ".": "./target/lib.js",
9
+ "./*": "./target/lib/*",
10
+ "./package.json": "./package.json"
14
11
  },
15
12
  "files": [
16
13
  "src",
@@ -49,7 +46,7 @@
49
46
  ]
50
47
  },
51
48
  "test": {
52
- "command": "ava target/**/*.test.js",
49
+ "command": "mocha target/**/*.test.js",
53
50
  "files": [
54
51
  "target/**"
55
52
  ],
@@ -1,10 +1,10 @@
1
- import test from 'ava';
1
+ import { assert } from "chai";
2
2
 
3
- import { Applicator } from './applicator.js';
4
- import { NoopTemplateCache } from './template-cache.js';
5
- import { TemplateLoader } from './template-loader.js';
3
+ import { Applicator } from "./applicator.js";
4
+ import { NoopTemplateCache } from "./template-cache.js";
5
+ import type { TemplateLoader } from "./template-loader.js";
6
6
 
7
- test('should apply declarative shadow dom to specified elements', async (t) => {
7
+ it("should apply declarative shadow dom to specified elements", async () => {
8
8
  class MockTemplateLoader implements TemplateLoader {
9
9
  loadCSS(tag: string): Promise<string | null> {
10
10
  return Promise.resolve(`:host { content: 'css for ${tag}' }`);
@@ -14,7 +14,10 @@ test('should apply declarative shadow dom to specified elements', async (t) => {
14
14
  }
15
15
  }
16
16
 
17
- const applicator = new Applicator(new NoopTemplateCache(), new MockTemplateLoader());
17
+ const applicator = new Applicator(
18
+ new NoopTemplateCache(),
19
+ new MockTemplateLoader(),
20
+ );
18
21
 
19
22
  const document = /*html*/ `
20
23
  <html>
@@ -28,9 +31,13 @@ test('should apply declarative shadow dom to specified elements', async (t) => {
28
31
  </html>
29
32
  `;
30
33
 
31
- const res = await applicator.apply(document, ['mock-header', 'mock-content', 'mock-footer']);
34
+ const res = await applicator.apply(document, [
35
+ "mock-header",
36
+ "mock-content",
37
+ "mock-footer",
38
+ ]);
32
39
 
33
- t.is(
40
+ assert.equal(
34
41
  trim(res),
35
42
  trim(`
36
43
  <html>
@@ -59,11 +66,11 @@ test('should apply declarative shadow dom to specified elements', async (t) => {
59
66
  </mock-footer>
60
67
  </body>
61
68
  </html>
62
- `)
69
+ `),
63
70
  );
64
71
  });
65
72
 
66
- test('should apply declarative shadow dom recursively', async (t) => {
73
+ it("should apply declarative shadow dom recursively", async () => {
67
74
  class MockTemplateLoader implements TemplateLoader {
68
75
  async loadCSS(tag: string): Promise<string | null> {
69
76
  return `:host { content: 'css for ${tag}' }`;
@@ -71,24 +78,31 @@ test('should apply declarative shadow dom recursively', async (t) => {
71
78
 
72
79
  async loadHTML(tag: string): Promise<string | null> {
73
80
  switch (tag) {
74
- case 'mock-foo':
75
- return `<mock-bar></mock-bar>`;
81
+ case "mock-foo":
82
+ return "<mock-bar></mock-bar>";
76
83
 
77
- case 'mock-bar':
78
- return `<mock-baz></mock-baz>`;
84
+ case "mock-bar":
85
+ return "<mock-baz></mock-baz>";
79
86
  }
80
87
 
81
88
  return `<div>html for ${tag}</div>`;
82
89
  }
83
90
  }
84
91
 
85
- const applicator = new Applicator(new NoopTemplateCache(), new MockTemplateLoader());
92
+ const applicator = new Applicator(
93
+ new NoopTemplateCache(),
94
+ new MockTemplateLoader(),
95
+ );
86
96
 
87
- const document = `<mock-foo></mock-foo>`;
97
+ const document = "<mock-foo></mock-foo>";
88
98
 
89
- const res = await applicator.apply(document, ['mock-foo', 'mock-bar', 'mock-baz']);
99
+ const res = await applicator.apply(document, [
100
+ "mock-foo",
101
+ "mock-bar",
102
+ "mock-baz",
103
+ ]);
90
104
 
91
- t.is(
105
+ assert.equal(
92
106
  trim(res),
93
107
  trim(`
94
108
  <html>
@@ -113,10 +127,10 @@ test('should apply declarative shadow dom recursively', async (t) => {
113
127
  </mock-foo>
114
128
  </body>
115
129
  </html>
116
- `)
130
+ `),
117
131
  );
118
132
  });
119
133
 
120
134
  function trim(value: string) {
121
- return value.replace(/\s+/g, '').replace(/(\r\n|\n|\r)/gm, '');
135
+ return value.replace(/\s+/g, "").replace(/(\r\n|\n|\r)/gm, "");
122
136
  }
@@ -1,7 +1,7 @@
1
- import { CheerioAPI, load } from 'cheerio';
1
+ import { type CheerioAPI, load } from "cheerio";
2
2
 
3
- import { TemplateCache } from './template-cache.js';
4
- import { TemplateLoader } from './template-loader.js';
3
+ import type { TemplateCache } from "./template-cache.js";
4
+ import type { TemplateLoader } from "./template-loader.js";
5
5
 
6
6
  export interface ApplicatorOpts {
7
7
  templateCache: TemplateCache;
@@ -17,7 +17,7 @@ export class Applicator {
17
17
  this.#templateLoader = templateLoader;
18
18
  }
19
19
 
20
- async apply(document: string, elements: string[]) {
20
+ async apply(document: string, elements: string[]): Promise<string> {
21
21
  const $ = load(document);
22
22
 
23
23
  return this.build($, elements);
@@ -33,12 +33,15 @@ export class Applicator {
33
33
 
34
34
  if (!elementTemplate) {
35
35
  const template = await this.#buildTemplate(element);
36
- elementTemplate = await this.build(load(template, null, false), elements);
36
+ elementTemplate = await this.build(
37
+ load(template, null, false),
38
+ elements,
39
+ );
37
40
 
38
41
  await this.#templateCache.set(element, elementTemplate);
39
42
  }
40
43
 
41
- if (node.find('> template[shadowrootmode]').length === 0) {
44
+ if (node.find("> template[shadowrootmode]").length === 0) {
42
45
  node.prepend(elementTemplate);
43
46
  }
44
47
  }
@@ -50,12 +53,12 @@ export class Applicator {
50
53
  async #buildTemplate(tag: string) {
51
54
  const [html, styles] = await Promise.all([
52
55
  this.#templateLoader.loadHTML(tag),
53
- this.#templateLoader.loadCSS(tag)
56
+ this.#templateLoader.loadCSS(tag),
54
57
  ]);
55
58
 
56
59
  return `<template shadowroot="open" shadowrootmode="open">
57
- ${styles ? `<style>${styles}</style>` : ''}
58
- ${html || ''}
60
+ ${styles ? `<style>${styles}</style>` : ""}
61
+ ${html || ""}
59
62
  </template>
60
63
  `;
61
64
  }
@@ -1,19 +1,19 @@
1
- import test from 'ava';
1
+ import { assert } from "chai";
2
2
 
3
- import { NoopTemplateCache, TemplateCache } from './template-cache.js';
3
+ import { NoopTemplateCache, TemplateCache } from "./template-cache.js";
4
4
 
5
- test('should cache (in memory)', async (t) => {
5
+ it("should cache (in memory)", async () => {
6
6
  const cache = new TemplateCache();
7
7
 
8
- await cache.set('foo-bar', '<h1>Hello World</h1>');
8
+ await cache.set("foo-bar", "<h1>Hello World</h1>");
9
9
 
10
- t.is(await cache.get('foo-bar'), '<h1>Hello World</h1>');
10
+ assert.equal(await cache.get("foo-bar"), "<h1>Hello World</h1>");
11
11
  });
12
12
 
13
- test('should never cache (noop)', async (t) => {
13
+ it("should never cache (noop)", async () => {
14
14
  const cache = new NoopTemplateCache();
15
15
 
16
- await cache.set('foo-bar', '<h1>Hello World</h1>');
16
+ await cache.set("foo-bar", "<h1>Hello World</h1>");
17
17
 
18
- t.is(await cache.get('foo-bar'), undefined);
18
+ assert.equal(await cache.get("foo-bar"), undefined);
19
19
  });
@@ -1,11 +1,11 @@
1
1
  export class TemplateCache {
2
2
  #cache = new Map<string, string>();
3
3
 
4
- async get(key: string) {
4
+ async get(key: string): Promise<string | undefined> {
5
5
  return this.#cache.get(key);
6
6
  }
7
7
 
8
- async set(key: string, val: string) {
8
+ async set(key: string, val: string): Promise<this> {
9
9
  this.#cache.set(key, val);
10
10
 
11
11
  return this;
@@ -13,11 +13,11 @@ export class TemplateCache {
13
13
  }
14
14
 
15
15
  export class NoopTemplateCache extends TemplateCache {
16
- async get(_: string) {
16
+ async get(_: string): Promise<undefined> {
17
17
  return undefined;
18
18
  }
19
19
 
20
- async set(_key: string, _val: string) {
20
+ async set(_key: string, _val: string): Promise<this> {
21
21
  return this;
22
22
  }
23
23
  }
@@ -1,20 +1,23 @@
1
- import test from 'ava';
2
- import { fileURLToPath } from 'node:url';
3
- import { join } from 'node:path';
1
+ import { join } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { assert } from "chai";
4
4
 
5
- import { FileSysTemplateLoader } from './template-loader.js';
5
+ import { FileSysTemplateLoader } from "./template-loader.js";
6
6
 
7
- const dirname = join(fileURLToPath(new URL('.', import.meta.url)), '../../src/testing');
7
+ const dirname = join(
8
+ fileURLToPath(new URL(".", import.meta.url)),
9
+ "../../src/testing",
10
+ );
8
11
 
9
- test('FileSysTemplateLoader: should read from defined paths', async (t) => {
12
+ it("FileSysTemplateLoader: should read from defined paths", async () => {
10
13
  const loader = new FileSysTemplateLoader(
11
- (tag) => join(dirname, 'elements', tag, tag + '.html'),
12
- (tag) => join(dirname, 'elements', tag, tag + '.css')
14
+ (tag) => join(dirname, "elements", tag, `${tag}.html`),
15
+ (tag) => join(dirname, "elements", tag, `${tag}.css`),
13
16
  );
14
17
 
15
- const html = await loader.loadHTML('my-element');
16
- const css = await loader.loadCSS('my-element');
18
+ const html = await loader.loadHTML("my-element");
19
+ const css = await loader.loadCSS("my-element");
17
20
 
18
- t.is(html?.trim(), `<h2>Hello World</h2>\n\n<slot></slot>`);
19
- t.is(css?.trim(), `:host {\n display: flex;\n}`);
21
+ assert.equal(html?.trim(), "<h2>Hello World</h2>\n\n<slot></slot>");
22
+ assert.equal(css?.trim(), ":host {\n display: flex;\n}");
20
23
  });
@@ -1,4 +1,4 @@
1
- import { readFile } from 'node:fs/promises';
1
+ import { readFile } from "node:fs/promises";
2
2
 
3
3
  /**
4
4
  * A template loader defines how css and html are generated for a given component template.
package/src/lib.ts CHANGED
@@ -1,3 +1,6 @@
1
- export { Applicator } from './lib/applicator.js';
2
- export { TemplateCache, NoopTemplateCache } from './lib/template-cache.js';
3
- export { TemplateLoader, FileSysTemplateLoader } from './lib/template-loader.js';
1
+ export { Applicator } from "./lib/applicator.js";
2
+ export { TemplateCache, NoopTemplateCache } from "./lib/template-cache.js";
3
+ export {
4
+ TemplateLoader,
5
+ FileSysTemplateLoader,
6
+ } from "./lib/template-loader.js";
@@ -0,0 +1,13 @@
1
+ import { type CheerioAPI } from "cheerio";
2
+ import type { TemplateCache } from "./template-cache.js";
3
+ import type { TemplateLoader } from "./template-loader.js";
4
+ export interface ApplicatorOpts {
5
+ templateCache: TemplateCache;
6
+ templateLoader: TemplateLoader;
7
+ }
8
+ export declare class Applicator {
9
+ #private;
10
+ constructor(templateCache: TemplateCache, templateLoader: TemplateLoader);
11
+ apply(document: string, elements: string[]): Promise<string>;
12
+ build($: CheerioAPI, elements: string[]): Promise<string>;
13
+ }
@@ -0,0 +1,43 @@
1
+ import { load } from "cheerio";
2
+ export class Applicator {
3
+ #templateCache;
4
+ #templateLoader;
5
+ constructor(templateCache, templateLoader) {
6
+ this.#templateCache = templateCache;
7
+ this.#templateLoader = templateLoader;
8
+ }
9
+ async apply(document, elements) {
10
+ const $ = load(document);
11
+ return this.build($, elements);
12
+ }
13
+ async build($, elements) {
14
+ for (let i = 0; i < elements.length; i++) {
15
+ const element = elements[i];
16
+ const node = $(element);
17
+ if (node.length) {
18
+ let elementTemplate = await this.#templateCache.get(element);
19
+ if (!elementTemplate) {
20
+ const template = await this.#buildTemplate(element);
21
+ elementTemplate = await this.build(load(template, null, false), elements);
22
+ await this.#templateCache.set(element, elementTemplate);
23
+ }
24
+ if (node.find("> template[shadowrootmode]").length === 0) {
25
+ node.prepend(elementTemplate);
26
+ }
27
+ }
28
+ }
29
+ return $.html();
30
+ }
31
+ async #buildTemplate(tag) {
32
+ const [html, styles] = await Promise.all([
33
+ this.#templateLoader.loadHTML(tag),
34
+ this.#templateLoader.loadCSS(tag),
35
+ ]);
36
+ return `<template shadowroot="open" shadowrootmode="open">
37
+ ${styles ? `<style>${styles}</style>` : ""}
38
+ ${html || ""}
39
+ </template>
40
+ `;
41
+ }
42
+ }
43
+ //# sourceMappingURL=applicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applicator.js","sourceRoot":"","sources":["../../src/lib/applicator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,SAAS,CAAC;AAUhD,MAAM,OAAO,UAAU;IACrB,cAAc,CAAgB;IAC9B,eAAe,CAAiB;IAEhC,YAAY,aAA4B,EAAE,cAA8B;QACtE,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,QAAkB;QAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEzB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,CAAa,EAAE,QAAkB;QAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;YAExB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,IAAI,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAE7D,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;oBACpD,eAAe,GAAG,MAAM,IAAI,CAAC,KAAK,CAChC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,EAC3B,QAAQ,CACT,CAAC;oBAEF,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;gBAC1D,CAAC;gBAED,IAAI,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACzD,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAW;QAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACvC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC;YAClC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC;SAClC,CAAC,CAAC;QAEH,OAAO;QACH,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,UAAU,CAAC,CAAC,CAAC,EAAE;QACxC,IAAI,IAAI,EAAE;;GAEf,CAAC;IACF,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ import { assert } from "chai";
2
+ import { Applicator } from "./applicator.js";
3
+ import { NoopTemplateCache } from "./template-cache.js";
4
+ it("should apply declarative shadow dom to specified elements", async () => {
5
+ class MockTemplateLoader {
6
+ loadCSS(tag) {
7
+ return Promise.resolve(`:host { content: 'css for ${tag}' }`);
8
+ }
9
+ loadHTML(tag) {
10
+ return Promise.resolve(`<div>html for ${tag}</div>`);
11
+ }
12
+ }
13
+ const applicator = new Applicator(new NoopTemplateCache(), new MockTemplateLoader());
14
+ const document = `
15
+ <html>
16
+ <head></head>
17
+
18
+ <body>
19
+ <mock-header></mock-header>
20
+ <mock-content></mock-content>
21
+ <mock-footer></mock-footer>
22
+ </body>
23
+ </html>
24
+ `;
25
+ const res = await applicator.apply(document, [
26
+ "mock-header",
27
+ "mock-content",
28
+ "mock-footer",
29
+ ]);
30
+ assert.equal(trim(res), trim(`
31
+ <html>
32
+ <head></head>
33
+
34
+ <body>
35
+ <mock-header>
36
+ <template shadowroot="open" shadowrootmode="open">
37
+ <style>:host { content: 'css for mock-header'}</style>
38
+ <div>html for mock-header</div>
39
+ </template>
40
+ </mock-header>
41
+
42
+ <mock-content>
43
+ <template shadowroot="open" shadowrootmode="open">
44
+ <style>:host { content: 'css for mock-content'}</style>
45
+ <div>html for mock-content</div>
46
+ </template>
47
+ </mock-content>
48
+
49
+ <mock-footer>
50
+ <template shadowroot="open" shadowrootmode="open">
51
+ <style>:host { content: 'css for mock-footer'}</style>
52
+ <div>html for mock-footer</div>
53
+ </template>
54
+ </mock-footer>
55
+ </body>
56
+ </html>
57
+ `));
58
+ });
59
+ it("should apply declarative shadow dom recursively", async () => {
60
+ class MockTemplateLoader {
61
+ async loadCSS(tag) {
62
+ return `:host { content: 'css for ${tag}' }`;
63
+ }
64
+ async loadHTML(tag) {
65
+ switch (tag) {
66
+ case "mock-foo":
67
+ return "<mock-bar></mock-bar>";
68
+ case "mock-bar":
69
+ return "<mock-baz></mock-baz>";
70
+ }
71
+ return `<div>html for ${tag}</div>`;
72
+ }
73
+ }
74
+ const applicator = new Applicator(new NoopTemplateCache(), new MockTemplateLoader());
75
+ const document = "<mock-foo></mock-foo>";
76
+ const res = await applicator.apply(document, [
77
+ "mock-foo",
78
+ "mock-bar",
79
+ "mock-baz",
80
+ ]);
81
+ assert.equal(trim(res), trim(`
82
+ <html>
83
+ <head></head>
84
+
85
+ <body>
86
+ <mock-foo>
87
+ <template shadowroot="open" shadowrootmode="open">
88
+ <style>:host { content: 'css for mock-foo'}</style>
89
+ <mock-bar>
90
+ <template shadowroot="open" shadowrootmode="open">
91
+ <style>:host { content: 'css for mock-bar'}</style>
92
+ <mock-baz>
93
+ <template shadowroot="open" shadowrootmode="open">
94
+ <style>:host { content: 'css for mock-baz'}</style>
95
+ <div>html for mock-baz</div>
96
+ </template>
97
+ </mock-baz>
98
+ </template>
99
+ </mock-bar>
100
+ </template>
101
+ </mock-foo>
102
+ </body>
103
+ </html>
104
+ `));
105
+ });
106
+ function trim(value) {
107
+ return value.replace(/\s+/g, "").replace(/(\r\n|\n|\r)/gm, "");
108
+ }
109
+ //# sourceMappingURL=applicator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applicator.test.js","sourceRoot":"","sources":["../../src/lib/applicator.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,kBAAkB;QACtB,OAAO,CAAC,GAAW;YACjB,OAAO,OAAO,CAAC,OAAO,CAAC,6BAA6B,GAAG,KAAK,CAAC,CAAC;QAChE,CAAC;QACD,QAAQ,CAAC,GAAW;YAClB,OAAO,OAAO,CAAC,OAAO,CAAC,iBAAiB,GAAG,QAAQ,CAAC,CAAC;QACvD,CAAC;KACF;IAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAC/B,IAAI,iBAAiB,EAAE,EACvB,IAAI,kBAAkB,EAAE,CACzB,CAAC;IAEF,MAAM,QAAQ,GAAY;;;;;;;;;;GAUzB,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE;QAC3C,aAAa;QACb,cAAc;QACd,aAAa;KACd,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CACV,IAAI,CAAC,GAAG,CAAC,EACT,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BN,CAAC,CACD,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;IAC/D,MAAM,kBAAkB;QACtB,KAAK,CAAC,OAAO,CAAC,GAAW;YACvB,OAAO,6BAA6B,GAAG,KAAK,CAAC;QAC/C,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,GAAW;YACxB,QAAQ,GAAG,EAAE,CAAC;gBACZ,KAAK,UAAU;oBACb,OAAO,uBAAuB,CAAC;gBAEjC,KAAK,UAAU;oBACb,OAAO,uBAAuB,CAAC;YACnC,CAAC;YAED,OAAO,iBAAiB,GAAG,QAAQ,CAAC;QACtC,CAAC;KACF;IAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAC/B,IAAI,iBAAiB,EAAE,EACvB,IAAI,kBAAkB,EAAE,CACzB,CAAC;IAEF,MAAM,QAAQ,GAAG,uBAAuB,CAAC;IAEzC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE;QAC3C,UAAU;QACV,UAAU;QACV,UAAU;KACX,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CACV,IAAI,CAAC,GAAG,CAAC,EACT,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;GAuBN,CAAC,CACD,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,SAAS,IAAI,CAAC,KAAa;IACzB,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare class TemplateCache {
2
+ #private;
3
+ get(key: string): Promise<string | undefined>;
4
+ set(key: string, val: string): Promise<this>;
5
+ }
6
+ export declare class NoopTemplateCache extends TemplateCache {
7
+ get(_: string): Promise<undefined>;
8
+ set(_key: string, _val: string): Promise<this>;
9
+ }
@@ -0,0 +1,19 @@
1
+ export class TemplateCache {
2
+ #cache = new Map();
3
+ async get(key) {
4
+ return this.#cache.get(key);
5
+ }
6
+ async set(key, val) {
7
+ this.#cache.set(key, val);
8
+ return this;
9
+ }
10
+ }
11
+ export class NoopTemplateCache extends TemplateCache {
12
+ async get(_) {
13
+ return undefined;
14
+ }
15
+ async set(_key, _val) {
16
+ return this;
17
+ }
18
+ }
19
+ //# sourceMappingURL=template-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-cache.js","sourceRoot":"","sources":["../../src/lib/template-cache.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,aAAa;IACxB,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEnC,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,GAAW;QAChC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAE1B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,KAAK,CAAC,GAAG,CAAC,CAAS;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,IAAY;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { assert } from "chai";
2
+ import { NoopTemplateCache, TemplateCache } from "./template-cache.js";
3
+ it("should cache (in memory)", async () => {
4
+ const cache = new TemplateCache();
5
+ await cache.set("foo-bar", "<h1>Hello World</h1>");
6
+ assert.equal(await cache.get("foo-bar"), "<h1>Hello World</h1>");
7
+ });
8
+ it("should never cache (noop)", async () => {
9
+ const cache = new NoopTemplateCache();
10
+ await cache.set("foo-bar", "<h1>Hello World</h1>");
11
+ assert.equal(await cache.get("foo-bar"), undefined);
12
+ });
13
+ //# sourceMappingURL=template-cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-cache.test.js","sourceRoot":"","sources":["../../src/lib/template-cache.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;IACxC,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAElC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAEnD,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;IACzC,MAAM,KAAK,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAEtC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAEnD,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface TemplateLoader {
2
+ loadHTML(tag: string): Promise<string | null>;
3
+ loadCSS(tag: string): Promise<string | null>;
4
+ }
5
+ export type PathFn = (tag: string) => string;
6
+ export declare class FileSysTemplateLoader implements TemplateLoader {
7
+ #private;
8
+ constructor(html: PathFn, css: PathFn);
9
+ loadHTML(tag: string): Promise<string | null>;
10
+ loadCSS(tag: string): Promise<string | null>;
11
+ }
@@ -0,0 +1,26 @@
1
+ import { readFile } from "node:fs/promises";
2
+ export class FileSysTemplateLoader {
3
+ #html;
4
+ #css;
5
+ constructor(html, css) {
6
+ this.#html = html;
7
+ this.#css = css;
8
+ }
9
+ async loadHTML(tag) {
10
+ try {
11
+ return await readFile(this.#html(tag)).then((res) => res.toString());
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ async loadCSS(tag) {
18
+ try {
19
+ return await readFile(this.#css(tag)).then((res) => res.toString());
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=template-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-loader.js","sourceRoot":"","sources":["../../src/lib/template-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAY5C,MAAM,OAAO,qBAAqB;IAChC,KAAK,CAAS;IACd,IAAI,CAAS;IAEb,YAAY,IAAY,EAAE,GAAW;QACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { join } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { assert } from "chai";
4
+ import { FileSysTemplateLoader } from "./template-loader.js";
5
+ const dirname = join(fileURLToPath(new URL(".", import.meta.url)), "../../src/testing");
6
+ it("FileSysTemplateLoader: should read from defined paths", async () => {
7
+ const loader = new FileSysTemplateLoader((tag) => join(dirname, "elements", tag, `${tag}.html`), (tag) => join(dirname, "elements", tag, `${tag}.css`));
8
+ const html = await loader.loadHTML("my-element");
9
+ const css = await loader.loadCSS("my-element");
10
+ assert.equal(html?.trim(), "<h2>Hello World</h2>\n\n<slot></slot>");
11
+ assert.equal(css?.trim(), ":host {\n display: flex;\n}");
12
+ });
13
+ //# sourceMappingURL=template-loader.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-loader.test.js","sourceRoot":"","sources":["../../src/lib/template-loader.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,OAAO,GAAG,IAAI,CAClB,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC5C,mBAAmB,CACpB,CAAC;AAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,MAAM,GAAG,IAAI,qBAAqB,CACtC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,EACtD,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,MAAM,CAAC,CACtD,CAAC;IAEF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAE/C,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,uCAAuC,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,8BAA8B,CAAC,CAAC;AAC5D,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Applicator } from "./lib/applicator.js";
2
+ export { TemplateCache, NoopTemplateCache } from "./lib/template-cache.js";
3
+ export { TemplateLoader, FileSysTemplateLoader, } from "./lib/template-loader.js";
package/target/lib.js ADDED
@@ -0,0 +1,4 @@
1
+ export { Applicator } from "./lib/applicator.js";
2
+ export { TemplateCache, NoopTemplateCache } from "./lib/template-cache.js";
3
+ export { FileSysTemplateLoader, } from "./lib/template-loader.js";
4
+ //# sourceMappingURL=lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAEL,qBAAqB,GACtB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=my-element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"my-element.js","sourceRoot":"","sources":["../../../../src/testing/elements/my-element/my-element.ts"],"names":[],"mappings":""}