Skip to content

Commit 1bdcdb9

Browse files
feat(hydrate): export style content from hydrated scoped components (#6260)
* feat(hydrate): export style content from hydrated scoped components * prettier * linting fix
1 parent 9657927 commit 1bdcdb9

File tree

5 files changed

+26
-1
lines changed

5 files changed

+26
-1
lines changed

src/declarations/stencil-private.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,9 @@ export interface HydrateScriptElement extends HydrateElement {
11961196
}
11971197

11981198
export interface HydrateStyleElement extends HydrateElement {
1199+
id?: string;
11991200
href?: string;
1201+
content?: string;
12001202
}
12011203

12021204
export interface HydrateStaticData {

src/hydrate/runner/render.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Readable } from 'node:stream';
22

33
import { hydrateFactory } from '@hydrate-factory';
44
import { modeResolutionChain, setMode } from '@platform';
5+
import { HYDRATED_STYLE_ID } from '@runtime';
56
import { MockWindow, serializeNodeToHtml } from '@stencil/core/mock-doc';
67
import { hasError } from '@utils';
78

@@ -215,6 +216,17 @@ function finalizeHydrate(win: MockWindow, doc: Document, opts: HydrateFactoryOpt
215216
removeScripts(doc.documentElement);
216217
}
217218

219+
const styles = doc.querySelectorAll('head style');
220+
if (styles.length > 0) {
221+
results.styles.push(
222+
...Array.from(styles).map((style) => ({
223+
href: style.getAttribute('href'),
224+
id: style.getAttribute(HYDRATED_STYLE_ID),
225+
content: style.textContent,
226+
})),
227+
);
228+
}
229+
218230
try {
219231
updateCanonicalLink(doc, opts.canonicalUrl);
220232
} catch (e) {

src/runtime/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export { parsePropertyValue } from './parse-property-value';
1313
export { setPlatformOptions } from './platform-options';
1414
export { proxyComponent } from './proxy-component';
1515
export { render } from './render';
16+
export { HYDRATED_STYLE_ID } from './runtime-constants';
1617
export { getValue, setValue } from './set-value';
1718
export { forceUpdate, getRenderingRef, postUpdateComponent } from './update-component';
1819
export { h, Host } from './vdom/h';

test/end-to-end/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/end-to-end/src/miscellaneous/renderToString.e2e.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,14 @@ describe('renderToString', () => {
159159
'<head><meta charset="utf-8"><style sty-id="sc-scoped-car-list">.sc-scoped-car-list-h{display:block;margin:10px;padding:10px;border:1px solid blue}ul.sc-scoped-car-list{display:block;margin:0;padding:0}li.sc-scoped-car-list{list-style:none;margin:0;padding:20px}.selected.sc-scoped-car-list{font-weight:bold;background:rgb(255, 255, 210)}</style><style class="vjs-styles-defaults">.video-js {width: 300px;height: 150px;}.vjs-fluid:not(.vjs-audio-only-mode) {padding-top: 56.25%}</style> <link rel="stylesheet" href="whatever.css"> </head>',
160160
);
161161
});
162+
163+
it('populates style information even if we do not render the whole document', async () => {
164+
const { styles } = await renderToString(
165+
`<scoped-car-list cars=${JSON.stringify([vento, beetle])}></scoped-car-list>`,
166+
);
167+
expect(styles.length).toBe(2);
168+
expect(styles[0].id).toBe('sc-scoped-car-list');
169+
expect(styles[0].content).toContain('.sc-scoped-car-list-h{display:block;');
170+
expect(styles[1].content).toContain('.video-js {');
171+
});
162172
});

0 commit comments

Comments
 (0)