diff --git a/core/css.ts b/core/css.ts index 07e9c98a485..4e71bda7b72 100644 --- a/core/css.ts +++ b/core/css.ts @@ -8,6 +8,7 @@ /** Has CSS already been injected? */ let injected = false; +let styleSheet: CSSStyleSheet; /** * Add some CSS to the blob that will be injected later. Allows optional @@ -33,27 +34,46 @@ export function register(cssContent: string) { * document's responsibility). * @param pathToMedia Path from page to the Blockly media directory. */ -export function inject(hasCss: boolean, pathToMedia: string) { - // Only inject the CSS once. - if (injected) { - return; - } - injected = true; +export function inject(hasCss: boolean, pathToMedia: string, container: Element) { if (!hasCss) { + injected = true; return; } - // Strip off any trailing slash (either Unix or Windows). - const mediaPath = pathToMedia.replace(/[\\/]$/, ''); - const cssContent = content.replace(/<<>>/g, mediaPath); - // Cleanup the collected css content after injecting it to the DOM. - content = ''; - - // Inject CSS tag at start of head. - const cssNode = document.createElement('style'); - cssNode.id = 'blockly-common-style'; - const cssTextNode = document.createTextNode(cssContent); - cssNode.appendChild(cssTextNode); - document.head.insertBefore(cssNode, document.head.firstChild); + + const root = container?.getRootNode() ?? document; + if (root === document) { + // Only inject the CSS once. + if (injected) { + return; + } + injected = true; + + // Strip off any trailing slash (either Unix or Windows). + const mediaPath = pathToMedia.replace(/[\\/]$/, ''); + const cssContent = content.replace(/<<>>/g, mediaPath); + // Cleanup the collected css content after injecting it to the DOM. + content = ''; + + // Inject CSS tag at start of head. + const cssNode = document.createElement('style'); + cssNode.id = 'blockly-common-style'; + const cssTextNode = document.createTextNode(cssContent); + cssNode.appendChild(cssTextNode); + + document.head.insertBefore(cssNode, document.head.firstChild); + } else { + if (!styleSheet) { + // Strip off any trailing slash (either Unix or Windows). + const mediaPath = pathToMedia.replace(/[\\/]$/, ''); + const cssContent = content.replace(/<<>>/g, mediaPath); + // Cleanup the collected css content after injecting it to the DOM. + content = ''; + + styleSheet = new CSSStyleSheet(); + styleSheet.replaceSync(cssContent); + } + ( root).adoptedStyleSheets = [...( root).adoptedStyleSheets, styleSheet]; + } } /** diff --git a/core/inject.ts b/core/inject.ts index b938abaa4e0..72bff381175 100644 --- a/core/inject.ts +++ b/core/inject.ts @@ -91,7 +91,7 @@ function createDom(container: Element, options: Options): SVGElement { container.setAttribute('dir', 'LTR'); // Load CSS. - Css.inject(options.hasCss, options.pathToMedia); + Css.inject(options.hasCss, options.pathToMedia, container); // Build the SVG DOM. /* diff --git a/core/renderers/common/constants.ts b/core/renderers/common/constants.ts index f0acc39aa02..d37e82e4343 100644 --- a/core/renderers/common/constants.ts +++ b/core/renderers/common/constants.ts @@ -1077,7 +1077,9 @@ export class ConstantProvider { * @param tagName The name of the style tag to use. * @param selector The CSS selector to use. */ - protected injectCSS_(tagName: string, selector: string) { + protected injectCSS_(tagName: string, selector: string, svg: SVGElement) { + const root = svg?.getRootNode() ?? document; + const cssArray = this.getCSS_(selector); const cssNodeId = 'blockly-renderer-style-' + tagName; this.cssNode = document.getElementById(cssNodeId) as HTMLStyleElement; @@ -1092,7 +1094,10 @@ export class ConstantProvider { cssNode.id = cssNodeId; const cssTextNode = document.createTextNode(text); cssNode.appendChild(cssTextNode); - document.head.insertBefore(cssNode, document.head.firstChild); + if (root === document) + document.head.insertBefore(cssNode, document.head.firstChild); + else + root.insertBefore(cssNode, root.firstChild); this.cssNode = cssNode; } diff --git a/tests/webcomponent.html b/tests/webcomponent.html new file mode 100644 index 00000000000..53a7205c346 --- /dev/null +++ b/tests/webcomponent.html @@ -0,0 +1,204 @@ + + + + + + Blockly Playground Webcomponent + + + + + + + + + + + + \ No newline at end of file