diff --git a/packages/rules_prerender/BUILD.bazel b/packages/rules_prerender/BUILD.bazel index bd54221c..1c08774d 100644 --- a/packages/rules_prerender/BUILD.bazel +++ b/packages/rules_prerender/BUILD.bazel @@ -1,5 +1,6 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@npm//@bazel/typescript:index.bzl", "ts_library") +load("//:index.bzl", "prerender_component") load("//tools:jasmine.bzl", "jasmine_node_test") load("//tools:publish.bzl", "publish_files") @@ -24,6 +25,8 @@ publish_files( name = "publish_files", files = glob(["**/*.bzl"]) + [ "rollup-default.config.js", + "declarative_shadow_dom.ts", + "declarative_shadow_dom_polyfill.ts", ], visibility = ["//:__pkg__"], ) @@ -165,3 +168,32 @@ jasmine_node_test( name = "styles_test", deps = [":styles_test_lib"], ) + + +prerender_component( + name = "declarative_shadow_dom", + srcs = ["declarative_shadow_dom.ts"], + scripts = [":declarative_shadow_dom_polyfill"], + lib_deps = [":rules_prerender"], + visibility = ["//visibility:public"], +) + +ts_library( + name = "declarative_shadow_dom_test_lib", + srcs = ["declarative_shadow_dom_test.ts"], + testonly = True, + deps = [ + ":declarative_shadow_dom_prerender_for_test", + "@npm//@types/jasmine", + ], +) + +jasmine_node_test( + name = "declarative_shadow_dom_test", + deps = [":declarative_shadow_dom_test_lib"], +) + +ts_library( + name = "declarative_shadow_dom_polyfill", + srcs = ["declarative_shadow_dom_polyfill.ts"], +) diff --git a/packages/rules_prerender/BUILD.publish b/packages/rules_prerender/BUILD.publish index 276aec82..b6b505f4 100644 --- a/packages/rules_prerender/BUILD.publish +++ b/packages/rules_prerender/BUILD.publish @@ -1,4 +1,22 @@ +load(":prerender_component.bzl", "prerender_component") +load("@npm//@bazel/typescript:index.bzl", "ts_library") + exports_files( ["rollup-default.config.js"], visibility = ["//visibility:public"], ) + +# TESTME +# TODO(#39): Don't ship TypeScript code to NPM and compile it on the user's cpu. +prerender_component( + name = "declarative_shadow_dom", + srcs = ["declarative_shadow_dom.ts"], + scripts = [":declarative_shadow_dom_polyfill"], + lib_deps = ["@npm//rules_prerender"], + visibility = ["//visibility:public"], +) + +ts_library( + name = "declarative_shadow_dom_polyfill", + srcs = ["declarative_shadow_dom_polyfill.ts"], +) diff --git a/packages/rules_prerender/declarative_shadow_dom.ts b/packages/rules_prerender/declarative_shadow_dom.ts new file mode 100644 index 00000000..eec74fe6 --- /dev/null +++ b/packages/rules_prerender/declarative_shadow_dom.ts @@ -0,0 +1,10 @@ +import { includeScript } from 'rules_prerender'; + +/** + * Returns a prerender annotation used by the bundler to inject the declarative + * shadow DOM polyfill into the document. + */ +export function polyfillDeclarativeShadowDom(): string { + return includeScript( + 'rules_prerender/packages/rules_prerender/declarative_shadow_dom_polyfill'); +} diff --git a/packages/rules_prerender/declarative_shadow_dom_polyfill.ts b/packages/rules_prerender/declarative_shadow_dom_polyfill.ts new file mode 100644 index 00000000..862882fb --- /dev/null +++ b/packages/rules_prerender/declarative_shadow_dom_polyfill.ts @@ -0,0 +1,23 @@ +/** + * @fileoverview Polyfills declarative shadow DOM by searching for templates + * which match its attributes and attaching them as real shadow roots. + * + * Shamelessly stolen from: https://web.dev/declarative-shadow-dom/#polyfill and + * adapted for TypeScript. + */ + +const templates = document.querySelectorAll('template[shadowroot]') as + NodeListOf; +for (const template of Array.from(templates)) { + const mode = template.getAttribute('shadowroot')!; + if (mode !== 'open' && mode !== 'closed') { + console.error( + `Found declarative shadow root with invalid mode: ${mode}.`); + continue; + } + + const parent = template.parentNode as Element; + const shadowRoot = parent.attachShadow({ mode }); + shadowRoot.appendChild(template.content); + template.remove(); +} diff --git a/packages/rules_prerender/declarative_shadow_dom_test.ts b/packages/rules_prerender/declarative_shadow_dom_test.ts new file mode 100644 index 00000000..c62e8f11 --- /dev/null +++ b/packages/rules_prerender/declarative_shadow_dom_test.ts @@ -0,0 +1,11 @@ +import 'jasmine'; +import { polyfillDeclarativeShadowDom } from 'rules_prerender/packages/rules_prerender/declarative_shadow_dom'; + +describe('declarative_shadow_dom', () => { + describe('polyfillDeclarativeShadowDom()', () => { + it('returns an annotation to include the declarative shadow DOM polyfill', () => { + expect(polyfillDeclarativeShadowDom()) + .toBe(''); + }); + }); +}); diff --git a/packages/rules_prerender/prerender_component.bzl b/packages/rules_prerender/prerender_component.bzl index e8b21844..f36b3da8 100644 --- a/packages/rules_prerender/prerender_component.bzl +++ b/packages/rules_prerender/prerender_component.bzl @@ -70,7 +70,7 @@ def prerender_component( name = prerender_lib, srcs = srcs, tsconfig = tsconfig, - data = data, + data = data + styles, deps = lib_deps + ["%s_prerender" % absolute(dep) for dep in deps], testonly = testonly, visibility = visibility,