From b427b04fc9191126d4bf819d61c7054306427be3 Mon Sep 17 00:00:00 2001 From: Doug Parker Date: Sat, 24 Jul 2021 11:06:00 -0700 Subject: [PATCH] Adds Declarative Shadow DOM polyfill. Refs #38. TODO --- packages/rules_prerender/BUILD.bazel | 50 +++++++++++++++++++ packages/rules_prerender/BUILD.publish | 18 +++++++ .../rules_prerender/declarative_shadow_dom.ts | 10 ++++ .../declarative_shadow_dom_polyfill.ts | 21 ++++++++ .../declarative_shadow_dom_polyfill_test.ts | 9 ++++ .../declarative_shadow_dom_script.ts | 4 ++ .../declarative_shadow_dom_test.ts | 11 ++++ .../rules_prerender/prerender_component.bzl | 2 +- 8 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 packages/rules_prerender/declarative_shadow_dom.ts create mode 100644 packages/rules_prerender/declarative_shadow_dom_polyfill.ts create mode 100644 packages/rules_prerender/declarative_shadow_dom_polyfill_test.ts create mode 100644 packages/rules_prerender/declarative_shadow_dom_script.ts create mode 100644 packages/rules_prerender/declarative_shadow_dom_test.ts diff --git a/packages/rules_prerender/BUILD.bazel b/packages/rules_prerender/BUILD.bazel index bd54221c..e66098b5 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,50 @@ 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_script"], + 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_script", + srcs = ["declarative_shadow_dom_script.ts"], + deps = [":declarative_shadow_dom_polyfill"], +) + +ts_library( + name = "declarative_shadow_dom_polyfill", + srcs = ["declarative_shadow_dom_polyfill.ts"], +) + +ts_library( + name = "declarative_shadow_dom_polyfill_test_lib", + srcs = ["declarative_shadow_dom_polyfill_test.ts"], + testonly = True, + deps = [ + ":declarative_shadow_dom_polyfill", + "@npm//@types/jasmine", + ], +) + +# TODO: Test in Karma. 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..24aa9fd5 --- /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_script'); +} 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..125fbc06 --- /dev/null +++ b/packages/rules_prerender/declarative_shadow_dom_polyfill.ts @@ -0,0 +1,21 @@ +/** + * Shamelessly stolen from: https://web.dev/declarative-shadow-dom/#polyfill and + * adapted for TypeScript. + */ +export function polyfillDeclarativeShadowDom(): void { + 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_polyfill_test.ts b/packages/rules_prerender/declarative_shadow_dom_polyfill_test.ts new file mode 100644 index 00000000..cd2823d2 --- /dev/null +++ b/packages/rules_prerender/declarative_shadow_dom_polyfill_test.ts @@ -0,0 +1,9 @@ +import 'jasmine'; + +describe('declarative_shadow_dom_polyfill', () => { + describe('polyfillDeclarativeShadowDom()', () => { + it('polyfills declarative shadow DOM', () => { + // TODO + }); + }); +}); diff --git a/packages/rules_prerender/declarative_shadow_dom_script.ts b/packages/rules_prerender/declarative_shadow_dom_script.ts new file mode 100644 index 00000000..2724c015 --- /dev/null +++ b/packages/rules_prerender/declarative_shadow_dom_script.ts @@ -0,0 +1,4 @@ +import { polyfillDeclarativeShadowDom } from './declarative_shadow_dom_polyfill'; + +// Polyfill on page load. +polyfillDeclarativeShadowDom(); 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..979fd089 --- /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,