diff --git a/greenwood.config.js b/greenwood.config.js index 73fc49abb..648fdc361 100644 --- a/greenwood.config.js +++ b/greenwood.config.js @@ -14,7 +14,9 @@ export default { interpolateFrontmatter: true, plugins: [ greenwoodPluginGraphQL(), - greenwoodPluginPolyfills(), + greenwoodPluginPolyfills({ + lit: true + }), greenwoodPluginPostCss(), greenwoodPluginImportJson(), greenwoodPluginImportCss(), diff --git a/package.json b/package.json index 71518641b..fe99893d8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "lint": "ls-lint && yarn lint:js && yarn lint:ts && yarn lint:css" }, "resolutions": { - "lit": "^2.1.1" + "lit": "^3.1.0" }, "devDependencies": { "@ls-lint/ls-lint": "^1.10.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3298bb85c..8bb492765 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -52,7 +52,7 @@ "remark-rehype": "^7.0.0", "rollup": "^3.29.4", "unified": "^9.2.0", - "wc-compiler": "~0.11.0" + "wc-compiler": "~0.12.0" }, "devDependencies": { "@babel/runtime": "^7.10.4", @@ -62,7 +62,7 @@ "@material/mwc-button": "^0.25.2", "@stencil/core": "^2.12.0", "@types/trusted-types": "^2.0.2", - "lit": "^2.0.0", + "lit": "^3.1.0", "lit-redux-router": "~0.20.0", "lodash-es": "^4.17.20", "postcss-nested": "^4.1.2", diff --git a/packages/cli/src/config/rollup.config.js b/packages/cli/src/config/rollup.config.js index 8aa6f56c2..53fa89845 100644 --- a/packages/cli/src/config/rollup.config.js +++ b/packages/cli/src/config/rollup.config.js @@ -6,30 +6,11 @@ import commonjs from '@rollup/plugin-commonjs'; import * as walk from 'acorn-walk'; // https://github.com/rollup/rollup/issues/2121 +// would be nice to get rid of this function cleanRollupId(id) { return id.replace('\x00', ''); } -// specifically to handle escodegen and other node modules -// using require for package.json or other json files -// https://github.com/estools/escodegen/issues/455 -function greenwoodJsonLoader() { - return { - name: 'greenwood-json-loader', - async load(id) { - const idUrl = new URL(`file://${cleanRollupId(id)}`); - const extension = idUrl.pathname.split('.').pop(); - - if (extension === 'json') { - const json = JSON.parse(await fs.promises.readFile(idUrl, 'utf-8')); - const contents = `export default ${JSON.stringify(json)}`; - - return contents; - } - } - }; -} - function greenwoodResourceLoader (compilation) { const resourcePlugins = compilation.config.plugins.filter((plugin) => { return plugin.type === 'resource'; @@ -373,9 +354,14 @@ const getRollupConfigForApis = async (compilation) => { chunkFileNames: '[name].[hash].js' }, plugins: [ - greenwoodJsonLoader(), greenwoodResourceLoader(compilation), - nodeResolve(), + // support node export conditions for API routes + // https://github.com/ProjectEvergreen/greenwood/issues/1118 + // https://github.com/rollup/plugins/issues/362#issuecomment-873448461 + nodeResolve({ + exportConditions: ['node'], + preferBuiltins: true + }), commonjs(), greenwoodImportMetaUrl(compilation) ] @@ -395,12 +381,12 @@ const getRollupConfigForSsr = async (compilation, input) => { chunkFileNames: '[name].[hash].js' }, plugins: [ - greenwoodJsonLoader(), greenwoodResourceLoader(compilation), - // TODO let this through for lit to enable nodeResolve({ preferBuiltins: true }) - // https://github.com/lit/lit/issues/449 + // support node export conditions for SSR pages // https://github.com/ProjectEvergreen/greenwood/issues/1118 + // https://github.com/rollup/plugins/issues/362#issuecomment-873448461 nodeResolve({ + exportConditions: ['node'], preferBuiltins: true }), commonjs(), diff --git a/packages/cli/src/lib/resource-utils.js b/packages/cli/src/lib/resource-utils.js index a3d71e579..1032afc5e 100644 --- a/packages/cli/src/lib/resource-utils.js +++ b/packages/cli/src/lib/resource-utils.js @@ -124,7 +124,8 @@ async function trackResourcesForRoute(html, compilation, route) { const scripts = await Promise.all(root.querySelectorAll('script') .filter(script => ( isLocalLink(script.getAttribute('src')) || script.rawText) - && script.rawAttrs.indexOf('importmap') < 0) + && script.rawAttrs.indexOf('importmap') < 0 + && script.getAttribute('type') !== 'application/json') .map(async(script) => { const src = script.getAttribute('src'); const optimizationAttr = script.getAttribute('data-gwd-opt'); diff --git a/packages/cli/src/lib/templating-utils.js b/packages/cli/src/lib/templating-utils.js index 9503e6aac..f9e83b771 100644 --- a/packages/cli/src/lib/templating-utils.js +++ b/packages/cli/src/lib/templating-utils.js @@ -1,7 +1,6 @@ import fs from 'fs/promises'; import htmlparser from 'node-html-parser'; import { checkResourceExists } from './resource-utils.js'; -import { getPackageJson } from './node-modules-utils.js'; async function getCustomPageTemplatesFromPlugins(contextPlugins, templateName) { const customTemplateLocations = []; @@ -177,7 +176,7 @@ async function getAppTemplate(pageTemplateContents, context, customImports = [], } async function getUserScripts (contents, compilation) { - const { context, config } = compilation; + const { config } = compilation; contents = contents.replace('', ` @@ -186,22 +185,6 @@ async function getUserScripts (contents, compilation) { `); - // TODO get rid of lit polyfills in core - // https://github.com/ProjectEvergreen/greenwood/issues/728 - // https://lit.dev/docs/tools/requirements/#polyfills - if (process.env.__GWD_COMMAND__ === 'build') { // eslint-disable-line no-underscore-dangle - const userPackageJson = await getPackageJson(context); - const dependencies = userPackageJson?.dependencies || {}; - const litPolyfill = dependencies && dependencies.lit - ? '\n' - : ''; - - contents = contents.replace('', ` - - ${litPolyfill} - `); - } - return contents; } diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js index e5a28fdd5..22f96cca4 100644 --- a/packages/cli/src/lifecycles/bundle.js +++ b/packages/cli/src/lifecycles/bundle.js @@ -7,6 +7,28 @@ import { checkResourceExists, mergeResponse, normalizePathnameForWindows } from import path from 'path'; import { rollup } from 'rollup'; +async function interceptPage(url, request, plugins, body) { + let response = new Response(body, { + headers: new Headers({ 'Content-Type': 'text/html' }) + }); + + for (const plugin of plugins) { + if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response)) { + response = await plugin.intercept(url, request, response); + } + } + + return response; +} + +function getPluginInstances(compilation) { + return [...compilation.config.plugins] + .filter(plugin => plugin.type === 'resource' && plugin.name !== 'plugin-node-modules:resource') + .map((plugin) => { + return plugin.provider(compilation); + }); +} + async function emitResources(compilation) { const { outputDir } = compilation.context; const { resources, graph } = compilation; @@ -202,6 +224,7 @@ async function bundleSsrPages(compilation) { staticHtml = data.template ? data.template : await getPageTemplate(staticHtml, compilation.context, template, []); staticHtml = await getAppTemplate(staticHtml, compilation.context, imports, [], false, title); staticHtml = await getUserScripts(staticHtml, compilation); + staticHtml = await (await interceptPage(new URL(`http://localhost:8080${route}`), new Request(new URL(`http://localhost:8080${route}`)), getPluginInstances(compilation), staticHtml)).text(); staticHtml = await (await htmlOptimizer.optimize(new URL(`http://localhost:8080${route}`), new Response(staticHtml))).text(); staticHtml = staticHtml.replace(/[`\\$]/g, '\\$&'); // https://stackoverflow.com/a/75688937/417806 diff --git a/packages/cli/src/lifecycles/graph.js b/packages/cli/src/lifecycles/graph.js index 557d6c0f9..227c87a78 100644 --- a/packages/cli/src/lifecycles/graph.js +++ b/packages/cli/src/lifecycles/graph.js @@ -51,6 +51,7 @@ const generateGraph = async (compilation) => { let filePath; let prerender = true; let isolation = false; + let hydration = false; /* * check if additional nested directories exist to correctly determine route (minus filename) @@ -132,8 +133,9 @@ const generateGraph = async (compilation) => { const request = await requestAsObject(new Request(filenameUrl)); worker.on('message', async (result) => { - prerender = result.prerender; + prerender = result.prerender ?? false; isolation = result.isolation ?? isolation; + hydration = result.hydration ?? hydration; if (result.frontmatter) { result.frontmatter.imports = result.frontmatter.imports || []; @@ -203,8 +205,9 @@ const generateGraph = async (compilation) => { * template: page template to use as a base for a generated component * title: a default value that can be used for * isSSR: if this is a server side route - * prerednder: if this should be statically exported + * prerender: if this should be statically exported * isolation: if this should be run in isolated mode + * hydration: if this page needs hydration support */ pages.push({ data: customData || {}, @@ -225,7 +228,8 @@ const generateGraph = async (compilation) => { title, isSSR: !isStatic, prerender, - isolation + isolation, + hydration }); } } diff --git a/packages/cli/src/plugins/resource/plugin-standard-html.js b/packages/cli/src/plugins/resource/plugin-standard-html.js index 8f0622545..cf3c1cff2 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-html.js +++ b/packages/cli/src/plugins/resource/plugin-standard-html.js @@ -115,6 +115,7 @@ class StandardHtmlResource extends ResourceInterface { if (result.template) { ssrTemplate = result.template; } + if (result.body) { ssrBody = result.body; } diff --git a/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js b/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js index 736d93df5..6f89c6466 100644 --- a/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js +++ b/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js @@ -217,9 +217,8 @@ describe('Build Greenwood With: ', function() { expect(mainScriptTags.length).to.be.equal(1); }); - // TODO clean up lit-polyfill as part of https://github.com/ProjectEvergreen/greenwood/issues/728 it('should have the total expected number of .js file in the output directory', async function() { - expect(await glob.promise(path.join(this.context.publicDir, '*.js'))).to.have.lengthOf(4); + expect(await glob.promise(path.join(this.context.publicDir, '*.js'))).to.have.lengthOf(3); }); it('should have the expected main.js file in the output directory', async function() { @@ -242,7 +241,7 @@ describe('Build Greenwood With: ', function() { const inlineScriptTag = Array.from(dom.window.document.querySelectorAll('head > script:not([src])')).filter(tag => !tag.getAttribute('data-gwd'))[0]; expect(inlineScriptTag.textContent.replace(/\n/g, '')).to - .equal('import"/116321042.262925e6.js";import"/lit-html.71ac31d8.js";//# sourceMappingURL=116321042.f667a8c7.js.map'); + .equal('import"/116321042.4f3171e3.js";import"/lit-html.31ea57aa.js";//# sourceMappingURL=116321042.69f46fc1.js.map'); }); }); diff --git a/packages/cli/test/cases/build.default.import-node-modules/package.json b/packages/cli/test/cases/build.default.import-node-modules/package.json index a280755e3..bf0c8c424 100644 --- a/packages/cli/test/cases/build.default.import-node-modules/package.json +++ b/packages/cli/test/cases/build.default.import-node-modules/package.json @@ -2,7 +2,7 @@ "name": "test-import-node-modules", "type": "module", "dependencies": { - "lit": "^2.0.0", + "lit": "^3.1.0", "lodash-es": "^4.17.20", "prismjs": "^1.21.0", "pwa-helpers": "^0.9.1", diff --git a/packages/cli/test/cases/build.default.spa/build.default.spa.spec.js b/packages/cli/test/cases/build.default.spa/build.default.spa.spec.js index 0905ab808..334895120 100644 --- a/packages/cli/test/cases/build.default.spa/build.default.spa.spec.js +++ b/packages/cli/test/cases/build.default.spa/build.default.spa.spec.js @@ -235,8 +235,7 @@ describe('Build Greenwood With: ', function() { // one for the footer.js // one for index.js // one for lit element bundle - // TODO clean up lit-polyfill as part of https://github.com/ProjectEvergreen/greenwood/issues/728 - expect(jsFiles.length).to.be.equal(6); + expect(jsFiles.length).to.be.equal(5); }); it('should have custom tag in the <head>', function() { diff --git a/packages/cli/test/cases/build.default.spa/package.json b/packages/cli/test/cases/build.default.spa/package.json index bc59f2ff5..e8f6bae6e 100644 --- a/packages/cli/test/cases/build.default.spa/package.json +++ b/packages/cli/test/cases/build.default.spa/package.json @@ -1,7 +1,7 @@ { "type": "module", "dependencies": { - "lit": "^2.0.0", + "lit": "^3.1.0", "lit-redux-router": "~0.20.0", "pwa-helpers": "^0.9.1", "redux": "^4.0.5", diff --git a/packages/cli/test/cases/build.default.ssr-static-export/build.default.ssr-static-export.spec.js b/packages/cli/test/cases/build.default.ssr-static-export/build.default.ssr-static-export.spec.js index 71582d099..566348c5c 100644 --- a/packages/cli/test/cases/build.default.ssr-static-export/build.default.ssr-static-export.spec.js +++ b/packages/cli/test/cases/build.default.ssr-static-export/build.default.ssr-static-export.spec.js @@ -147,11 +147,10 @@ describe('Build Greenwood With: ', function() { expect(styles.length).to.equal(1); }); - // TODO clean up lit-polyfill as part of https://github.com/ProjectEvergreen/greenwood/issues/728 it('should have four script tags', function() { const scripts = Array.from(dom.window.document.querySelectorAll('head > script')).filter(tag => !tag.getAttribute('data-gwd')); - expect(scripts.length).to.equal(4); + expect(scripts.length).to.equal(3); }); it('should have expected SSR content from the non module script tag', function() { diff --git a/packages/cli/test/cases/build.default.ssr-static-export/package.json b/packages/cli/test/cases/build.default.ssr-static-export/package.json index 2dee3e768..0b8c2d82a 100644 --- a/packages/cli/test/cases/build.default.ssr-static-export/package.json +++ b/packages/cli/test/cases/build.default.ssr-static-export/package.json @@ -1,6 +1,6 @@ { "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/cli/test/cases/develop.default/develop.default.spec.js b/packages/cli/test/cases/develop.default/develop.default.spec.js index 8c3cf16e2..3958267f5 100644 --- a/packages/cli/test/cases/develop.default/develop.default.spec.js +++ b/packages/cli/test/cases/develop.default/develop.default.spec.js @@ -101,6 +101,10 @@ describe('Develop Greenwood With: ', function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -379,6 +383,7 @@ describe('Develop Greenwood With: ', function() { ...getSetupFiles(outputPath), ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, diff --git a/packages/cli/test/cases/develop.default/import-map.snapshot.json b/packages/cli/test/cases/develop.default/import-map.snapshot.json index ad256ef39..4e5f60629 100644 --- a/packages/cli/test/cases/develop.default/import-map.snapshot.json +++ b/packages/cli/test/cases/develop.default/import-map.snapshot.json @@ -235,10 +235,6 @@ "lit-html/directives/unsafe-svg.js": "/node_modules/lit-html/directives/unsafe-svg.js", "lit/directives/unsafe-svg.js": "/node_modules/lit/directives/unsafe-svg.js", "lit-html/directives/until.js": "/node_modules/lit-html/directives/until.js", - "lit-element/experimental-hydrate-support.js": "/node_modules/lit-element/experimental-hydrate-support.js", - "lit/experimental-hydrate-support.js": "/node_modules/lit/experimental-hydrate-support.js", - "lit-html/experimental-hydrate.js": "/node_modules/lit-html/experimental-hydrate.js", - "lit/experimental-hydrate.js": "/node_modules/lit/experimental-hydrate.js", "lit/html.js": "/node_modules/lit/html.js", "lit/polyfill-support.js": "/node_modules/lit/polyfill-support.js", "lit-html/static.js": "/node_modules/lit-html/static.js", diff --git a/packages/cli/test/cases/develop.default/package.json b/packages/cli/test/cases/develop.default/package.json index cb0f93aca..b3fda5ee7 100644 --- a/packages/cli/test/cases/develop.default/package.json +++ b/packages/cli/test/cases/develop.default/package.json @@ -8,6 +8,6 @@ "@material/mwc-button": "^0.25.2", "@stencil/core": "^2.12.0", "@types/trusted-types": "^2.0.2", - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js b/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js index 4f7919f66..4eef144f6 100644 --- a/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js +++ b/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js @@ -64,6 +64,10 @@ describe('Develop Greenwood With: ', function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -111,6 +115,7 @@ describe('Develop Greenwood With: ', function() { ...getSetupFiles(outputPath), ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, diff --git a/packages/cli/test/cases/develop.ssr/package.json b/packages/cli/test/cases/develop.ssr/package.json index 2dee3e768..0b8c2d82a 100644 --- a/packages/cli/test/cases/develop.ssr/package.json +++ b/packages/cli/test/cases/develop.ssr/package.json @@ -1,6 +1,6 @@ { "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/cli/test/cases/serve.default.ssr-static-export/package.json b/packages/cli/test/cases/serve.default.ssr-static-export/package.json index 2dee3e768..0b8c2d82a 100644 --- a/packages/cli/test/cases/serve.default.ssr-static-export/package.json +++ b/packages/cli/test/cases/serve.default.ssr-static-export/package.json @@ -1,6 +1,6 @@ { "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/cli/test/cases/serve.default.ssr-static-export/serve.default.ssr-static-export.spec.js b/packages/cli/test/cases/serve.default.ssr-static-export/serve.default.ssr-static-export.spec.js index 26fa97766..117e6ed62 100644 --- a/packages/cli/test/cases/serve.default.ssr-static-export/serve.default.ssr-static-export.spec.js +++ b/packages/cli/test/cases/serve.default.ssr-static-export/serve.default.ssr-static-export.spec.js @@ -175,11 +175,10 @@ describe('Serve Greenwood With: ', function() { expect(styles.length).to.equal(1); }); - // TODO clean up lit-polyfill as part of https://github.com/ProjectEvergreen/greenwood/issues/728 it('should have four script tags', function() { const scripts = Array.from(dom.window.document.querySelectorAll('head script')).filter(tag => !tag.getAttribute('data-gwd')); - expect(scripts.length).to.equal(4); + expect(scripts.length).to.equal(3); }); it('should have expected SSR content from the non module script tag', function() { diff --git a/packages/plugin-graphql/test/cases/query-children/package.json b/packages/plugin-graphql/test/cases/query-children/package.json index 9b235502e..225becaa2 100644 --- a/packages/plugin-graphql/test/cases/query-children/package.json +++ b/packages/plugin-graphql/test/cases/query-children/package.json @@ -2,6 +2,6 @@ "name": "plugin-graphql-test-children-query", "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-children/query-children.spec.js b/packages/plugin-graphql/test/cases/query-children/query-children.spec.js index 65df87110..20c5793f8 100644 --- a/packages/plugin-graphql/test/cases/query-children/query-children.spec.js +++ b/packages/plugin-graphql/test/cases/query-children/query-children.spec.js @@ -77,6 +77,10 @@ describe('Build Greenwood With: ', function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -126,6 +130,7 @@ describe('Build Greenwood With: ', function() { ...greenwoodGraphqlQueryLibs, ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, diff --git a/packages/plugin-graphql/test/cases/query-custom-frontmatter/package.json b/packages/plugin-graphql/test/cases/query-custom-frontmatter/package.json index 83511be89..e9e9ceab1 100644 --- a/packages/plugin-graphql/test/cases/query-custom-frontmatter/package.json +++ b/packages/plugin-graphql/test/cases/query-custom-frontmatter/package.json @@ -2,6 +2,6 @@ "name": "plugin-graphql-test-query-custom-frontmatter", "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-custom-frontmatter/query-custom-frontmatter.spec.js b/packages/plugin-graphql/test/cases/query-custom-frontmatter/query-custom-frontmatter.spec.js index c4a3a620e..967f4de86 100644 --- a/packages/plugin-graphql/test/cases/query-custom-frontmatter/query-custom-frontmatter.spec.js +++ b/packages/plugin-graphql/test/cases/query-custom-frontmatter/query-custom-frontmatter.spec.js @@ -79,6 +79,10 @@ describe('Build Greenwood With: ', function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -128,6 +132,7 @@ describe('Build Greenwood With: ', function() { ...greenwoodGraphqlQueryLibs, ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, diff --git a/packages/plugin-graphql/test/cases/query-graph/package.json b/packages/plugin-graphql/test/cases/query-graph/package.json index 5a64a7a74..27178da74 100644 --- a/packages/plugin-graphql/test/cases/query-graph/package.json +++ b/packages/plugin-graphql/test/cases/query-graph/package.json @@ -2,6 +2,6 @@ "name": "plugin-graphql-test-graph-query", "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-graph/query-graph.spec.js b/packages/plugin-graphql/test/cases/query-graph/query-graph.spec.js index 43d20a5d0..11209a801 100644 --- a/packages/plugin-graphql/test/cases/query-graph/query-graph.spec.js +++ b/packages/plugin-graphql/test/cases/query-graph/query-graph.spec.js @@ -75,6 +75,10 @@ describe('Build Greenwood With: ', function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -124,6 +128,7 @@ describe('Build Greenwood With: ', function() { ...greenwoodGraphqlQueryLibs, ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, diff --git a/packages/plugin-graphql/test/cases/query-menu/package.json b/packages/plugin-graphql/test/cases/query-menu/package.json index cf01e2bba..3d07f5b69 100644 --- a/packages/plugin-graphql/test/cases/query-menu/package.json +++ b/packages/plugin-graphql/test/cases/query-menu/package.json @@ -2,6 +2,6 @@ "name": "plugin-graphql-test-menu-query", "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-graphql/test/cases/query-menu/query-menu.spec.js b/packages/plugin-graphql/test/cases/query-menu/query-menu.spec.js index ffe69c7f6..0d3df4ca6 100644 --- a/packages/plugin-graphql/test/cases/query-menu/query-menu.spec.js +++ b/packages/plugin-graphql/test/cases/query-menu/query-menu.spec.js @@ -77,6 +77,10 @@ describe('Build Greenwood With: ', async function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -126,6 +130,7 @@ describe('Build Greenwood With: ', async function() { ...greenwoodGraphqlQueryLibs, ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, diff --git a/packages/plugin-import-jsx/package.json b/packages/plugin-import-jsx/package.json index f9f4e08d5..382bddd52 100644 --- a/packages/plugin-import-jsx/package.json +++ b/packages/plugin-import-jsx/package.json @@ -27,7 +27,7 @@ "@greenwood/cli": "^0.28.0-alpha.4" }, "dependencies": { - "wc-compiler": "~0.11.0" + "wc-compiler": "~0.12.0" }, "devDependencies": { "@greenwood/cli": "^0.29.2" diff --git a/packages/plugin-polyfills/test/cases/lit/lit.spec.js b/packages/plugin-polyfills/test/cases/lit/lit.spec.js index 13f39990c..2ba1855f5 100644 --- a/packages/plugin-polyfills/test/cases/lit/lit.spec.js +++ b/packages/plugin-polyfills/test/cases/lit/lit.spec.js @@ -139,15 +139,13 @@ describe('Build Greenwood With: ', function() { dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, 'index.html')); }); - // TODO need to reconcile how this lit polyfilling is working since the CLI already adds it? - // related to https://github.com/ProjectEvergreen/greenwood/issues/728 it('should have one <script> tag for lit polyfills loaded in the <head> tag', function() { const scriptTags = dom.window.document.querySelectorAll('head > script'); const polyfillScriptTags = Array.prototype.slice.call(scriptTags).filter(script => { return script.src.indexOf('polyfill-support') >= 0; }); - expect(polyfillScriptTags.length).to.be.equal(2); + expect(polyfillScriptTags.length).to.be.equal(1); }); it('should have the expected lit polyfill files in the output directory', function() { diff --git a/packages/plugin-polyfills/test/cases/lit/package.json b/packages/plugin-polyfills/test/cases/lit/package.json index a18b66ac7..f1dc1522d 100644 --- a/packages/plugin-polyfills/test/cases/lit/package.json +++ b/packages/plugin-polyfills/test/cases/lit/package.json @@ -2,6 +2,6 @@ "name": "plugin-polyfills-lit-spec", "type": "module", "dependencies": { - "lit": "^2.0.0" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-renderer-lit/README.md b/packages/plugin-renderer-lit/README.md index 7fa2b6f2e..e5928e9d1 100644 --- a/packages/plugin-renderer-lit/README.md +++ b/packages/plugin-renderer-lit/README.md @@ -2,7 +2,7 @@ ## Overview -A Greenwood plugin for using [**Lit**'s SSR capabilities](https://github.com/lit/lit/tree/main/packages/labs/ssr) as a custom server-side renderer. Although support is experimental at this time, this plugin also gives the ability to statically render entire pages and templates (instead of puppeteer) to output completely static sites. +A Greenwood plugin for using [**Lit**'s SSR capabilities](https://github.com/lit/lit/tree/main/packages/labs/ssr) as a custom server-side renderer. Although support is experimental at this time, this plugin also gives the ability to statically render entire pages and templates to output completely static sites. _We are still actively working on SSR features and enhancements for Greenwood [as part of our 1.0 release](https://github.com/ProjectEvergreen/greenwood/issues?q=is%3Aissue+is%3Aopen+label%3Assr+milestone%3A1.0) so please feel free to test it out and report your feedback._ 🙏 @@ -11,7 +11,7 @@ _We are still actively working on SSR features and enhancements for Greenwood [a ## Prerequisite -This packages depends on the Lit package as a `peerDependency`. This means you must have Lit already installed in your project. You can install anything following the `2.x` release line. +This packages depends on the Lit package as a `peerDependency`. This means you must have Lit already installed in your project. You can install anything following the `3.x` release line. ```sh # npm @@ -33,7 +33,18 @@ npm install @greenwood/plugin-renderer-lit --save-dev yarn add @greenwood/plugin-renderer-lit --dev ``` +## Caveats + +1. Please familiarize yourself with some of the [caveats](https://lit.dev/docs/ssr/overview/#library-status) called out in the Lit docs, like: + - Lit SSR [**only** renders into declarative shadow roots](https://github.com/lit/lit/issues/3080#issuecomment-1165158794), so you will have to keep browser support and polyfill usage in mind. + - At this time, `LitElement` does not support `async` work. You can follow along with this issue [in the Lit repo](https://github.com/lit/lit/issues/2469). +1. Lit only supports templates on the server side for HTML only generated content, thus Greenwood's `getBody` API must be used. We would love for [server only components](https://github.com/lit/lit/issues/2469#issuecomment-1759583861) to be a thing though! +1. Full hydration support is not available yet. See [this Greenwood issue](https://github.com/ProjectEvergreen/greenwood/issues/880) to follow along when it will land + +> See [this repo](https://github.com/thescientist13/greenwood-lit-ssr) for a full demo of isomorphic Lit SSR with SSR pages and API routes deployed to Vercel serverless functions. + ## Usage + Add this plugin to your _greenwood.config.js_. ```javascript @@ -48,48 +59,33 @@ export default { } ``` -Now, you can write some [SSR routes](/docs/server-rendering/) using Lit including all the [available APIs](docs/server-rendering/#api). The below example uses the standard [SimpleGreeting](https://lit.dev/playground/) component from the Lit docs by also using a LitElement as the `default export`! -```js -import { html, LitElement } from 'lit'; -import './path/to/greeting.js'; - -export default class ArtistsPage extends LitElement { +Now, you can author [SSR pages](/docs/server-rendering/) using Lit templates and components using Greenwood's [`getBody` API](https://www.greenwoodjs.io/docs/server-rendering/#usage). The below is an example of generating a template of LitElement based `<app-card>` web components. - constructor() { - super(); - this.artists = [{ /* ... */ }]; - } - - render() { - const { artists } = this; - - return html` - ${ - artists.map((artist) => { - const { id, name, imageUrl } = artist; - - return html` - <a href="/artists/${id}" target="_blank"> - <simple-greeting .name="${name}"></simple-greeting> - </a> - - <img src="${imageUrl}" loading="lazy"/> - - <br/> - `; - }) - } - `; - } +```js +// src/pages/products.js +import { html } from 'lit'; +import '../components/card.js'; + +export async function getBody() { + const products = await getProducts(); + + return html` + ${ + products.map((product, idx) => { + const { title, thumbnail } = product; + + return html` + <app-card + title="${idx + 1}) ${title}" + thumbnail="${thumbnail}" + ></app-card> + `; + }) + } + `; } - -// for now these are needed for the Lit specific implementations -customElements.define('artists-page', ArtistsPage); -export const tagName = 'artists-page'; ``` -> _By default, this plugin sets `isolation` mode to `true` for all SSR pages. See the [isolation configuration](https://www.greenwoodjs.io/docs/configuration/#isolation) docs for more information._ - ## Caveats There are a few considerations to take into account when using a `LitElement` as your page component: @@ -97,11 +93,29 @@ There are a few considerations to take into account when using a `LitElement` as - Depending on your use case, SSR bundling may break due to bundle chunking and code splitting by Rollup, which we are [hoping to correct ASAP](https://github.com/ProjectEvergreen/greenwood/issues/1118). - At this time, `LitElement` does [not support `async` work](https://lit.dev/docs/ssr/overview/#library-status) which makes data fetching in pages a bit of challenge. You can follow along with this issue [in the Lit repo](https://github.com/lit/lit/issues/2469). -> _You can see a work (in progress) demo of using Lit SSR (with Serverless!) [here](https://github.com/thescientist13/greenwood-demo-adapter-vercel-lit/)._ - ## Options -### Prerender (experimental) +### Isolation Mode + +By default, this plugin sets `isolation` mode to `true` for all SSR pages. If you want to override this, just export an `isolation` const. + +```js +// src/pages/products.js +export const isolation = false; +``` + +> _See the [isolation configuration](https://www.greenwoodjs.io/docs/configuration/#isolation) docs for more information._ + +### Hydration + +In order for server-rendered components to become interactive on the client side, Lit's [client-side hydration script](https://lit.dev/docs/ssr/client-usage/#loading-@lit-labsssr-clientlit-element-hydrate-support.js) must be included on the page. This setting is `true` by default, but if you want to turn it off, you can `export` the **hydration** option from your page with a value of `false`. + +```js +// src/pages/products.js +export const hydration = false; // disable Lit hydration scripts for this page +``` + +### Prerender The plugin provides a setting that can be used to override Greenwood's [default _prerender_](/docs/configuration/#prerender) implementation which uses [WCC](https://github.com/ProjectEvergreen/wcc), to use Lit instead. diff --git a/packages/plugin-renderer-lit/package.json b/packages/plugin-renderer-lit/package.json index 10f0f45d3..57c1c2dad 100644 --- a/packages/plugin-renderer-lit/package.json +++ b/packages/plugin-renderer-lit/package.json @@ -25,13 +25,14 @@ }, "peerDependencies": { "@greenwood/cli": "^0.22.1", - "lit": "^2.1.1" + "lit": "^3.1.0" }, "dependencies": { - "@lit-labs/ssr": "^2.0.1" + "@lit-labs/ssr": "^3.2.0", + "@lit-labs/ssr-client": "^1.1.6" }, "devDependencies": { "@greenwood/cli": "^0.29.2", - "lit": "^2.1.1" + "lit": "^3.1.0" } } diff --git a/packages/plugin-renderer-lit/src/execute-route-module.js b/packages/plugin-renderer-lit/src/execute-route-module.js index 10a7d0149..4ef510635 100644 --- a/packages/plugin-renderer-lit/src/execute-route-module.js +++ b/packages/plugin-renderer-lit/src/execute-route-module.js @@ -1,30 +1,15 @@ -// this needs to come first -import { render } from '@lit-labs/ssr/lib/render-with-global-dom-shim.js'; -import { Buffer } from 'buffer'; +import { render } from '@lit-labs/ssr'; +import { collectResult } from '@lit-labs/ssr/lib/render-result.js'; import { html } from 'lit'; import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; -import { Readable } from 'stream'; - -async function streamToString (stream) { - const chunks = []; - - for await (let chunk of stream) { - chunks.push(Buffer.from(chunk)); - } - - return Buffer.concat(chunks).toString('utf-8'); -} - -async function getTemplateResultString(template) { - return await streamToString(Readable.from(render(template))); -} async function executeRouteModule({ moduleUrl, compilation, page, prerender, htmlContents, scripts }) { const data = { template: null, body: null, frontmatter: null, - html: null + html: null, + hydration: false }; // prerender static content @@ -35,10 +20,10 @@ async function executeRouteModule({ moduleUrl, compilation, page, prerender, htm const templateResult = html`${unsafeHTML(htmlContents)}`; - data.html = await getTemplateResultString(templateResult); + data.html = await collectResult(render(templateResult)); } else { const module = await import(moduleUrl).then(module => module); - const { getTemplate = null, getBody = null, getFrontmatter = null, isolation = true } = module; + const { getTemplate = null, getBody = null, getFrontmatter = null, isolation = true, hydration = true } = module; // TODO cant we get these from just pulling from the file during the graph phase? // https://github.com/ProjectEvergreen/greenwood/issues/991 @@ -46,23 +31,20 @@ async function executeRouteModule({ moduleUrl, compilation, page, prerender, htm data.isolation = true; } - if (module.default && module.tagName) { - const { tagName } = module; - const templateResult = html` - ${unsafeHTML(`<${tagName}></${tagName}>`)} - `; + if (hydration) { + data.hydration = true; + } - data.body = await getTemplateResultString(templateResult); - } else if (getBody) { - const templateResult = await getBody(compilation, page); + if (getBody) { + const templateResult = await getBody(compilation, page, data.pageData); - data.body = await getTemplateResultString(templateResult); + data.body = await collectResult(render(templateResult)); } if (getTemplate) { const templateResult = await getTemplate(compilation, page); - data.template = await getTemplateResultString(templateResult); + data.template = await collectResult(render(templateResult)); } if (getFrontmatter) { diff --git a/packages/plugin-renderer-lit/src/index.js b/packages/plugin-renderer-lit/src/index.js index e4e190be0..4f33502bd 100755 --- a/packages/plugin-renderer-lit/src/index.js +++ b/packages/plugin-renderer-lit/src/index.js @@ -1,14 +1,51 @@ +import { ResourceInterface } from '@greenwood/cli/src/lib/resource-interface.js'; + +class LitHydrationResource extends ResourceInterface { + constructor(compilation, options) { + super(compilation, options); + } + + async shouldIntercept(url) { + const { pathname } = url; + const matchingRoute = this.compilation.graph.find((node) => node.route === pathname) || {}; + + return matchingRoute.isSSR && matchingRoute.hydration; + } + + async intercept(url, request, response) { + let body = await response.text(); + + // TODO would be nice not have to manually set module-shim + // when we drop support for import-map shim - https://github.com/ProjectEvergreen/greenwood/pull/1115 + const type = process.env.__GWD_COMMAND__ === 'develop' // eslint-disable-line no-underscore-dangle + ? 'module-shim' + : 'module'; + + // this needs to come first before any userland code + body = body.replace('<head>', ` + <head> + <script type="${type}" src="/node_modules/@lit-labs/ssr-client/lit-element-hydrate-support.js"></script> + `); + + return new Response(body); + } +} + const greenwoodPluginRendererLit = (options = {}) => { - return { + return [{ type: 'renderer', - name: 'plugin-renderer-lit', + name: 'plugin-renderer-lit:renderer', provider: () => { return { executeModuleUrl: new URL('./execute-route-module.js', import.meta.url), prerender: options.prerender }; } - }; + }, { + type: 'resource', + name: 'plugin-renderer-lit:resource', + provider: (compilation, options) => new LitHydrationResource(compilation, options) + }]; }; export { diff --git a/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/build.prerender.getting-started.spec.js b/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/build.prerender.getting-started.spec.js index adced6d2c..34ac418e6 100644 --- a/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/build.prerender.getting-started.spec.js +++ b/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/build.prerender.getting-started.spec.js @@ -96,6 +96,10 @@ describe('Build Greenwood With Custom Lit Renderer for SSG prerendering: ', func `${process.cwd()}/node_modules/lit-html/*.js`, `${outputPath}/node_modules/lit-html/` ); + const litHtmlNode = await getDependencyFiles( + `${process.cwd()}/node_modules/lit-html/node/*.js`, + `${outputPath}/node_modules/lit-html/node/` + ); const litHtmlPackageJson = await getDependencyFiles( `${process.cwd()}/node_modules/lit-html/package.json`, `${outputPath}/node_modules/lit-html/` @@ -116,6 +120,11 @@ describe('Build Greenwood With Custom Lit Renderer for SSG prerendering: ', func `${process.cwd()}/node_modules/@lit/reactive-element/package.json`, `${outputPath}/node_modules/@lit/reactive-element/` ); + const litReactiveElementNode = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit/reactive-element/node/*.js`, + `${outputPath}/node_modules/@lit/reactive-element/node/` + ); + // lit-html/node/directives/unsafe-html.js const litHtmlSourceMap = await getDependencyFiles( `${process.cwd()}/node_modules/lit-html/lit-html.js.map`, `${outputPath}/node_modules/lit-html/` @@ -136,11 +145,13 @@ describe('Build Greenwood With Custom Lit Renderer for SSG prerendering: ', func ...litElementDecorators, ...litHtmlPackageJson, ...litHtml, + ...litHtmlNode, ...litHtmlDirectives, ...trustedTypes, ...litReactiveElement, ...litReactiveElementDecorators, ...litReactiveElementPackageJson, + ...litReactiveElementNode, ...litHtmlSourceMap ]); runner.runCommand(cliPath, 'build'); diff --git a/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/package.json b/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/package.json index fe421bf5b..c5116ac18 100644 --- a/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/package.json +++ b/packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/package.json @@ -2,6 +2,6 @@ "name": "plugin-prerender-lit-build-prerender-getting-started", "type": "module", "dependencies": { - "lit": "^2.1.1" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-renderer-lit/test/cases/serve.default/package.json b/packages/plugin-renderer-lit/test/cases/serve.default/package.json index 15b06e848..bacd51937 100644 --- a/packages/plugin-renderer-lit/test/cases/serve.default/package.json +++ b/packages/plugin-renderer-lit/test/cases/serve.default/package.json @@ -2,6 +2,6 @@ "name": "plugin-prerender-lit-build-default", "type": "module", "dependencies": { - "lit": "^2.1.1" + "lit": "^3.1.0" } } \ No newline at end of file diff --git a/packages/plugin-renderer-lit/test/cases/serve.default/serve.default.spec.js b/packages/plugin-renderer-lit/test/cases/serve.default/serve.default.spec.js index 2f776bc7c..5219f773b 100644 --- a/packages/plugin-renderer-lit/test/cases/serve.default/serve.default.spec.js +++ b/packages/plugin-renderer-lit/test/cases/serve.default/serve.default.spec.js @@ -13,8 +13,10 @@ * * User Workspace * src/ + * api/ + * search.js * components/ - * counter.js + * card.js * footer.js * greeting.js * pages/ @@ -82,6 +84,14 @@ describe('Serve Greenwood With: ', function() { `${process.cwd()}/node_modules/lit-html/*.js`, `${outputPath}/node_modules/lit-html/` ); + const litHtmlNode = await getDependencyFiles( + `${process.cwd()}/node_modules/lit-html/node/*.js`, + `${outputPath}/node_modules/lit-html/node/` + ); + const litHtmlNodeDirectives = await getDependencyFiles( + `${process.cwd()}/node_modules/lit-html/node/directives/*.js`, + `${outputPath}/node_modules/lit-html/node/directives/` + ); const litHtmlPackageJson = await getDependencyFiles( `${process.cwd()}/node_modules/lit-html/package.json`, `${outputPath}/node_modules/lit-html/` @@ -100,6 +110,10 @@ describe('Serve Greenwood With: ', function() { `${process.cwd()}/node_modules/@lit/reactive-element/*.js`, `${outputPath}/node_modules/@lit/reactive-element/` ); + const litReactiveElementNode = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit/reactive-element/node/*.js`, + `${outputPath}/node_modules/@lit/reactive-element/node/` + ); const litReactiveElementDecorators = await getDependencyFiles( `${process.cwd()}/node_modules/@lit/reactive-element/decorators/*.js`, `${outputPath}/node_modules/@lit/reactive-element/decorators/` @@ -108,6 +122,14 @@ describe('Serve Greenwood With: ', function() { `${process.cwd()}/node_modules/@lit/reactive-element/package.json`, `${outputPath}/node_modules/@lit/reactive-element/` ); + const litSsrElementHydrationSupport = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-client/lit-element-hydrate-support.js`, + `${outputPath}/node_modules/@lit-labs/ssr-client/` + ); + const litSsrHtmlHydrationSupport = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-client/lib/*.js`, + `${outputPath}/node_modules/@lit-labs/ssr-client/lib/` + ); runner.setup(outputPath, [ ...getSetupFiles(outputPath), @@ -120,11 +142,16 @@ describe('Serve Greenwood With: ', function() { ...litElementDecorators, ...litHtmlPackageJson, ...litHtml, + ...litHtmlNode, ...litHtmlDirectives, + ...litHtmlNodeDirectives, ...trustedTypes, ...litReactiveElement, + ...litReactiveElementNode, ...litReactiveElementDecorators, - ...litReactiveElementPackageJson + ...litReactiveElementPackageJson, + ...litSsrElementHydrationSupport, + ...litSsrHtmlHydrationSupport ]); runner.runCommand(cliPath, 'build'); @@ -160,7 +187,7 @@ describe('Serve Greenwood With: ', function() { usersPageDom = new JSDOM(usersPageHtml); }); - describe('Serve command with HTML route response using getBody, getTemplate and getFrontmatter', function() { + describe('Serve command with HTML route response using getBody, getTemplate and getFrontmatter for the artists page', function() { it('should return a 200 status', function() { expect(response.status).to.equal(200); @@ -184,15 +211,6 @@ describe('Serve Greenwood With: ', function() { expect(styles.length).to.equal(1); }); - // TODO this should be managed via a plugin, not in core - // https://github.com/ProjectEvergreen/greenwood/issues/728 - it('should have one <script> tag in the <head> for lit polyfills', function() { - const scripts = Array.from(dom.window.document.querySelectorAll('head > script')).filter(tag => !tag.getAttribute('data-gwd')); - - expect(scripts.length).to.equal(1); - expect(scripts[0].getAttribute('src').startsWith('/polyfill-support')).to.equal(true); - }); - it('should have the expected number of <tr> tags of content', function() { const rows = dom.window.document.querySelectorAll('body > table tr'); @@ -239,9 +257,16 @@ describe('Serve Greenwood With: ', function() { expect(aboutPageGraphData.data.author).to.equal('Project Evergreen'); expect(aboutPageGraphData.data.date).to.equal('01-01-2021'); }); + + it('should not have the expected lit hydration script in the <head>', function() { + const scripts = Array.from(dom.window.document.querySelectorAll('head script')) + .filter((script) => script.getAttribute('src')?.indexOf('lit-element-hydrate-support') >= 0); + + expect(scripts.length).to.equal(0); + }); }); - describe('Serve command with HTML route response using LitElement as default export', function() { + describe('Serve command with HTML route response using LitElement as a getPage export with an <app-footer> component for the users page', function() { it('the response body should be valid HTML from JSDOM', function(done) { expect(usersPageDom).to.not.be.undefined; done(); @@ -258,6 +283,58 @@ describe('Serve Greenwood With: ', function() { it('should have the expected <app-footer> content in the <body>', function() { expect(usersPageHtml).to.contain('<footer class="footer">'); }); + + it('should have the expected lit hydration script in the <head>', function() { + const scripts = Array.from(usersPageDom.window.document.querySelectorAll('head script')) + .filter((script) => script.getAttribute('src')?.indexOf('lit-element-hydrate-support') >= 0); + + expect(scripts.length).to.equal(1); + }); + }); + + describe('Serve command with API route server rendering LitElement <app-card> components as an HTML response', function() { + const term = 'Analog'; + let resp; + let html; + let dom; + + before(async function() { + resp = await fetch(`${hostname}/api/search`, { + method: 'POST', + body: new URLSearchParams({ term }).toString(), + headers: new Headers({ + 'content-type': 'application/x-www-form-urlencoded' + }) + }); + html = await resp.text(); + dom = new JSDOM(html); + }); + + it('should have a response status of 200', function(done) { + expect(resp.status).to.equal(200); + + done(); + }); + + it('should have a Content-Type header of text/html', function(done) { + const type = response.headers.get('Content-Type'); + + expect(type).to.equal('text/html'); + + done(); + }); + + it('should have the expected number of <app-card> components for a single search result', function(done) { + const cards = dom.window.document.querySelectorAll('app-card template[shadowrootmode="open"]'); + const cardDom = new JSDOM(cards[0].innerHTML); + + expect(cards.length).to.equal(1); + // TODO this should be real data (see issue with static in card.js) + expect(cardDom.window.document.querySelectorAll('h3')[0].textContent).to.equal('Foo'); + expect(cardDom.window.document.querySelectorAll('img')[0].getAttribute('src')).to.equal('bar.png'); + + done(); + }); }); }); diff --git a/packages/plugin-renderer-lit/test/cases/serve.default/src/api/search.js b/packages/plugin-renderer-lit/test/cases/serve.default/src/api/search.js new file mode 100644 index 000000000..3000cc333 --- /dev/null +++ b/packages/plugin-renderer-lit/test/cases/serve.default/src/api/search.js @@ -0,0 +1,41 @@ +import { render } from '@lit-labs/ssr'; +import { collectResultSync } from '@lit-labs/ssr/lib/render-result.js'; +import fs from 'fs'; +import { html } from 'lit'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import '../components/card.js'; + +export async function handler(request) { + const artists = JSON.parse(fs.readFileSync(new URL('../../artists.json', import.meta.url), 'utf-8')); + const formData = await request.formData(); + const term = formData.has('term') ? formData.get('term') : ''; + const filteredArtists = artists.filter((artist) => { + return term !== '' && artist.name.toLowerCase().includes(term.toLowerCase()); + }); + let body = ''; + + if (filteredArtists.length === 0) { + body = 'No results found.'; + } else { + body = collectResultSync(render(html` + ${ + unsafeHTML(filteredArtists.map((item, idx) => { + const { name, imageUrl } = item; + + return ` + <app-card + title="${idx + 1}) ${name}" + thumbnail="${imageUrl}" + ></app-card> + `; + }).join('')) + } + `)); + } + + return new Response(body, { + headers: new Headers({ + 'Content-Type': 'text/html' + }) + }); +} \ No newline at end of file diff --git a/packages/plugin-renderer-lit/test/cases/serve.default/src/components/card.js b/packages/plugin-renderer-lit/test/cases/serve.default/src/components/card.js new file mode 100644 index 000000000..32fb3e205 --- /dev/null +++ b/packages/plugin-renderer-lit/test/cases/serve.default/src/components/card.js @@ -0,0 +1,82 @@ +import { LitElement, html } from 'lit'; + +export default class Card extends LitElement { + // TODO we have a clash on acorn version? + // or this issue - https://github.com/ProjectEvergreen/greenwood/issues/1183 + // static properties = { + // title: '', + // thumbnail: '' + // }; + // static styles = css` + // div { + // display: flex; + // flex-direction: column; + // align-items: center; + // gap: 0.5rem; + // border: 1px solid #818181; + // width: fit-content; + // border-radius: 10px; + // padding: 2rem 1rem; + // height: 680px; + // justify-content: space-between; + // background-color: #fff; + // overflow-x: hidden; + // } + // button { + // background: var(--color-accent); + // color: var(--color-white); + // padding: 1rem 2rem; + // border: 0; + // font-size: 1rem; + // border-radius: 5px; + // cursor: pointer; + // } + // img { + // max-width: 500px; + // min-width: 500px; + // width: 100%; + // } + // h3 { + // font-size: 1.85rem; + // } + + // @media(max-width: 768px) { + // img { + // max-width: 300px; + // min-width: 300px; + // } + // div { + // height: 500px; + // } + // } + // `; + + constructor() { + super(); + + this.title; + this.thumbnail; + } + + selectItem() { + alert(`selected item is => ${this.title}!`); + } + + render() { + const { title = 'Foo', thumbnail = 'bar.png' } = this; + + if (!title && !thumbnail) { + return; + } + + return html` + <div> + <h3>${title}</h3> + <img src="${thumbnail}" alt="${title}" loading="lazy" width="100%"> + <button @click="${this.selectItem}">View Item Details</button> + </div> + `; + } +} + +customElements.define('app-card', Card); \ No newline at end of file diff --git a/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/artists.js b/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/artists.js index f6a90b6f2..58596191f 100644 --- a/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/artists.js +++ b/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/artists.js @@ -77,6 +77,7 @@ async function getFrontmatter(compilation, { route }) { }; } +export const hydration = false; export { getTemplate, getBody, diff --git a/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/users.js b/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/users.js index 71a9515e5..47b662b67 100644 --- a/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/users.js +++ b/packages/plugin-renderer-lit/test/cases/serve.default/src/pages/users.js @@ -1,25 +1,15 @@ import fs from 'fs'; -import { html, LitElement } from 'lit'; +import { html } from 'lit'; import '../components/footer.js'; -class UsersComponent extends LitElement { - - constructor() { - super(); - this.users = JSON.parse(fs.readFileSync(new URL('../../artists.json', import.meta.url), 'utf-8')); - } - - render() { - return html` - <h1>Users Page</h1> - <div id="users">${this.users.length}</div> - <app-footer></app-footer> - `; - } -} +export const isolation = false; -customElements.define('app-users', UsersComponent); +export async function getBody() { + const users = JSON.parse(fs.readFileSync(new URL('../../artists.json', import.meta.url), 'utf-8')); -export const isolation = false; -export const tagName = 'app-users'; -export default UsersComponent; \ No newline at end of file + return html` + <h1>Users Page</h1> + <div id="users">${users.length}</div> + <app-footer></app-footer> + `; +} \ No newline at end of file diff --git a/packages/plugin-renderer-puppeteer/test/cases/build.default/build.default.spec.js b/packages/plugin-renderer-puppeteer/test/cases/build.default/build.default.spec.js index c4449df2e..e6876fd31 100644 --- a/packages/plugin-renderer-puppeteer/test/cases/build.default/build.default.spec.js +++ b/packages/plugin-renderer-puppeteer/test/cases/build.default/build.default.spec.js @@ -68,6 +68,10 @@ describe('Build Greenwood With: ', function() { `${process.cwd()}/node_modules/lit/package.json`, `${outputPath}/node_modules/lit/` ); + const litSsrPackageJson = await getDependencyFiles( + `${process.cwd()}/node_modules/@lit-labs/ssr-dom-shim/package.json`, + `${outputPath}/node_modules/@lit-labs/ssr-dom-shim/` + ); const litElement = await getDependencyFiles( `${process.cwd()}/node_modules/lit-element/*.js`, `${outputPath}/node_modules/lit-element/` @@ -187,6 +191,7 @@ describe('Build Greenwood With: ', function() { ...symbolLibsPackageJson, ...lit, ...litPackageJson, + ...litSsrPackageJson, ...litDirectives, ...litDecorators, ...litElementPackageJson, @@ -298,7 +303,7 @@ describe('Build Greenwood With: ', function() { expect(inlineScriptTag.textContent.replace('\n', '')).to // eslint-disable-next-line max-len - .contain('import"/lit-element.76be1f9d.js";document.getElementsByClassName("output-script-inline")[0].innerHTML="script tag module inline";//# sourceMappingURL=1635690801.3e40c728.js.map'); + .contain('import"/lit-element.6eb76f27.js";document.getElementsByClassName("output-script-inline")[0].innerHTML="script tag module inline";//# sourceMappingURL=1635690801.4bc08000.js.map'); }); it('should have prerendered content from <app-header> component', function() { diff --git a/packages/plugin-renderer-puppeteer/test/cases/build.default/package.json b/packages/plugin-renderer-puppeteer/test/cases/build.default/package.json index 9348db6f7..42687993c 100644 --- a/packages/plugin-renderer-puppeteer/test/cases/build.default/package.json +++ b/packages/plugin-renderer-puppeteer/test/cases/build.default/package.json @@ -2,7 +2,7 @@ "name": "test-renderer-puppeteer", "type": "module", "dependencies": { - "lit": "^2.0.0", + "lit": "^3.1.0", "lodash-es": "^4.17.20", "prismjs": "^1.21.0", "pwa-helpers": "^0.9.1", diff --git a/packages/plugin-typescript/test/cases/options.extend-config/src/scripts/main.ts b/packages/plugin-typescript/test/cases/options.extend-config/src/scripts/main.ts index cddcb1a4e..b4e387822 100644 --- a/packages/plugin-typescript/test/cases/options.extend-config/src/scripts/main.ts +++ b/packages/plugin-typescript/test/cases/options.extend-config/src/scripts/main.ts @@ -1,4 +1,5 @@ -import { html, css, LitElement, customElement, property } from 'lit-element'; +import { html, css, LitElement } from 'lit-element'; +import { customElement, property } from 'lit/decorators.js'; import { TemplateResult } from 'lit-html'; @customElement('app-greeting') diff --git a/www/package.json b/www/package.json index fdc1da989..dd85efee1 100644 --- a/www/package.json +++ b/www/package.json @@ -10,7 +10,7 @@ "dependencies": { "@evergreen-wc/eve-button": "^0.1.1", "@evergreen-wc/eve-container": "^0.1.1", - "lit": "^2.1.1", + "lit": "^3.1.0", "prismjs": "^1.21.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 660a73a29..e09df1dad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2393,28 +2393,36 @@ "@lion/core" "0.19.0" singleton-manager "1.4.2" -"@lit-labs/ssr-client@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@lit-labs/ssr-client/-/ssr-client-1.0.0.tgz#9d5a437f575469023500b7eff3bd27632197f720" - integrity sha512-bYnX1uhE7oO/579xRoAdAHnngROQHj93bqCUqw/L4vvRyBWBIeeshoM3OjPX0DFdeJIvZy/1x29t9iaNvTB5bg== +"@lit-labs/ssr-client@^1.1.4", "@lit-labs/ssr-client@^1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-client/-/ssr-client-1.1.6.tgz#d7aa2d68b18317057e193d18a8d81a2e347004f5" + integrity sha512-MHOHSDGmlum66PP2a6ATLHHwTFvYl+s7R4NYBp8E1NqHDA5UEuEIA1o/E4NoDinc3Ow56yz9Cvh89DvFDif5Pg== dependencies: - "@lit/reactive-element" "^1.0.0" - lit "^2.0.0" - lit-html "^2.0.0" + "@lit/reactive-element" "^1.6.1 || ^2.0.0" + lit "^2.7.0 || ^3.0.0" + lit-html "^2.7.0 || ^3.0.0" -"@lit-labs/ssr@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@lit-labs/ssr/-/ssr-2.0.1.tgz#18e5aa000b9937aeaa4325998e98a6f1c1a90b13" - integrity sha512-WVBWmGj8NmuJLDu/Y812zsro4kzh03ZVzTTIinFlDIrSawZcPi8ZOCDIxtsXcNLYkYhmBNOsEb9nDtF9opdXnA== - dependencies: - "@lit-labs/ssr-client" "^1.0.0" - "@lit/reactive-element" "^1.1.0" - lit "^2.1.0" - lit-element "^3.1.0" - lit-html "^2.1.0" - node-fetch "^2.6.0" - parse5 "^6.0.1" - resolve "^1.10.1" +"@lit-labs/ssr-dom-shim@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz#d693d972974a354034454ec1317eb6afd0b00312" + integrity sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g== + +"@lit-labs/ssr@^3.2.0": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr/-/ssr-3.2.1.tgz#ee6230776387b02844c8d8d4a3084c9534f76898" + integrity sha512-y8LHFdRFYLXJ44kddCjeaKM/NVqcz1Z0TQHic7Siawxr07d4YZKYtghqnX1bbe2Oa8+qFW7NKFv54CIB7BzrZQ== + dependencies: + "@lit-labs/ssr-client" "^1.1.4" + "@lit-labs/ssr-dom-shim" "^1.1.2" + "@lit/reactive-element" "^1.6.1 || ^2.0.0" + "@parse5/tools" "^0.3.0" + "@types/node" "^16.0.0" + enhanced-resolve "^5.10.0" + lit "^3.1.0" + lit-element "^3.3.0 || ^4.0.0" + lit-html "^3.1.0" + node-fetch "^3.2.8" + parse5 "^7.1.1" "@lit/reactive-element@1.0.0-rc.4": version "1.0.0-rc.4" @@ -2426,10 +2434,12 @@ resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.0.0.tgz#7b6e6a85709cda0370c47e425ac2f3b553696a4b" integrity sha512-Kpgenb8UNFsKCsFhggiVvUkCbcFQSd6N8hffYEEGjz27/4rw3cTSsmP9t3q1EHOAsdum60Wo64HvuZDFpEwexA== -"@lit/reactive-element@^1.1.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.2.0.tgz#c62444a0e3d3f8d3a6875ad56f867279aa89fa88" - integrity sha512-7i/Fz8enAQ2AN5DyJ2i2AFERufjP6x1NjuHoNgDyJkjjHxEoo8kVyyHxu1A9YyeShlksjt5FvpvENBDuivQHLA== +"@lit/reactive-element@^1.6.1 || ^2.0.0", "@lit/reactive-element@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-2.0.3.tgz#29d7d4ee8d9b00804be957cc6937577eb4d3db63" + integrity sha512-e067EuTNNgOHm1tZcc0Ia7TCzD/9ZpoPegHKgesrGK6pSDRGkGDAQbYuQclqLPIoJ9eC8Kb9mYtGryWcM5AywA== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.1.2" "@ls-lint/ls-lint@^1.10.0": version "1.10.0" @@ -3600,6 +3610,13 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.1.tgz#3d745996b2bd11095b515515fd3d68d46092a02d" integrity sha512-n8Kur1/CZlYG32YCEj30CoUqA8R7UyDVZzoEU6SDP+13+kXDT2kFVu6MpcnEUTyGP3i058ID6Qjp5h6IJxdPPQ== +"@parse5/tools@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@parse5/tools/-/tools-0.3.0.tgz#4cac601408065a84c31a88431b02f9f69f92434a" + integrity sha512-zxRyTHkqb7WQMV8kTNBKWb1BeOFUKXBXTBWuxg9H9hfvQB3IwP6Iw2U75Ia5eyRxPNltmY7E8YAlz6zWwUnjKg== + dependencies: + parse5 "^7.0.0" + "@pnpm/config.env-replace@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" @@ -3621,6 +3638,22 @@ "@pnpm/network.ca-file" "^1.0.1" config-chain "^1.1.11" +"@projectevergreen/acorn-jsx-esm@~0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@projectevergreen/acorn-jsx-esm/-/acorn-jsx-esm-0.1.0.tgz#9870be988907048b5b432425d6157b84f8e4fdef" + integrity sha512-ZBSkr0e2M4ylq74dTGHSkWI2dF3Mz8zwBLyzIXZMftecKDADcsCTj7bWltVgtdl8Rh4+bmY1jNWUw7AlSV/r7A== + +"@projectevergreen/escodegen-esm@~0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@projectevergreen/escodegen-esm/-/escodegen-esm-0.1.0.tgz#c9259d51178d4be948dd19e561ce5e2a16948a0f" + integrity sha512-LM9FFffsXPHiOFt78K3bgF8kO8Fx+qluAPy9jP3H4lvCFE+2nbwQM4cWdOpVik++rHf4pkDA7FxDPWWATyBABg== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -4089,6 +4122,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.54.tgz#a737488631aca3ec7bd9f6229d77f1079e444793" integrity sha512-c8Lm7+hXdSPmWH4B9z/P/xIXhFK3mCQin4yCYMd2p1qpMG5AfgyJuYZ+3q2dT7qLiMMMGMd5dnkFpdqJARlvtQ== +"@types/node@^16.0.0": + version "16.18.76" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.76.tgz#deecdf6b71b9ef45ceda63fec7220ddf2354d7a1" + integrity sha512-/GsO2uv1Z6R42lBr59dtem56gVF/yHKQaScggwU+gLU6DXE25sDmOar4c4IfWb3h+X/7OYZznPOFk7oGF3jQSA== + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -4508,15 +4546,10 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.1, acorn@^8.0.5, acorn@^8.7.0: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== - -acorn@^8.4.1, acorn@^8.6.0, acorn@^8.9.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== +acorn@^8.0.1, acorn@^8.0.5, acorn@^8.4.1, acorn@^8.6.0, acorn@^8.7.0, acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== acorn@^8.8.2: version "8.11.2" @@ -7304,6 +7337,14 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +enhanced-resolve@^5.10.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -7319,6 +7360,11 @@ entities@^2.2.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@3.0.0, env-paths@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da" @@ -8931,7 +8977,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -graceful-fs@^4.1.3, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.3, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -9823,13 +9869,6 @@ is-core-module@^2.13.0, is-core-module@^2.5.0: dependencies: has "^1.0.3" -is-core-module@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -10770,25 +10809,19 @@ listr@0.14.3: p-map "^2.0.0" rxjs "^6.3.3" -lit-element@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.1.1.tgz#562d5ccbc8ba0c01d8ba4a0ac3576263167d2ccb" - integrity sha512-14ClnMAU8EXnzC+M2/KDd3SFmNUn1QUw1+GxWkEMwGV3iaH8ObunMlO5svzvaWlkSV0WlxJCi40NGnDVJ2XZKQ== - dependencies: - "@lit/reactive-element" "^1.1.0" - lit-html "^2.1.0" - -lit-html@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.0.0.tgz#ba6779269c382e66d7403a96ed99516ccc3d658b" - integrity sha512-tJsCapCmc0vtLj6harqd6HfCxnlt/RSkgowtz4SC9dFE3nSL38Tb33I5HMDiyJsRjQZRTgpVsahrnDrR9wg27w== +"lit-element@^3.3.0 || ^4.0.0", lit-element@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.0.3.tgz#18239840a7c1a6a6e09c6ed3b5cd3db0512ebf15" + integrity sha512-2vhidmC7gGLfnVx41P8UZpzyS0Fb8wYhS5RCm16cMW3oERO0Khd3EsKwtRpOnttuByI5rURjT2dfoA7NlInCNw== dependencies: - "@types/trusted-types" "^2.0.2" + "@lit-labs/ssr-dom-shim" "^1.1.2" + "@lit/reactive-element" "^2.0.0" + lit-html "^3.1.0" -lit-html@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.1.1.tgz#f4da485798a0d967514d31730d387350fafb79f7" - integrity sha512-E4BImK6lopAYanJpvcGaAG8kQFF1ccIulPu2BRNZI7acFB6i4ujjjsnaPVFT1j/4lD9r8GKih0Y8d7/LH8SeyQ== +"lit-html@^2.7.0 || ^3.0.0", lit-html@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.1.1.tgz#50c2e74a2074f85fc9816676ac11cf0c96f257c3" + integrity sha512-x/EwfGk2D/f4odSFM40hcGumzqoKv0/SUh6fBO+1Ragez81APrcAMPo1jIrCDd9Sn+Z4CT867HWKViByvkDZUA== dependencies: "@types/trusted-types" "^2.0.2" @@ -10799,14 +10832,14 @@ lit-redux-router@~0.20.0: dependencies: regexparam "^2.0.0" -lit@^2.0.0, lit@^2.0.0-rc.2, lit@^2.0.2, lit@^2.1.0, lit@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/lit/-/lit-2.1.1.tgz#65f43abca945988f696391f762c645ba51966b0b" - integrity sha512-yqDqf36IhXwOxIQSFqCMgpfvDCRdxLCLZl7m/+tO5C9W/OBHUj17qZpiMBT35v97QMVKcKEi1KZ3hZRyTwBNsQ== +lit@^2.0.0, lit@^2.0.0-rc.2, lit@^2.0.2, "lit@^2.7.0 || ^3.0.0", lit@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.1.tgz#49340c8875019a777cc83904f75a2bf7764617dc" + integrity sha512-hF1y4K58+Gqrz+aAPS0DNBwPqPrg6P04DuWK52eMkt/SM9Qe9keWLcFgRcEKOLuDlRZlDsDbNL37Vr7ew1VCuw== dependencies: - "@lit/reactive-element" "^1.1.0" - lit-element "^3.1.0" - lit-html "^2.1.0" + "@lit/reactive-element" "^2.0.0" + lit-element "^4.0.0" + lit-html "^3.1.0" livereload-js@^3.1.0: version "3.3.1" @@ -12117,14 +12150,14 @@ node-fetch@2.6.12, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.7, node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@2.6.7, node-fetch@^2.5.0, node-fetch@^2.6.1: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@^3.0.0, node-fetch@^3.1.1, node-fetch@^3.3.1: +node-fetch@^3.0.0, node-fetch@^3.1.1, node-fetch@^3.2.8, node-fetch@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== @@ -12988,6 +13021,13 @@ parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parse5@^7.0.0, parse5@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + parseurl@^1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -14560,15 +14600,6 @@ resolve@^1.10.0: dependencies: path-parse "^1.0.6" -resolve@^1.10.1: - version "1.21.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" - integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== - dependencies: - is-core-module "^2.8.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - resolve@^1.12.0, resolve@^1.14.2, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" @@ -15800,6 +15831,11 @@ tabtab@3.0.2: mkdirp "^0.5.1" untildify "^3.0.3" +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + tar-fs@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" @@ -16795,15 +16831,15 @@ wait-port@1.0.4: commander "^9.3.0" debug "^4.3.4" -wc-compiler@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/wc-compiler/-/wc-compiler-0.11.0.tgz#fc42d81f23eee0cc98d497aec574cf49c553ae03" - integrity sha512-2reo21bD1jbjqDKbN4rBZ07Om4riP58Llb8Wtc7H7s704Jm8t8yFMKVpNZh3S9/3GpkDZbwp6XKI2MmkYugafQ== +wc-compiler@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/wc-compiler/-/wc-compiler-0.12.0.tgz#f9d04b5bfca505f836487ce63040fdf30f1cea5b" + integrity sha512-eMgHEGhJGcyjSL9p6YIix0ReMViffhtabVEnNE1oRiNlNJL/Fd8e0GZ2gdWhIOV5ZvNMOocyAKFODKpg3CDMkg== dependencies: + "@projectevergreen/acorn-jsx-esm" "~0.1.0" + "@projectevergreen/escodegen-esm" "~0.1.0" acorn "^8.7.0" - acorn-jsx "^5.3.2" acorn-walk "^8.2.0" - escodegen "^2.0.0" parse5 "^6.0.1" wcwidth@^1.0.0, wcwidth@^1.0.1: