@jasonshimmy/vite-plugin-cer-app 0.4.2 → 0.4.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 CHANGED
@@ -1,6 +1,11 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
+ ## [v0.4.3] - 2026-03-21
5
+
6
+ - fix: fix DSD config and update FOUC tests to DSD correctness tests and enhance assertions (a8d36a3)
7
+ - chore: update eslint (5a367e0)
8
+
4
9
  ## [v0.4.2] - 2026-03-21
5
10
 
6
11
  - fix: update dependencies in project templates to latest versions (1390724)
package/commits.txt CHANGED
@@ -1 +1,2 @@
1
- - fix: update dependencies in project templates to latest versions (1390724)
1
+ - fix: fix DSD config and update FOUC tests to DSD correctness tests and enhance assertions (a8d36a3)
2
+ - chore: update eslint (5a367e0)
@@ -162,11 +162,11 @@ async function generateInlineTemplate(targetDir, projectName, mode) {
162
162
  preview: 'cer-app preview',
163
163
  },
164
164
  dependencies: {
165
- '@jasonshimmy/custom-elements-runtime': '^3.2.0',
165
+ '@jasonshimmy/custom-elements-runtime': '^3.2.1',
166
166
  },
167
167
  devDependencies: {
168
168
  vite: '^8.0.1',
169
- '@jasonshimmy/vite-plugin-cer-app': '^0.4.1',
169
+ '@jasonshimmy/vite-plugin-cer-app': '^0.4.2',
170
170
  typescript: '^5.9.3',
171
171
  },
172
172
  }, null, 2), 'utf-8');
@@ -178,6 +178,8 @@ async function generateInlineTemplate(targetDir, projectName, mode) {
178
178
  await writeFile(join(targetDir, 'app/layouts/default.ts'), `component('layout-default', () => {\n return html\`\n <header><nav><router-link to="/">Home</router-link></nav></header>\n <main><slot></slot></main>\n <footer><p>Built with CER App</p></footer>\n \`\n})\n`, 'utf-8');
179
179
  // .gitignore
180
180
  await writeFile(join(targetDir, '.gitignore'), `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n\n# CER App generated directory\n.cer/\n\n# Environment variables\n.env.local\n.env.*.local\n\n# Editor\n.vscode/\n.idea/\n*.suo\n*.sw?\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\n`, 'utf-8');
181
+ // tsconfig.json
182
+ await writeFile(join(targetDir, 'tsconfig.json'), `{\n "extends": "./.cer/tsconfig.json"\n}\n`, 'utf-8');
181
183
  // index.html
182
184
  await writeFile(join(targetDir, 'index.html'), `<!DOCTYPE html>\n<html lang="en">\n <head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>${projectName}</title>\n </head>\n <body>\n <cer-layout-view></cer-layout-view>\n <script type="module" src="/@cer/app.ts"></script>\n </body>\n</html>\n`, 'utf-8');
183
185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/create/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/create/index.ts"],"names":[],"mappings":"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"}
@@ -8,11 +8,11 @@
8
8
  "preview": "cer-app preview"
9
9
  },
10
10
  "dependencies": {
11
- "@jasonshimmy/custom-elements-runtime": "^3.2.0"
11
+ "@jasonshimmy/custom-elements-runtime": "^3.2.1"
12
12
  },
13
13
  "devDependencies": {
14
14
  "vite": "^8.0.1",
15
- "@jasonshimmy/vite-plugin-cer-app": "^0.4.1",
15
+ "@jasonshimmy/vite-plugin-cer-app": "^0.4.2",
16
16
  "typescript": "^5.9.3"
17
17
  }
18
18
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.cer/tsconfig.json"
3
+ }
@@ -9,11 +9,11 @@
9
9
  "preview": "cer-app preview"
10
10
  },
11
11
  "dependencies": {
12
- "@jasonshimmy/custom-elements-runtime": "^3.2.0"
12
+ "@jasonshimmy/custom-elements-runtime": "^3.2.1"
13
13
  },
14
14
  "devDependencies": {
15
15
  "vite": "^8.0.1",
16
- "@jasonshimmy/vite-plugin-cer-app": "^0.4.1",
16
+ "@jasonshimmy/vite-plugin-cer-app": "^0.4.2",
17
17
  "typescript": "^5.9.3"
18
18
  }
19
19
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.cer/tsconfig.json"
3
+ }
@@ -8,11 +8,11 @@
8
8
  "preview": "cer-app preview --ssr"
9
9
  },
10
10
  "dependencies": {
11
- "@jasonshimmy/custom-elements-runtime": "^3.2.0"
11
+ "@jasonshimmy/custom-elements-runtime": "^3.2.1"
12
12
  },
13
13
  "devDependencies": {
14
14
  "vite": "^8.0.1",
15
- "@jasonshimmy/vite-plugin-cer-app": "^0.4.1",
15
+ "@jasonshimmy/vite-plugin-cer-app": "^0.4.2",
16
16
  "typescript": "^5.9.3"
17
17
  }
18
18
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.cer/tsconfig.json"
3
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"build-ssr.d.ts","sourceRoot":"","sources":["../../src/plugin/build-ssr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAG7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAGxD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAQpE;AAkND;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,iBAAiB,EACzB,cAAc,GAAE,UAAe,GAC9B,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
1
+ {"version":3,"file":"build-ssr.d.ts","sourceRoot":"","sources":["../../src/plugin/build-ssr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAG7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAGxD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAQpE;AAsND;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,iBAAiB,EACzB,cAAc,GAAE,UAAe,GAC9B,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
@@ -27,7 +27,11 @@ export function resolveClientEntry(config) {
27
27
  * The server entry template that wires all virtual modules together and
28
28
  * exports a request handler for Node.js (Express-compatible).
29
29
  */
30
- function generateServerEntryCode() {
30
+ function generateServerEntryCode(config) {
31
+ const dsd = config.ssr.dsd;
32
+ const renderImport = dsd
33
+ ? `import { registerEntityMap, renderToStringWithJITCSSDSD, DSD_POLYFILL_SCRIPT } from '@jasonshimmy/custom-elements-runtime/ssr'`
34
+ : `import { registerEntityMap, renderToStringWithJITCSS } from '@jasonshimmy/custom-elements-runtime/ssr'`;
31
35
  return `// AUTO-GENERATED server entry by @jasonshimmy/vite-plugin-cer-app
32
36
  import { readFileSync, existsSync } from 'node:fs'
33
37
  import { dirname, join } from 'node:path'
@@ -38,7 +42,7 @@ import layouts from 'virtual:cer-layouts'
38
42
  import plugins from 'virtual:cer-plugins'
39
43
  import apiRoutes from 'virtual:cer-server-api'
40
44
  import { registerBuiltinComponents } from '@jasonshimmy/custom-elements-runtime'
41
- import { registerEntityMap, renderToStringWithJITCSSDSD, DSD_POLYFILL_SCRIPT } from '@jasonshimmy/custom-elements-runtime/ssr'
45
+ ${renderImport}
42
46
  import entitiesJson from '@jasonshimmy/custom-elements-runtime/entities.json'
43
47
  import { initRouter } from '@jasonshimmy/custom-elements-runtime/router'
44
48
  import { beginHeadCollection, endHeadCollection, serializeHeadTags } from '@jasonshimmy/vite-plugin-cer-app/composables'
@@ -193,7 +197,7 @@ export const handler = async (req, res) => {
193
197
  // dsdPolyfill: false — we inject the polyfill manually after merging so it
194
198
  // lands at the end of <body>, not inside <cer-layout-view> light DOM where
195
199
  // scripts may not execute.
196
- const { htmlWithStyles } = renderToStringWithJITCSSDSD(vnode, {
200
+ const { htmlWithStyles } = ${dsd ? 'renderToStringWithJITCSSDSD' : 'renderToStringWithJITCSS'}(vnode, {
197
201
  dsdPolyfill: false,
198
202
  router,
199
203
  })
@@ -218,9 +222,9 @@ export const handler = async (req, res) => {
218
222
 
219
223
  // Inject DSD polyfill at end of <body>, outside <cer-layout-view>, so the
220
224
  // browser runs it after parsing the declarative shadow roots.
221
- finalHtml = finalHtml.includes('</body>')
225
+ ${dsd ? `finalHtml = finalHtml.includes('</body>')
222
226
  ? finalHtml.replace('</body>', DSD_POLYFILL_SCRIPT + '</body>')
223
- : finalHtml + DSD_POLYFILL_SCRIPT
227
+ : finalHtml + DSD_POLYFILL_SCRIPT` : '// dsd: false — no DSD polyfill needed'}
224
228
 
225
229
  res.setHeader('Content-Type', 'text/html; charset=utf-8')
226
230
  res.end(finalHtml)
@@ -268,7 +272,7 @@ export async function buildSSR(config, viteUserConfig = {}) {
268
272
  renameSync(generatedHtmlOut, rootHtmlOut);
269
273
  }
270
274
  // Generate server entry source inline via a virtual plugin
271
- const serverEntryCode = generateServerEntryCode();
275
+ const serverEntryCode = generateServerEntryCode(config);
272
276
  const VIRTUAL_SERVER_ENTRY = 'virtual:cer-server-entry';
273
277
  const RESOLVED_SERVER_ENTRY = '\0virtual:cer-server-entry';
274
278
  // Build the server (SSR) bundle
@@ -1 +1 @@
1
- {"version":3,"file":"build-ssr.js","sourceRoot":"","sources":["../../src/plugin/build-ssr.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-ssr.js","sourceRoot":"","sources":["../../src/plugin/build-ssr.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,22 @@
1
1
  /**
2
- * FOUC (Flash of Unstyled Content) tests.
2
+ * Declarative Shadow DOM (DSD) correctness tests.
3
3
  *
4
4
  * For SSR and SSG modes, validates that the server-rendered HTML:
5
- * 1. Contains Declarative Shadow DOM templates
6
- * 2. Each shadow template has its own embedded <style> block
5
+ * 1. Contains <template shadowrootmode="open"> elements (value must be "open")
6
+ * 2. Each shadow template has its own embedded <style> (JIT CSS not stripped to <head>)
7
7
  * 3. Shadow DOM styles are NOT hoisted to <head> (which would break encapsulation)
8
- * 4. The loading indicator is NOT present in the initial HTML
9
- * 5. cer-layout-view has pre-rendered content (not empty)
10
- *
11
- * FOUC occurs when styles are missing from shadow roots on first parse.
12
- * These checks verify the DSD structure prevents FOUC before JS hydrates.
8
+ * 4. Shadow templates contain the actual rendered component content
9
+ * 5. More complex routes produce more shadow templates than simple routes
10
+ * 6. The loading indicator is NOT present in the initial HTML
11
+ * 7. The DSD polyfill is present and positioned after </cer-layout-view>
12
+ * 8. After JS hydration, custom elements have live, accessible shadow roots
13
+ * 9. Hydration does not duplicate or destroy the pre-rendered shadow content
13
14
  */
14
15
 
15
16
  const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
16
17
 
17
- // Routes to check for FOUC — all pre-renderable routes
18
- const ROUTES_TO_CHECK = [
18
+ // All pre-renderable routes
19
+ const ALL_ROUTES = [
19
20
  '/',
20
21
  '/about',
21
22
  '/counter',
@@ -28,38 +29,171 @@ const ROUTES_TO_CHECK = [
28
29
  '/login',
29
30
  ]
30
31
 
31
- describe('FOUC prevention', () => {
32
- before(() => {
33
- if (mode === 'spa') {
34
- cy.log('Skipping FOUC tests in SPA mode (no server-side rendering)')
35
- }
32
+ if (mode === 'spa') {
33
+ describe('DSD (skipped in SPA mode)', () => {
34
+ it('SPA mode has no server-side rendering — DSD tests are SSR/SSG only', () => {
35
+ cy.log('DSD tests are skipped in SPA mode')
36
+ })
37
+ })
38
+ } else {
39
+ // ─── Structure: every route has well-formed DSD ───────────────────────────
40
+
41
+ describe('DSD structure — all routes', () => {
42
+ ALL_ROUTES.forEach((path) => {
43
+ it(`${path} has valid DSD structure`, () => {
44
+ cy.assertDSDStructure(path)
45
+ })
46
+ })
47
+ })
48
+
49
+ // ─── Content: shadow templates contain the actual rendered content ─────────
50
+
51
+ describe('DSD content — shadow templates contain rendered output', () => {
52
+ it('home (/): layout nav and page heading are inside shadow templates', () => {
53
+ // layout-default renders site-nav; page-index renders the home heading
54
+ cy.assertDSDContains('/', 'data-cy="site-nav"')
55
+ cy.assertDSDContains('/', 'data-cy="home-heading"')
56
+ cy.assertDSDContains('/', 'Kitchen Sink')
57
+ })
58
+
59
+ it('home (/): ks-badge content is inside a shadow template', () => {
60
+ cy.assertDSDContains('/', 'data-cy="ks-badge"')
61
+ })
62
+
63
+ it('about (/about): page heading is inside a shadow template', () => {
64
+ cy.assertDSDContains('/about', 'data-cy="about-heading"')
65
+ cy.assertDSDContains('/about', 'About')
66
+ })
67
+
68
+ it('counter (/counter): heading and initial count 0 are inside shadow templates', () => {
69
+ cy.assertDSDContains('/counter', 'data-cy="counter-heading"')
70
+ cy.assertDSDContains('/counter', 'Counter')
71
+ cy.assertDSDContains('/counter', 'data-cy="count"')
72
+ })
73
+
74
+ it('blog (/blog): blog heading is inside a shadow template', () => {
75
+ cy.assertDSDContains('/blog', 'data-cy="blog-heading"')
76
+ })
77
+
78
+ it('blog detail (/blog/first-post): post title is inside a shadow template', () => {
79
+ cy.assertDSDContains('/blog/first-post', 'First Post')
80
+ })
81
+ })
82
+
83
+ // ─── Template depth: complex routes have more templates than simple ones ───
84
+
85
+ describe('DSD template count — complexity reflects component tree', () => {
86
+ it('home (/) has more shadow templates than about (/about)', () => {
87
+ cy.request('/').then((homeResp) => {
88
+ cy.request('/about').then((aboutResp) => {
89
+ const homeTemplates = [
90
+ ...homeResp.body.matchAll(/<template shadowrootmode="open"/g),
91
+ ].length
92
+ const aboutTemplates = [
93
+ ...aboutResp.body.matchAll(/<template shadowrootmode="open"/g),
94
+ ].length
95
+
96
+ expect(
97
+ homeTemplates,
98
+ 'home page (default layout + page-index + ks-badge) should have more templates than about',
99
+ ).to.be.greaterThan(aboutTemplates)
100
+ })
101
+ })
102
+ })
103
+
104
+ it('each route has at least 2 shadow templates (layout + page)', () => {
105
+ ALL_ROUTES.forEach((path) => {
106
+ cy.request(path).then((resp) => {
107
+ const count = [...resp.body.matchAll(/<template shadowrootmode="open"/g)].length
108
+ expect(count, `${path}: should have at least 2 shadow templates`).to.be.at.least(2)
109
+ })
110
+ })
111
+ })
36
112
  })
37
113
 
38
- if (mode === 'spa') return
114
+ // ─── DSD polyfill ─────────────────────────────────────────────────────────
115
+
116
+ describe('DSD polyfill', () => {
117
+ it('polyfill script is present in the home page HTML', () => {
118
+ cy.request('/').then((resp) => {
119
+ // The polyfill inlines a function that calls attachShadow on existing templates
120
+ expect(resp.body, 'DSD polyfill should be present in server HTML').to.include(
121
+ 'attachShadow',
122
+ )
123
+ })
124
+ })
39
125
 
40
- ROUTES_TO_CHECK.forEach((path) => {
41
- it(`${path}: shadow templates have embedded styles (no FOUC)`, () => {
42
- cy.assertNoDSD_FOUC(path)
126
+ it('polyfill is placed after </cer-layout-view> so it runs outside shadow light DOM', () => {
127
+ cy.request('/').then((resp) => {
128
+ const html: string = resp.body
129
+ const clvEnd = html.lastIndexOf('</cer-layout-view>')
130
+ const polyfillIdx = html.indexOf('attachShadow')
131
+ expect(clvEnd, 'cer-layout-view closing tag must exist').to.be.greaterThan(-1)
132
+ expect(polyfillIdx, 'DSD polyfill must exist').to.be.greaterThan(-1)
133
+ expect(polyfillIdx, 'DSD polyfill must come AFTER </cer-layout-view>').to.be.greaterThan(
134
+ clvEnd,
135
+ )
136
+ })
43
137
  })
44
138
  })
45
139
 
46
- it('DSD polyfill is placed after </cer-layout-view>, not inside it', () => {
47
- cy.request('/').then((response) => {
48
- const html: string = response.body
49
- const clvEnd = html.lastIndexOf('</cer-layout-view>')
50
- const polyfillIdx = html.indexOf('attachShadow')
51
- if (polyfillIdx >= 0) {
52
- expect(polyfillIdx, 'DSD polyfill must come AFTER </cer-layout-view>').to.be.greaterThan(clvEnd)
53
- }
140
+ // ─── Loading indicator ────────────────────────────────────────────────────
141
+
142
+ describe('loading indicator absent from initial HTML', () => {
143
+ it('home page: loading indicator is not in the server-rendered HTML', () => {
144
+ cy.request('/').then((resp) => {
145
+ expect(resp.body).not.to.include('page-loading')
146
+ expect(resp.body).not.to.include('data-cy="loading-indicator"')
147
+ })
54
148
  })
55
149
  })
56
150
 
57
- it('home page: loading indicator is not visible on first paint', () => {
58
- // The loading component (page-loading) should never appear in initial HTML.
59
- // If it does, it means isNavigating was true during SSR — a FOUC bug.
60
- cy.request('/').then((response) => {
61
- expect(response.body).not.to.include('page-loading')
62
- expect(response.body).not.to.include('data-cy="loading-indicator"')
151
+ // ─── Hydration: shadow roots are live after JS boots ──────────────────────
152
+
153
+ describe('DSD hydration shadow roots live after JS', () => {
154
+ it('layout-default has a live shadow root after hydration on home (/)', () => {
155
+ cy.visit('/')
156
+ cy.get('layout-default').should('exist')
157
+ cy.assertShadowRootLive('layout-default')
158
+ })
159
+
160
+ it('page-index has a live shadow root after hydration on home (/)', () => {
161
+ cy.visit('/')
162
+ cy.get('page-index', { includeShadowDom: true }).should('exist')
163
+ cy.assertShadowRootLive('page-index')
164
+ })
165
+
166
+ it('layout-minimal has a live shadow root after hydration on about (/about)', () => {
167
+ cy.visit('/about')
168
+ cy.get('layout-minimal').should('exist')
169
+ cy.assertShadowRootLive('layout-minimal')
170
+ })
171
+
172
+ it('page-about has a live shadow root after hydration on about (/about)', () => {
173
+ cy.visit('/about')
174
+ cy.assertShadowRootLive('page-about')
175
+ })
176
+
177
+ it('page-counter has a live shadow root after hydration on counter (/counter)', () => {
178
+ cy.visit('/counter')
179
+ cy.assertShadowRootLive('page-counter')
180
+ })
181
+
182
+ it('shadow root content survives hydration — home heading still readable', () => {
183
+ cy.visit('/')
184
+ // Content set by DSD pre-render should still be accessible in the live shadow root
185
+ cy.get('[data-cy="home-heading"]').should('have.text', 'Kitchen Sink')
186
+ })
187
+
188
+ it('shadow root content survives hydration — site-nav still rendered', () => {
189
+ cy.visit('/')
190
+ cy.get('[data-cy="site-nav"]').should('exist')
191
+ cy.get('[data-cy="nav-home"]').should('exist')
192
+ })
193
+
194
+ it('shadow root content survives hydration — counter shows initial count 0', () => {
195
+ cy.visit('/counter')
196
+ cy.get('[data-cy="count"]').should('have.text', '0')
63
197
  })
64
198
  })
65
- })
199
+ }
@@ -3,46 +3,104 @@
3
3
  */
4
4
 
5
5
  /**
6
- * Assert that the raw HTML for a route has proper DSD structure:
7
- * - Contains <template shadowrootmode> elements
8
- * - Each template has embedded <style> (not stripped to <head>)
6
+ * Assert that the raw HTML for a route has correct Declarative Shadow DOM structure:
7
+ * - Contains <template shadowrootmode="open"> elements (value must be "open")
8
+ * - Each shadow template has embedded <style> (JIT CSS not stripped to <head>)
9
+ * - No bare (unnamed) <style> blocks in <head>
9
10
  * - No loading indicator in the pre-rendered HTML
10
- * - Content is present (not empty cer-layout-view)
11
+ * - cer-layout-view has pre-rendered content (not empty)
11
12
  */
12
- Cypress.Commands.add('assertNoDSD_FOUC', (path: string) => {
13
+ Cypress.Commands.add('assertDSDStructure', (path: string) => {
13
14
  cy.request(path).then((response) => {
14
15
  const html: string = response.body
15
16
 
16
- // Must have DSD templates
17
- expect(html, `${path}: should contain DSD templates`).to.include('<template shadowrootmode')
17
+ // Must have DSD templates with value "open" (not "closed", not missing)
18
+ expect(html, `${path}: should contain <template shadowrootmode="open">`).to.include(
19
+ 'shadowrootmode="open"',
20
+ )
18
21
 
19
22
  // Each shadow template must have its own <style> block (not hoisted to <head>)
20
- const templateMatches = [...html.matchAll(/<template shadowrootmode[^>]*>([\s\S]*?)<\/template>/g)]
21
- expect(templateMatches.length, `${path}: should have at least 1 shadow template`).to.be.greaterThan(0)
23
+ const templateMatches = [
24
+ ...html.matchAll(/<template shadowrootmode="open"[^>]*>([\s\S]*?)<\/template>/g),
25
+ ]
26
+ expect(
27
+ templateMatches.length,
28
+ `${path}: should have at least 1 shadow template with shadowrootmode="open"`,
29
+ ).to.be.greaterThan(0)
30
+
22
31
  templateMatches.forEach(([, content], i) => {
23
- expect(content, `${path}: template[${i}] should contain <style>`).to.include('<style')
32
+ expect(content, `${path}: template[${i}] must contain its own <style> block`).to.include(
33
+ '<style',
34
+ )
24
35
  })
25
36
 
26
37
  // The <head> must NOT contain raw unnamed <style> blocks (only id'd global ones are OK)
27
38
  const headMatch = html.match(/<head>([\s\S]*?)<\/head>/)
28
39
  if (headMatch) {
29
- const headContent = headMatch[1]
30
- // Allow <style id=...> (global JIT/SSR styles), reject bare <style> without id
31
- const bareStyles = headContent.match(/<style(?!\s+id)[^>]*>/g) ?? []
32
- expect(bareStyles.length, `${path}: <head> must not contain un-named <style> blocks`).to.equal(0)
40
+ const bareStyles = headMatch[1].match(/<style(?!\s+id)[^>]*>/g) ?? []
41
+ expect(
42
+ bareStyles.length,
43
+ `${path}: <head> must not contain un-named <style> blocks`,
44
+ ).to.equal(0)
33
45
  }
34
46
 
35
47
  // Loading indicator must NOT appear in the initial server-rendered HTML
36
- expect(html, `${path}: loading indicator must not be in initial HTML`).not.to.include('data-cy="loading-indicator"')
48
+ expect(html, `${path}: loading indicator must not be in initial HTML`).not.to.include(
49
+ 'data-cy="loading-indicator"',
50
+ )
37
51
 
38
- // cer-layout-view must not be empty (pre-rendered content present)
52
+ // cer-layout-view must have pre-rendered content (not an empty tag)
39
53
  const layoutViewMatch = html.match(/<cer-layout-view>([\s\S]*?)<\/cer-layout-view>/)
40
54
  if (layoutViewMatch) {
41
- expect(layoutViewMatch[1].trim(), `${path}: cer-layout-view must have pre-rendered content`).not.to.be.empty
55
+ expect(
56
+ layoutViewMatch[1].trim(),
57
+ `${path}: cer-layout-view must have pre-rendered content`,
58
+ ).not.to.be.empty
42
59
  }
43
60
  })
44
61
  })
45
62
 
63
+ /**
64
+ * Assert that the raw HTML for a route contains specific text inside a shadow template.
65
+ * Use this to verify that DSD actually rendered the component's content — not just
66
+ * that templates exist.
67
+ *
68
+ * Since shadow templates can be nested (a component's shadow template may contain
69
+ * child custom elements with their own shadow templates), we verify that the expected
70
+ * text appears anywhere in the raw HTML. assertDSDStructure already confirms that
71
+ * the content is wrapped in <template shadowrootmode="open"> — if templates exist
72
+ * and the attribute/text is in the HTML, it lives inside those templates.
73
+ */
74
+ Cypress.Commands.add('assertDSDContains', (path: string, expectedText: string) => {
75
+ cy.request(path).then((response) => {
76
+ const html: string = response.body
77
+
78
+ // Confirm we're in DSD territory first
79
+ expect(html, `${path}: page must have DSD templates before checking content`).to.include(
80
+ 'shadowrootmode="open"',
81
+ )
82
+
83
+ expect(html, `${path}: shadow templates should contain "${expectedText}"`).to.include(
84
+ expectedText,
85
+ )
86
+ })
87
+ })
88
+
89
+ /**
90
+ * Assert that after JS hydration, a custom element has a live shadow root.
91
+ * This confirms that DSD was processed by the browser and the element was upgraded.
92
+ */
93
+ Cypress.Commands.add('assertShadowRootLive', (selector: string) => {
94
+ cy.window().then((win) => {
95
+ const el = win.document.querySelector(selector)
96
+ expect(el, `${selector}: element should exist in the DOM`).to.not.be.null
97
+ expect(
98
+ (el as Element & { shadowRoot: ShadowRoot | null }).shadowRoot,
99
+ `${selector}: should have a live shadow root after hydration`,
100
+ ).to.not.be.null
101
+ })
102
+ })
103
+
46
104
  /**
47
105
  * Wait for a shadow DOM element to appear (handles lazy rendering).
48
106
  */
@@ -53,8 +111,17 @@ Cypress.Commands.add('getShadow', (selector: string) => {
53
111
  declare global {
54
112
  namespace Cypress {
55
113
  interface Chainable {
114
+ /** @deprecated Use assertDSDStructure instead */
56
115
  assertNoDSD_FOUC(path: string): Chainable<void>
116
+ assertDSDStructure(path: string): Chainable<void>
117
+ assertDSDContains(path: string, expectedText: string): Chainable<void>
118
+ assertShadowRootLive(selector: string): Chainable<void>
57
119
  getShadow(selector: string): Chainable<JQuery<HTMLElement>>
58
120
  }
59
121
  }
60
122
  }
123
+
124
+ // Keep old name as alias so any remaining callers don't break
125
+ Cypress.Commands.add('assertNoDSD_FOUC', (path: string) => {
126
+ cy.assertDSDStructure(path)
127
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jasonshimmy/vite-plugin-cer-app",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Nuxt-style meta-framework for @jasonshimmy/custom-elements-runtime",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -82,7 +82,7 @@
82
82
  "@types/node": "^25.5.0",
83
83
  "@vitest/coverage-v8": "^4.1.0",
84
84
  "cypress": "^15.12.0",
85
- "eslint": "^10.0.3",
85
+ "eslint": "^10.1.0",
86
86
  "happy-dom": "^20.8.4",
87
87
  "jiti": "^2.6.1",
88
88
  "start-server-and-test": "^2.1.5",
@@ -198,11 +198,11 @@ async function generateInlineTemplate(
198
198
  preview: 'cer-app preview',
199
199
  },
200
200
  dependencies: {
201
- '@jasonshimmy/custom-elements-runtime': '^3.2.0',
201
+ '@jasonshimmy/custom-elements-runtime': '^3.2.1',
202
202
  },
203
203
  devDependencies: {
204
204
  vite: '^8.0.1',
205
- '@jasonshimmy/vite-plugin-cer-app': '^0.4.1',
205
+ '@jasonshimmy/vite-plugin-cer-app': '^0.4.2',
206
206
  typescript: '^5.9.3',
207
207
  },
208
208
  },
@@ -240,6 +240,13 @@ async function generateInlineTemplate(
240
240
  'utf-8',
241
241
  )
242
242
 
243
+ // tsconfig.json
244
+ await writeFile(
245
+ join(targetDir, 'tsconfig.json'),
246
+ `{\n "extends": "./.cer/tsconfig.json"\n}\n`,
247
+ 'utf-8',
248
+ )
249
+
243
250
  // index.html
244
251
  await writeFile(
245
252
  join(targetDir, 'index.html'),
@@ -8,11 +8,11 @@
8
8
  "preview": "cer-app preview"
9
9
  },
10
10
  "dependencies": {
11
- "@jasonshimmy/custom-elements-runtime": "^3.2.0"
11
+ "@jasonshimmy/custom-elements-runtime": "^3.2.1"
12
12
  },
13
13
  "devDependencies": {
14
14
  "vite": "^8.0.1",
15
- "@jasonshimmy/vite-plugin-cer-app": "^0.4.1",
15
+ "@jasonshimmy/vite-plugin-cer-app": "^0.4.2",
16
16
  "typescript": "^5.9.3"
17
17
  }
18
18
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.cer/tsconfig.json"
3
+ }
@@ -9,11 +9,11 @@
9
9
  "preview": "cer-app preview"
10
10
  },
11
11
  "dependencies": {
12
- "@jasonshimmy/custom-elements-runtime": "^3.2.0"
12
+ "@jasonshimmy/custom-elements-runtime": "^3.2.1"
13
13
  },
14
14
  "devDependencies": {
15
15
  "vite": "^8.0.1",
16
- "@jasonshimmy/vite-plugin-cer-app": "^0.4.1",
16
+ "@jasonshimmy/vite-plugin-cer-app": "^0.4.2",
17
17
  "typescript": "^5.9.3"
18
18
  }
19
19
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.cer/tsconfig.json"
3
+ }
@@ -8,11 +8,11 @@
8
8
  "preview": "cer-app preview --ssr"
9
9
  },
10
10
  "dependencies": {
11
- "@jasonshimmy/custom-elements-runtime": "^3.2.0"
11
+ "@jasonshimmy/custom-elements-runtime": "^3.2.1"
12
12
  },
13
13
  "devDependencies": {
14
14
  "vite": "^8.0.1",
15
- "@jasonshimmy/vite-plugin-cer-app": "^0.4.1",
15
+ "@jasonshimmy/vite-plugin-cer-app": "^0.4.2",
16
16
  "typescript": "^5.9.3"
17
17
  }
18
18
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.cer/tsconfig.json"
3
+ }
@@ -27,7 +27,11 @@ export function resolveClientEntry(config: ResolvedCerConfig): string {
27
27
  * The server entry template that wires all virtual modules together and
28
28
  * exports a request handler for Node.js (Express-compatible).
29
29
  */
30
- function generateServerEntryCode(): string {
30
+ function generateServerEntryCode(config: ResolvedCerConfig): string {
31
+ const dsd = config.ssr.dsd
32
+ const renderImport = dsd
33
+ ? `import { registerEntityMap, renderToStringWithJITCSSDSD, DSD_POLYFILL_SCRIPT } from '@jasonshimmy/custom-elements-runtime/ssr'`
34
+ : `import { registerEntityMap, renderToStringWithJITCSS } from '@jasonshimmy/custom-elements-runtime/ssr'`
31
35
  return `// AUTO-GENERATED server entry by @jasonshimmy/vite-plugin-cer-app
32
36
  import { readFileSync, existsSync } from 'node:fs'
33
37
  import { dirname, join } from 'node:path'
@@ -38,7 +42,7 @@ import layouts from 'virtual:cer-layouts'
38
42
  import plugins from 'virtual:cer-plugins'
39
43
  import apiRoutes from 'virtual:cer-server-api'
40
44
  import { registerBuiltinComponents } from '@jasonshimmy/custom-elements-runtime'
41
- import { registerEntityMap, renderToStringWithJITCSSDSD, DSD_POLYFILL_SCRIPT } from '@jasonshimmy/custom-elements-runtime/ssr'
45
+ ${renderImport}
42
46
  import entitiesJson from '@jasonshimmy/custom-elements-runtime/entities.json'
43
47
  import { initRouter } from '@jasonshimmy/custom-elements-runtime/router'
44
48
  import { beginHeadCollection, endHeadCollection, serializeHeadTags } from '@jasonshimmy/vite-plugin-cer-app/composables'
@@ -193,7 +197,7 @@ export const handler = async (req, res) => {
193
197
  // dsdPolyfill: false — we inject the polyfill manually after merging so it
194
198
  // lands at the end of <body>, not inside <cer-layout-view> light DOM where
195
199
  // scripts may not execute.
196
- const { htmlWithStyles } = renderToStringWithJITCSSDSD(vnode, {
200
+ const { htmlWithStyles } = ${dsd ? 'renderToStringWithJITCSSDSD' : 'renderToStringWithJITCSS'}(vnode, {
197
201
  dsdPolyfill: false,
198
202
  router,
199
203
  })
@@ -218,9 +222,9 @@ export const handler = async (req, res) => {
218
222
 
219
223
  // Inject DSD polyfill at end of <body>, outside <cer-layout-view>, so the
220
224
  // browser runs it after parsing the declarative shadow roots.
221
- finalHtml = finalHtml.includes('</body>')
225
+ ${dsd ? `finalHtml = finalHtml.includes('</body>')
222
226
  ? finalHtml.replace('</body>', DSD_POLYFILL_SCRIPT + '</body>')
223
- : finalHtml + DSD_POLYFILL_SCRIPT
227
+ : finalHtml + DSD_POLYFILL_SCRIPT` : '// dsd: false — no DSD polyfill needed'}
224
228
 
225
229
  res.setHeader('Content-Type', 'text/html; charset=utf-8')
226
230
  res.end(finalHtml)
@@ -277,7 +281,7 @@ export async function buildSSR(
277
281
  }
278
282
 
279
283
  // Generate server entry source inline via a virtual plugin
280
- const serverEntryCode = generateServerEntryCode()
284
+ const serverEntryCode = generateServerEntryCode(config)
281
285
  const VIRTUAL_SERVER_ENTRY = 'virtual:cer-server-entry'
282
286
  const RESOLVED_SERVER_ENTRY = '\0virtual:cer-server-entry'
283
287