Skip to content

Commit eb79fd5

Browse files
feat(hydrate): export style content from hydrated scoped components
1 parent 992a687 commit eb79fd5

File tree

5 files changed

+22
-1
lines changed

5 files changed

+22
-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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { hydrateFactory } from '@hydrate-factory';
44
import { modeResolutionChain, setMode } from '@platform';
55
import { MockWindow, serializeNodeToHtml } from '@stencil/core/mock-doc';
66
import { hasError } from '@utils';
7+
import { HYDRATED_STYLE_ID } from '@runtime';
78

89
import { updateCanonicalLink } from '../../compiler/html/canonical-link';
910
import { relocateMetaCharset } from '../../compiler/html/relocate-meta-charset';
@@ -210,6 +211,15 @@ function finalizeHydrate(win: MockWindow, doc: Document, opts: HydrateFactoryOpt
210211
removeScripts(doc.documentElement);
211212
}
212213

214+
const styles = doc.querySelectorAll('head style');
215+
if (styles.length > 0) {
216+
results.styles.push(...Array.from(styles).map((style) => ({
217+
href: style.getAttribute('href'),
218+
id: style.getAttribute(HYDRATED_STYLE_ID),
219+
content: style.textContent,
220+
})));
221+
}
222+
213223
try {
214224
updateCanonicalLink(doc, opts.canonicalUrl);
215225
} catch (e) {

src/runtime/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ export { forceUpdate, getRenderingRef, postUpdateComponent } from './update-comp
1818
export { h, Host } from './vdom/h';
1919
export { insertVdomAnnotations } from './vdom/vdom-annotations';
2020
export { renderVdom } from './vdom/vdom-render';
21+
export { HYDRATED_STYLE_ID } from './runtime-constants';

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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,12 @@ 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(`<scoped-car-list cars=${JSON.stringify([vento, beetle])}></scoped-car-list>`);
165+
expect(styles.length).toBe(2);
166+
expect(styles[0].id).toBe('sc-scoped-car-list');
167+
expect(styles[0].content).toContain('.sc-scoped-car-list-h{display:block;');
168+
expect(styles[1].content).toContain('.video-js {');
169+
});
162170
});

0 commit comments

Comments
 (0)