diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 0c06c5089..dce41cebc 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -1,14 +1,27 @@
+// need this custom parser configuration until ESLint natively supports import attributes
+// https://github.com/eslint/eslint/discussions/15305#discussioncomment-2508948
module.exports = {
- parser: '@typescript-eslint/parser',
+ parser: '@babel/eslint-parser',
parserOptions: {
- ecmaVersion: 2018,
- sourceType: 'module'
+ ecmaVersion: 2022,
+ sourceType: 'module',
+ requireConfigFile: false,
+ ecmaFeatures: {
+ jsx: true
+ },
+ babelOptions: {
+ plugins: [
+ '@babel/plugin-syntax-import-assertions'
+ ],
+ presets: ['@babel/preset-react']
+ }
},
plugins: [
- '@typescript-eslint',
'no-only-tests'
],
- extends: 'plugin:markdown/recommended',
+ // plugin does not seem to work well with custom parsers?
+ // https://github.com/eslint/eslint-plugin-markdown/discussions/221
+ // extends: 'plugin:markdown/recommended-legacy',
env: {
browser: true,
node: false
diff --git a/.github/workflows/ci-exp.yml b/.github/workflows/ci-loaders.yml
similarity index 89%
rename from .github/workflows/ci-exp.yml
rename to .github/workflows/ci-loaders.yml
index f4916828d..34c079cbd 100644
--- a/.github/workflows/ci-exp.yml
+++ b/.github/workflows/ci-loaders.yml
@@ -1,4 +1,4 @@
-name: Continuous Integration (Experimental)
+name: Continuous Integration (Loaders)
on: [pull_request]
@@ -25,4 +25,4 @@ jobs:
yarn install --frozen-lockfile && yarn lerna bootstrap
- name: Test
run: |
- yarn test:exp
\ No newline at end of file
+ yarn test:loaders
\ No newline at end of file
diff --git a/.github/workflows/ci-win-exp.yml b/.github/workflows/ci-win-loaders.yml
similarity index 85%
rename from .github/workflows/ci-win-exp.yml
rename to .github/workflows/ci-win-loaders.yml
index ffc7ef0fd..7e69f3873 100644
--- a/.github/workflows/ci-win-exp.yml
+++ b/.github/workflows/ci-win-loaders.yml
@@ -1,4 +1,4 @@
-name: Continuous Integration Windows (Experimental)
+name: Continuous Integration Windows (Loaders)
on: [pull_request]
@@ -22,4 +22,4 @@ jobs:
yarn install --frozen-lockfile --network-timeout 1000000 && yarn lerna bootstrap
- name: Test
run: |
- yarn test:exp:win
\ No newline at end of file
+ yarn test:loaders:win
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index eaa6b83a2..bd89ae68f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
.vscode/
coverage/
node_modules/
+packages/init/test/**/my-app
packages/**/test/**/yarn.lock
packages/**/test/**/package-lock.json
packages/**/test/**/netlify
diff --git a/.ls-lint.yml b/.ls-lint.yml
index 64ab822b4..ab2ad9cba 100644
--- a/.ls-lint.yml
+++ b/.ls-lint.yml
@@ -14,5 +14,6 @@ ls:
ignore:
- .git
- node_modules
+ - packages/plugin-babel/node_modules
- packages/init/node_modules
- packages/plugin-typescript/node_modules
\ No newline at end of file
diff --git a/.nvmrc b/.nvmrc
index 72c7744b3..23cc58a71 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-18.12.1
\ No newline at end of file
+18.20.0
\ No newline at end of file
diff --git a/greenwood.config.js b/greenwood.config.js
index 648fdc361..216952137 100644
--- a/greenwood.config.js
+++ b/greenwood.config.js
@@ -1,9 +1,8 @@
import { greenwoodPluginGraphQL } from '@greenwood/plugin-graphql';
import { greenwoodPluginIncludeHTML } from '@greenwood/plugin-include-html';
-import { greenwoodPluginImportCss } from '@greenwood/plugin-import-css';
-import { greenwoodPluginImportJson } from '@greenwood/plugin-import-json';
import { greenwoodPluginPolyfills } from '@greenwood/plugin-polyfills';
import { greenwoodPluginPostCss } from '@greenwood/plugin-postcss';
+import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
import { greenwoodPluginRendererPuppeteer } from '@greenwood/plugin-renderer-puppeteer';
import rollupPluginAnalyzer from 'rollup-plugin-analyzer';
@@ -18,8 +17,12 @@ export default {
lit: true
}),
greenwoodPluginPostCss(),
- greenwoodPluginImportJson(),
- greenwoodPluginImportCss(),
+ greenwoodPluginImportRaw({
+ matches: [
+ 'eve-button.css',
+ 'eve-container.css'
+ ]
+ }),
greenwoodPluginIncludeHTML(),
greenwoodPluginRendererPuppeteer(),
{
diff --git a/package.json b/package.json
index fe99893d8..fe45e2b24 100644
--- a/package.json
+++ b/package.json
@@ -20,22 +20,24 @@
"build": "cross-env __GWD_ROLLUP_MODE__=strict node . build",
"serve": "node . serve",
"develop": "node . develop",
- "test": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 c8 mocha --exclude \"./packages/**/test/cases/exp-*/**\" \"./packages/**/**/*.spec.js\"",
- "test:exp": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 node --experimental-loader $(pwd)/test/test-loader.js ./node_modules/mocha/bin/mocha \"./packages/**/**/*.spec.js\"",
- "test:exp:win": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 node --experimental-loader file:\\\\%cd%\\test\\test-loader.js ./node_modules/mocha/bin/mocha --exclude \"./packages/init/test/cases/**\" \"./packages/**/**/*.spec.js\"",
+ "test": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 c8 mocha --exclude \"./packages/**/test/cases/loaders-*/**\" \"./packages/**/**/*.spec.js\"",
+ "test:loaders": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 node --loader $(pwd)/test/test-loader.js ./node_modules/mocha/bin/mocha \"./packages/**/**/*.spec.js\"",
+ "test:loaders:win": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 node --loader file:\\\\%cd%\\test\\test-loader.js ./node_modules/mocha/bin/mocha --exclude \"./packages/init/test/cases/**\" \"./packages/**/**/*.spec.js\"",
"test:tdd": "yarn test --watch",
- "lint:js": "eslint \"*.{js,md}\" \"./packages/**/**/*.{js,md}\" \"./test/*.js\" \"./www/**/**/*.{js,md}\"",
+ "lint:js": "eslint \"*.js\" \"./packages/**/**/*.js\" \"./test/*.js\" \"./www/**/**/*.js\"",
"lint:ts": "eslint \"./packages/**/**/*.ts\"",
"lint:css": "stylelint \"./www/**/*.js\", \"./www/**/*.css\"",
- "lint": "ls-lint && yarn lint:js && yarn lint:ts && yarn lint:css"
+ "lint": "ls-lint && yarn lint:js && yarn lint:css"
},
"resolutions": {
"lit": "^3.1.0"
},
"devDependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/eslint-parser": "^7.24.1",
+ "@babel/plugin-syntax-import-assertions": "^7.24.1",
+ "@babel/preset-react": "^7.24.1",
"@ls-lint/ls-lint": "^1.10.0",
- "@typescript-eslint/eslint-plugin": "^6.7.5",
- "@typescript-eslint/parser": "^6.7.5",
"babel-eslint": "^10.1.0",
"c8": "^7.10.0",
"chai": "^4.2.0",
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 23af05e1d..0143d4d63 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -18,7 +18,7 @@
"NodeJS"
],
"engines": {
- "node": ">=18.12.1"
+ "node": ">=18.20.0"
},
"bin": {
"greenwood": "./src/index.js"
@@ -38,7 +38,7 @@
"acorn-walk": "^8.0.0",
"commander": "^2.20.0",
"css-tree": "^2.2.1",
- "es-module-shims": "^1.2.0",
+ "es-module-shims": "^1.8.3",
"front-matter": "^4.0.2",
"koa": "^2.13.0",
"koa-body": "^6.0.1",
@@ -52,7 +52,7 @@
"remark-rehype": "^7.0.0",
"rollup": "^3.29.4",
"unified": "^9.2.0",
- "wc-compiler": "~0.12.1"
+ "wc-compiler": "~0.13.0"
},
"devDependencies": {
"@babel/runtime": "^7.10.4",
diff --git a/packages/cli/src/commands/build.js b/packages/cli/src/commands/build.js
index fba4ef73f..e2cc575fe 100644
--- a/packages/cli/src/commands/build.js
+++ b/packages/cli/src/commands/build.js
@@ -26,6 +26,10 @@ async function interceptPage(url, request, plugins, body) {
});
for (const plugin of plugins) {
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, response)) {
+ response = await plugin.preIntercept(url, request, response);
+ }
+
if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response)) {
response = await plugin.intercept(url, request, response);
}
diff --git a/packages/cli/src/config/rollup.config.js b/packages/cli/src/config/rollup.config.js
index e9103edc9..73ddb24b9 100644
--- a/packages/cli/src/config/rollup.config.js
+++ b/packages/cli/src/config/rollup.config.js
@@ -9,7 +9,7 @@ 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', '');
+ return id.replace('\x00', '').replace('?commonjs-proxy', '');
}
function greenwoodResourceLoader (compilation) {
@@ -35,25 +35,42 @@ function greenwoodResourceLoader (compilation) {
}
},
async load(id) {
- const idUrl = new URL(`file://${cleanRollupId(id)}`);
+ let idUrl = new URL(`file://${cleanRollupId(id)}`);
const { pathname } = idUrl;
const extension = pathname.split('.').pop();
+ const headers = {
+ 'Accept': 'text/javascript',
+ 'Sec-Fetch-Dest': 'empty'
+ };
// filter first for any bare specifiers
- if (await checkResourceExists(idUrl) && extension !== '' && extension !== 'js') {
- const url = new URL(`${idUrl.href}?type=${extension}`);
- const request = new Request(url.href);
+ if (await checkResourceExists(idUrl) && extension !== 'js') {
+ for (const plugin of resourcePlugins) {
+ if (plugin.shouldResolve && await plugin.shouldResolve(idUrl)) {
+ idUrl = new URL((await plugin.resolve(idUrl)).url);
+ }
+ }
+
+ const request = new Request(idUrl, {
+ headers
+ });
let response = new Response('');
for (const plugin of resourcePlugins) {
- if (plugin.shouldServe && await plugin.shouldServe(url, request)) {
- response = await plugin.serve(url, request);
+ if (plugin.shouldServe && await plugin.shouldServe(idUrl, request)) {
+ response = await plugin.serve(idUrl, request);
}
}
for (const plugin of resourcePlugins) {
- if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response.clone())) {
- response = await plugin.intercept(url, request, response.clone());
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(idUrl, request, response.clone())) {
+ response = await plugin.preIntercept(idUrl, request, response.clone());
+ }
+ }
+
+ for (const plugin of resourcePlugins) {
+ if (plugin.shouldIntercept && await plugin.shouldIntercept(idUrl, request, response.clone())) {
+ response = await plugin.intercept(idUrl, request, response.clone());
}
}
@@ -161,26 +178,42 @@ function greenwoodImportMetaUrl(compilation) {
});
const idAssetName = path.basename(id);
const normalizedId = id.replace(/\\\\/g, '/').replace(/\\/g, '/'); // windows shenanigans...
- const idUrl = new URL(`file://${cleanRollupId(id)}`);
- const { pathname } = idUrl;
- const extension = pathname.split('.').pop();
- const urlWithType = new URL(`${idUrl.href}?type=${extension}`);
- const request = new Request(urlWithType.href);
+ let idUrl = new URL(`file://${cleanRollupId(id)}`);
+ const headers = {
+ 'Accept': 'text/javascript',
+ 'Sec-Fetch-Dest': 'empty'
+ };
+ const request = new Request(idUrl, {
+ headers
+ });
let canTransform = false;
let response = new Response(code);
// handle any custom imports or pre-processing needed before passing to Rollup this.parse
- if (await checkResourceExists(idUrl) && extension !== '' && extension !== 'json') {
+ if (await checkResourceExists(idUrl)) {
+ for (const plugin of resourcePlugins) {
+ if (plugin.shouldResolve && await plugin.shouldResolve(idUrl)) {
+ idUrl = new URL((await plugin.resolve(idUrl)).url);
+ }
+ }
+
+ for (const plugin of resourcePlugins) {
+ if (plugin.shouldServe && await plugin.shouldServe(idUrl, request)) {
+ response = await plugin.serve(idUrl, request);
+ canTransform = true;
+ }
+ }
+
for (const plugin of resourcePlugins) {
- if (plugin.shouldServe && await plugin.shouldServe(urlWithType, request)) {
- response = await plugin.serve(urlWithType, request);
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(idUrl, request, response)) {
+ response = await plugin.preIntercept(idUrl, request, response);
canTransform = true;
}
}
for (const plugin of resourcePlugins) {
- if (plugin.shouldIntercept && await plugin.shouldIntercept(urlWithType, request, response.clone())) {
- response = await plugin.intercept(urlWithType, request, response.clone());
+ if (plugin.shouldIntercept && await plugin.shouldIntercept(idUrl, request, response.clone())) {
+ response = await plugin.intercept(idUrl, request, response.clone());
canTransform = true;
}
}
@@ -201,11 +234,9 @@ function greenwoodImportMetaUrl(compilation) {
const absoluteScriptDir = path.dirname(id);
const relativeAssetPath = getMetaImportPath(node);
const absoluteAssetPath = path.resolve(absoluteScriptDir, relativeAssetPath);
- const assetName = path.basename(absoluteAssetPath);
- const assetExtension = assetName.split('.').pop();
assetUrls.push({
- url: new URL(`file://${absoluteAssetPath}?type=${assetExtension}`),
+ url: new URL(`file://${absoluteAssetPath}`),
relativeAssetPath
});
}
diff --git a/packages/cli/src/lib/resource-utils.js b/packages/cli/src/lib/resource-utils.js
index 1032afc5e..a08cd9c57 100644
--- a/packages/cli/src/lib/resource-utils.js
+++ b/packages/cli/src/lib/resource-utils.js
@@ -61,15 +61,18 @@ function mergeResponse(destination, source) {
// https://github.com/rollup/rollup/issues/3779
function normalizePathnameForWindows(url) {
const windowsDriveRegex = /\/[a-zA-Z]{1}:\//;
- const { pathname = '' } = url;
+ const { pathname = '', searchParams } = url;
+ const params = searchParams.size > 0
+ ? `?${searchParams.toString()}`
+ : '';
if (windowsDriveRegex.test(pathname)) {
const driveMatch = pathname.match(windowsDriveRegex)[0];
- return pathname.replace(driveMatch, driveMatch.replace('/', ''));
+ return `${pathname.replace(driveMatch, driveMatch.replace('/', ''))}${params}`;
}
- return pathname;
+ return `${pathname}${params}`;
}
async function checkResourceExists(url) {
@@ -108,7 +111,7 @@ async function resolveForRelativeUrl(url, rootUrl) {
return reducedUrl;
}
-// TODO does this make more sense in bundle lifecycle?
+// does this make more sense in bundle lifecycle?
// https://github.com/ProjectEvergreen/greenwood/issues/970
// or could this be done sooner (like in appTemplate building in html resource plugin)?
// Or do we need to ensure userland code / plugins have gone first
diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js
index e3a037a7e..82686250c 100644
--- a/packages/cli/src/lifecycles/bundle.js
+++ b/packages/cli/src/lifecycles/bundle.js
@@ -13,6 +13,10 @@ async function interceptPage(url, request, plugins, body) {
});
for (const plugin of plugins) {
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, response)) {
+ response = await plugin.preIntercept(url, request, response);
+ }
+
if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response)) {
response = await plugin.intercept(url, request, response);
}
@@ -140,11 +144,27 @@ async function bundleStyleResources(compilation, resourcePlugins) {
} else {
const url = resource.sourcePathURL;
const contentType = 'text/css';
- const headers = new Headers({ 'Content-Type': contentType });
+ const headers = new Headers({ 'Content-Type': contentType, 'Accept': contentType });
const request = new Request(url, { headers });
const initResponse = new Response(contents, { headers });
let response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
+ const intermediateResponse = await responsePromise;
+ const shouldPreIntercept = plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, intermediateResponse.clone());
+
+ if (shouldPreIntercept) {
+ const currentResponse = await plugin.preIntercept(url, request, intermediateResponse.clone());
+ const mergedResponse = mergeResponse(intermediateResponse.clone(), currentResponse.clone());
+
+ if (mergedResponse.headers.get('Content-Type').indexOf(contentType) >= 0) {
+ return Promise.resolve(mergedResponse.clone());
+ }
+ }
+
+ return Promise.resolve(responsePromise);
+ }, Promise.resolve(initResponse));
+
+ response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
const intermediateResponse = await responsePromise;
const shouldIntercept = plugin.shouldIntercept && await plugin.shouldIntercept(url, request, intermediateResponse.clone());
@@ -158,7 +178,7 @@ async function bundleStyleResources(compilation, resourcePlugins) {
}
return Promise.resolve(responsePromise);
- }, Promise.resolve(initResponse));
+ }, Promise.resolve(response.clone()));
response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
const intermediateResponse = await responsePromise;
@@ -295,6 +315,7 @@ const bundleCompilation = async (compilation) => {
return plugin.provider(compilation);
}).filter((provider) => {
return provider.shouldIntercept && provider.intercept
+ || provider.shouldPreIntercept && provider.preIntercept
|| provider.shouldOptimize && provider.optimize;
});
diff --git a/packages/cli/src/lifecycles/prerender.js b/packages/cli/src/lifecycles/prerender.js
index 6eb1a3438..804cfd4a1 100644
--- a/packages/cli/src/lifecycles/prerender.js
+++ b/packages/cli/src/lifecycles/prerender.js
@@ -32,6 +32,10 @@ async function interceptPage(url, request, plugins, body) {
});
for (const plugin of plugins) {
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, response)) {
+ response = await plugin.preIntercept(url, request, response);
+ }
+
if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response)) {
response = await plugin.intercept(url, request, response);
}
diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js
index 6ae901876..6201ea80f 100644
--- a/packages/cli/src/lifecycles/serve.js
+++ b/packages/cli/src/lifecycles/serve.js
@@ -88,6 +88,42 @@ async function getDevServer(compilation) {
await next();
});
+ // allow pre-processing of userland plugins _before_ Greenwood "standardizes" it
+ app.use(async (ctx, next) => {
+ try {
+ const url = new URL(ctx.url);
+ const { header, status, message } = ctx.response;
+ const request = transformKoaRequestIntoStandardRequest(url, ctx.request);
+ const initResponse = new Response(status === 204 ? null : ctx.body, {
+ statusText: message,
+ status,
+ headers: new Headers(header)
+ });
+ const response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
+ const intermediateResponse = await responsePromise;
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, intermediateResponse.clone())) {
+ const current = await plugin.preIntercept(url, request, await intermediateResponse.clone());
+ const merged = mergeResponse(intermediateResponse.clone(), current);
+
+ return Promise.resolve(merged);
+ } else {
+ return Promise.resolve(await responsePromise);
+ }
+ }, Promise.resolve(initResponse.clone()));
+
+ ctx.body = response.body ? Readable.from(response.body) : '';
+ ctx.message = response.statusText;
+ response.headers.forEach((value, key) => {
+ ctx.set(key, value);
+ });
+ } catch (e) {
+ ctx.status = 500;
+ console.error(e);
+ }
+
+ await next();
+ });
+
// allow intercepting of responses for URLs
app.use(async (ctx, next) => {
try {
diff --git a/packages/cli/src/loader.js b/packages/cli/src/loader.js
index 238fefcd0..5d347bc20 100644
--- a/packages/cli/src/loader.js
+++ b/packages/cli/src/loader.js
@@ -1,19 +1,23 @@
-import fs from 'fs/promises';
import { readAndMergeConfig as initConfig } from './lifecycles/config.js';
const config = await initConfig();
-const resourcePlugins = config.plugins.filter(plugin => plugin.type === 'resource' && !plugin.isGreenwoodDefaultPlugin).map(plugin => plugin.provider({
+const resourcePlugins = config.plugins.filter(plugin => plugin.type === 'resource').map(plugin => plugin.provider({
context: {
projectDirectory: new URL(`file://${process.cwd()}`)
- }
+ },
+ config: {
+ devServer: {}
+ },
+ graph: []
}));
-async function getCustomLoaderResponse(url, body = '', checkOnly = false) {
- const headers = new Headers({
- 'Content-Type': 'text/javascript'
- });
- const request = new Request(url.href, { headers });
- const initResponse = new Response(body, { headers });
+async function getCustomLoaderResponse(url, checkOnly = false) {
+ const headers = {
+ 'Accept': 'text/javascript',
+ 'Sec-Fetch-Dest': 'empty'
+ };
+ const request = new Request(url, { headers });
+ const initResponse = new Response('');
let response = initResponse.clone();
let shouldHandle = false;
@@ -28,6 +32,14 @@ async function getCustomLoaderResponse(url, body = '', checkOnly = false) {
}
for (const plugin of resourcePlugins) {
+ if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, response.clone())) {
+ shouldHandle = true;
+
+ if (!checkOnly) {
+ response = await plugin.preIntercept(url, request, response.clone());
+ }
+ }
+
if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response.clone())) {
shouldHandle = true;
@@ -53,7 +65,7 @@ export async function resolve(specifier, context, defaultResolve) {
: undefined;
if (url) {
- const { shouldHandle } = await getCustomLoaderResponse(url, null, true);
+ const { shouldHandle } = await getCustomLoaderResponse(url, true);
if (shouldHandle) {
return {
@@ -69,19 +81,16 @@ export async function resolve(specifier, context, defaultResolve) {
// https://nodejs.org/docs/latest-v18.x/api/esm.html#loadurl-context-nextload
export async function load(source, context, defaultLoad) {
const extension = source.split('.').pop();
- const url = new URL(`${source}?type=${extension}`);
- const { shouldHandle } = await getCustomLoaderResponse(url, null, true);
+ const url = new URL(source);
+ const { shouldHandle } = await getCustomLoaderResponse(url, true);
- if (shouldHandle) {
- const contents = await fs.readFile(url, 'utf-8');
- const { response } = await getCustomLoaderResponse(url, contents);
- const body = await response.text();
+ if (shouldHandle && extension !== 'js') {
+ const { response } = await getCustomLoaderResponse(url);
+ const contents = await response.text();
- // TODO better way to handle remove export default? leverage import assertions instead
- // https://github.com/ProjectEvergreen/greenwood/issues/923
return {
- format: extension === 'json' ? 'json' : 'module',
- source: extension === 'json' ? JSON.stringify(JSON.parse(contents.replace('export default ', ''))) : body,
+ format: 'module',
+ source: contents,
shortCircuit: true
};
}
diff --git a/packages/cli/src/plugins/resource/plugin-node-modules.js b/packages/cli/src/plugins/resource/plugin-node-modules.js
index 475efbf18..ff05c4446 100644
--- a/packages/cli/src/plugins/resource/plugin-node-modules.js
+++ b/packages/cli/src/plugins/resource/plugin-node-modules.js
@@ -29,7 +29,7 @@ class NodeModulesResource extends ResourceInterface {
// https://github.com/ProjectEvergreen/greenwood/issues/953v
async resolve(url) {
const { projectDirectory } = this.compilation.context;
- const { pathname } = url;
+ const { pathname, searchParams } = url;
const packageName = getPackageNameFromUrl(pathname);
const absoluteNodeModulesLocation = await getNodeModulesLocationForPackage(packageName);
const packagePathPieces = pathname.split('node_modules/')[1].split('/'); // double split to handle node_modules within nested paths
@@ -37,8 +37,11 @@ class NodeModulesResource extends ResourceInterface {
const absoluteNodeModulesPathname = absoluteNodeModulesLocation
? `${absoluteNodeModulesLocation}${packagePathPieces.join('/').replace(packageName, '')}`
: (await resolveForRelativeUrl(url, projectDirectory)).pathname;
+ const params = searchParams.size > 0
+ ? `?${searchParams.toString()}`
+ : '';
- return new Request(`file://${absoluteNodeModulesPathname}`);
+ return new Request(`file://${absoluteNodeModulesPathname}${params}`);
}
async shouldServe(url) {
diff --git a/packages/cli/src/plugins/resource/plugin-standard-css.js b/packages/cli/src/plugins/resource/plugin-standard-css.js
index d52c723e2..f9cfbe664 100644
--- a/packages/cli/src/plugins/resource/plugin-standard-css.js
+++ b/packages/cli/src/plugins/resource/plugin-standard-css.js
@@ -227,11 +227,30 @@ class StandardCssResource extends ResourceInterface {
});
}
+ async shouldIntercept(url, request) {
+ const { pathname, searchParams } = url;
+ const ext = pathname.split('.').pop();
+
+ return url.protocol === 'file:' && ext === this.extensions[0] && request.headers.get('Accept')?.indexOf('text/javascript') >= 0 && !searchParams.has('type');
+ }
+
+ async intercept(url, request, response) {
+ const contents = (await response.text()).replace(/\r?\n|\r/g, ' ').replace(/\\/g, '\\\\');
+ const body = `const sheet = new CSSStyleSheet();sheet.replaceSync(\`${contents}\`);export default sheet;`;
+
+ return new Response(body, {
+ headers: {
+ 'Content-Type': 'text/javascript'
+ }
+ });
+ }
+
async shouldOptimize(url, response) {
- const { protocol, pathname } = url;
+ const { protocol, pathname, searchParams } = url;
const isValidCss = pathname.split('.').pop() === this.extensions[0]
&& protocol === 'file:'
- && response.headers.get('Content-Type').indexOf(this.contentType) >= 0;
+ && response.headers.get('Content-Type').indexOf(this.contentType) >= 0
+ && searchParams.get('type') !== 'css';
return this.compilation.config.optimization !== 'none' && isValidCss;
}
diff --git a/packages/cli/src/plugins/resource/plugin-standard-json.js b/packages/cli/src/plugins/resource/plugin-standard-json.js
index 726c9b5c1..07d9883aa 100644
--- a/packages/cli/src/plugins/resource/plugin-standard-json.js
+++ b/packages/cli/src/plugins/resource/plugin-standard-json.js
@@ -40,6 +40,24 @@ class StandardJsonResource extends ResourceInterface {
})
});
}
+
+ async shouldIntercept(url, request) {
+ const { protocol, pathname, searchParams } = url;
+ const ext = pathname.split('.').pop();
+
+ return protocol === 'file:' && request.headers.get('Accept')?.indexOf('text/javascript') >= 0 && ext === this.extensions[0] && !searchParams.has('type');
+ }
+
+ async intercept(url, request, response) {
+ const json = await response.json();
+ const body = `export default ${JSON.stringify(json)}`;
+
+ return new Response(body, {
+ headers: {
+ 'Content-Type': 'text/javascript'
+ }
+ });
+ }
}
const pluginGreenwoodStandardJson = [{
diff --git a/packages/cli/test/cases/build.plugins.context/theme-pack-context-plugin.js b/packages/cli/test/cases/build.plugins.context/theme-pack-context-plugin.js
index bff573f54..2227fbad2 100644
--- a/packages/cli/test/cases/build.plugins.context/theme-pack-context-plugin.js
+++ b/packages/cli/test/cases/build.plugins.context/theme-pack-context-plugin.js
@@ -1,20 +1,15 @@
import fs from 'fs/promises';
-import os from 'os';
-import { spawnSync } from 'child_process';
const packageJson = JSON.parse(await fs.readFile(new URL('./package.json', import.meta.url), 'utf-8'));
-const myThemePackPlugin = () => [{
+const myThemePackPlugin = (options = {}) => [{
type: 'context',
name: 'my-theme-pack:context',
provider: () => {
const { name } = packageJson;
- const command = os.platform() === 'win32' ? 'npm.cmd' : 'npm';
- const ls = spawnSync(command, ['ls', name]);
- const isInstalled = ls.stdout.toString().indexOf('(empty)') < 0;
- const templateLocation = isInstalled
- ? new URL(`./node_modules/${name}/dist/layouts/`, import.meta.url)
- : new URL('./fixtures/layouts/', import.meta.url);
+ const templateLocation = options.__isDevelopment // eslint-disable-line no-underscore-dangle
+ ? new URL('./fixtures/layouts/', import.meta.url)
+ : new URL(`./node_modules/${name}/dist/layouts/`, import.meta.url);
return {
templates: [
diff --git a/packages/cli/test/cases/develop.plugins.context/greenwood.config.js b/packages/cli/test/cases/develop.plugins.context/greenwood.config.js
index 74c311257..60eaf3c94 100644
--- a/packages/cli/test/cases/develop.plugins.context/greenwood.config.js
+++ b/packages/cli/test/cases/develop.plugins.context/greenwood.config.js
@@ -24,7 +24,9 @@ class MyThemePackDevelopmentResource extends ResourceInterface {
export default {
plugins: [
- ...myThemePackPlugin(),
+ ...myThemePackPlugin({
+ __isDevelopment: true
+ }),
{
type: 'resource',
name: 'my-theme-pack:resource',
diff --git a/packages/cli/test/cases/loaders-build.import-attributes/loaders-build.import-attributes.spec.js b/packages/cli/test/cases/loaders-build.import-attributes/loaders-build.import-attributes.spec.js
new file mode 100644
index 000000000..7d474741c
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.import-attributes/loaders-build.import-attributes.spec.js
@@ -0,0 +1,77 @@
+/*
+ * Use Case
+ * Run Greenwood serve command with no config for using import attributes with a basic static bundles.
+ *
+ * User Result
+ * Should start the development server and render a bare bones Greenwood build.
+ *
+ * User Command
+ * greenwood serve
+ *
+ * User Config
+ * {}
+ *
+ * User Workspace
+ * src/
+ * components/
+ * card/
+ * card.css
+ * card.js
+ * card.json
+ * pages/
+ * index.html
+ *
+ */
+import chai from 'chai';
+import fs from 'fs';
+import glob from 'glob-promise';
+import path from 'path';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Build Greenwood With: ', function() {
+ const LABEL = 'Import Attributes used in static pages';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ const hostname = 'http://localhost:8080';
+ let runner;
+
+ before(function() {
+ this.context = {
+ hostname
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+
+ before(async function() {
+ runner.setup(outputPath);
+ runner.runCommand(cliPath, 'build');
+ });
+
+ describe('Importing CSS w/ Constructable Stylesheets', function() {
+ let scripts;
+
+ before(async function() {
+ scripts = await glob.promise(path.join(outputPath, 'public/card.*.js'));
+ });
+
+ it('should have the expected output from importing hero.css as a Constructable Stylesheet', function() {
+ const scriptContents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(scriptContents).to.contain('const e=new CSSStyleSheet;e.replaceSync(":host { color: red; }");');
+ });
+ });
+ });
+
+ after(function() {
+ runner.stopCommand();
+ runner.teardown([
+ path.join(outputPath, '.greenwood'),
+ path.join(outputPath, 'node_modules')
+ ]);
+ });
+});
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.css b/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.css
new file mode 100644
index 000000000..2ace1c18d
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.css
@@ -0,0 +1,3 @@
+:host {
+ color: red;
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.js b/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.js
new file mode 100644
index 000000000..49a154086
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.js
@@ -0,0 +1,27 @@
+import sheet from './card.css' with { type: 'css' };
+import data from './card.json' with { type: 'json' };
+
+export default class Card extends HTMLElement {
+
+ connectedCallback() {
+ if (!this.shadowRoot) {
+ const name = this.getAttribute('name') || 'World';
+ const template = document.createElement('template');
+
+ template.innerHTML = `
+
+
+
Hello, ${name}!
+
+
+ `;
+
+ this.attachShadow({ mode: 'open' });
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
+ }
+
+ this.shadowRoot.adoptedStyleSheets = [sheet];
+ }
+}
+
+customElements.define('app-card', Card);
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.json b/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.json
new file mode 100644
index 000000000..cf759ab71
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.import-attributes/src/components/card/card.json
@@ -0,0 +1,5 @@
+{
+ "image": {
+ "url": "/path/to/image.webp"
+ }
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.import-attributes/src/pages/index.html b/packages/cli/test/cases/loaders-build.import-attributes/src/pages/index.html
new file mode 100644
index 000000000..ed61c4594
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.import-attributes/src/pages/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ The home page
+
+
+
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/greenwood.config.js b/packages/cli/test/cases/loaders-build.prerender-import-attributes/greenwood.config.js
new file mode 100644
index 000000000..8dc4be464
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/greenwood.config.js
@@ -0,0 +1,3 @@
+export default {
+ prerender: true
+};
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/loaders-build.prerender-import-attributes.spec.js b/packages/cli/test/cases/loaders-build.prerender-import-attributes/loaders-build.prerender-import-attributes.spec.js
new file mode 100644
index 000000000..7b765e769
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/loaders-build.prerender-import-attributes.spec.js
@@ -0,0 +1,97 @@
+/*
+ * Use Case
+ * Run Greenwood with prerendering of CSS and JSON being referenced using import attributes.
+ *
+ * User Result
+ * Should generate a static Greenwood build with CSS properly prerendered.
+ *
+ * User Command
+ * greenwood build
+ *
+ * User Config
+ * import { greenwoodPluginImportCss } from '@greenwood/plugin-import-css';
+ *
+ * {
+ * prerender: true,
+ * }
+ *
+ * User Workspace
+ * src/
+ * components/
+ * hero/
+ * hero.css
+ * hero.js
+ * hero.json
+* index.html
+ */
+import chai from 'chai';
+import fs from 'fs';
+import glob from 'glob-promise';
+import { JSDOM } from 'jsdom';
+import path from 'path';
+import { runSmokeTest } from '../../../../../test/smoke-test.js';
+import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Build Greenwood With: ', function() {
+ const LABEL = 'ESM Import Attribute for CSS and JSON with prerendering';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+ before(function() {
+ runner.setup(outputPath, getSetupFiles(outputPath));
+ runner.runCommand(cliPath, 'build');
+ });
+
+ runSmokeTest(['public'], LABEL);
+
+ describe('Importing CSS w/ Constructable Stylesheets', function() {
+ let scripts;
+
+ before(async function() {
+ scripts = await glob.promise(path.join(this.context.publicDir, '*.js'));
+ });
+
+ // TODO is this actually the output we want here?
+ // https://github.com/ProjectEvergreen/greenwood/discussions/1216
+ it('should have the expected output from importing hero.css as a Constructable Stylesheet', function() {
+ const scriptContents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(scriptContents).to.contain('const t=new CSSStyleSheet;t.replaceSync(":host { text-align: center');
+ });
+ });
+
+ describe('Importing JSON', function() {
+ let dom;
+
+ before(async function() {
+ dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './index.html'));
+ });
+
+ it('should have the expected inline content from the JSON file', function() {
+ const hero = new JSDOM(dom.window.document.querySelector('app-hero template[shadowrootmode="open"]').innerHTML);
+ const heading = hero.window.document.querySelectorAll('div.hero h2');
+
+ expect(heading.length).to.equal(1);
+ expect(heading[0].textContent).to.be.equal('Welcome to my website');
+ });
+ });
+ });
+
+ after(function() {
+ runner.teardown(getOutputTeardownFiles(outputPath));
+ });
+
+});
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/package.json b/packages/cli/test/cases/loaders-build.prerender-import-attributes/package.json
new file mode 100644
index 000000000..aead43de3
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "module"
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.css b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.css
new file mode 100644
index 000000000..86fb17fc3
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.css
@@ -0,0 +1,18 @@
+:host {
+ text-align: center;
+ margin-bottom: 40px;
+}
+
+:host h2 {
+ font-size: 3em;
+}
+
+:host button {
+ display: inline-block;
+ background-color: var(--color-primary);
+ color: var(--color-white);
+ font-size: 1.5em;
+ padding: 14px;
+ border-radius: 10px;
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.js b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.js
new file mode 100644
index 000000000..9ef6625cb
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.js
@@ -0,0 +1,40 @@
+import sheet from './hero.css' with { type: 'css' };
+import data from './hero.json' with { type: 'json' };
+
+export default class HeroBanner extends HTMLElement {
+ clickButton(el) {
+ console.log('clicked button =>', el.textContent);
+ }
+
+ connectedCallback() {
+ if (!this.shadowRoot) {
+ const template = document.createElement('template');
+
+ template.innerHTML = `
+
+ `;
+
+ this.attachShadow({ mode: 'open' });
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
+ }
+
+ this.shadowRoot.adoptedStyleSheets = [sheet];
+ // TODO upstream to WCC?
+ // this.shadowRoot.querySelectorAll('button')
+ // .forEach(button => {
+ // button.addEventListener('click', () => this.clickButton(button))
+ // });
+ }
+}
+
+customElements.define('app-hero', HeroBanner);
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.json b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.json
new file mode 100644
index 000000000..662f223f5
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/components/hero/hero.json
@@ -0,0 +1,3 @@
+{
+ "message": "Welcome to my website"
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/index.html b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/index.html
new file mode 100644
index 000000000..f67c1b687
--- /dev/null
+++ b/packages/cli/test/cases/loaders-build.prerender-import-attributes/src/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-develop.ssr-import-attributes/loaders-develop.ssr-import-attributes.spec.js b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/loaders-develop.ssr-import-attributes.spec.js
new file mode 100644
index 000000000..4e8ba8745
--- /dev/null
+++ b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/loaders-develop.ssr-import-attributes.spec.js
@@ -0,0 +1,186 @@
+/*
+ * Use Case
+ * Run Greenwood develop command with no config.
+ *
+ * User Result
+ * Should start the development server and render a bare bones Greenwood build.
+ *
+ * User Command
+ * greenwood develop
+ *
+ * User Config
+ * {}
+ *
+ * User Workspace
+ * src/
+ * api/
+ * fragment.js
+ * components/
+ * card/
+ * card.css
+ * card.js
+ * card.json
+ * pages/
+ * greeting.js
+ *
+ */
+import chai from 'chai';
+import { JSDOM } from 'jsdom';
+import path from 'path';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Develop Greenwood With: ', function() {
+ const LABEL = 'Import Attributes used in API Routes and SSR Pages';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ const hostname = 'http://127.0.0.1:1984';
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+
+ before(async function() {
+ runner.setup(outputPath);
+
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, 5000);
+
+ runner.runCommand(cliPath, 'develop', { async: true });
+ });
+ });
+
+ describe('CSS file is returned as CSS (text/css)', function() {
+ let response = {};
+ let body;
+
+ before(async function() {
+ response = await fetch(`${hostname}/components/card/card.css`);
+ body = await response.clone().text();
+ });
+
+ it('should return a 200 status', function(done) {
+ expect(response.status).to.equal(200);
+ done();
+ });
+
+ it('should return the correct content type', function(done) {
+ expect(response.headers.get('content-type')).to.equal('text/css');
+ done();
+ });
+
+ it('should return the correct response body', function(done) {
+ expect(body).to.equal(':host {\n color: red;\n}');
+ done();
+ });
+ });
+
+ describe('JSON file is returned as JSON (application/json)', function() {
+ let response = {};
+ let data;
+
+ before(async function() {
+ response = await fetch(`${hostname}/components/card/card.json`);
+ data = await response.clone().json();
+ });
+
+ it('should return a 200 status', function(done) {
+ expect(response.status).to.equal(200);
+ done();
+ });
+
+ it('should return the correct content type', function(done) {
+ expect(response.headers.get('content-type')).to.equal('application/json');
+ done();
+ });
+
+ it('should return the correct response body data', function(done) {
+ expect(data.image.url).to.equal('/path/to/image.webp');
+ done();
+ });
+ });
+
+ describe('API Route specific behaviors for an HTML ("fragment") API', function() {
+ const name = 'Greenwood';
+ let response = {};
+ let body;
+
+ before(async function() {
+ response = await fetch(`${hostname}/api/fragment?name=${name}`);
+ body = await response.clone().text();
+ });
+
+ it('should return a 200 status', function(done) {
+ expect(response.status).to.equal(200);
+ done();
+ });
+
+ it('should return the correct content type', function(done) {
+ expect(response.headers.get('content-type')).to.equal('text/html');
+ done();
+ });
+
+ it('should return the correct response body', function(done) {
+ const dom = new JSDOM(body);
+ const card = new JSDOM(dom.window.document.querySelectorAll('app-card template[shadowrootmode="open"]')[0].innerHTML);
+ const heading = card.window.document.querySelector('h2');
+ const image = card.window.document.querySelector('img');
+
+ expect(heading.textContent).to.equal(`Hello, ${name}!`);
+ expect(image.getAttribute('href')).to.equal('/path/to/image.webp');
+
+ done();
+ });
+ });
+
+ describe('SSR route specific behaviors when using a custom element as the page', function() {
+ let response = {};
+ let body;
+
+ before(async function() {
+ response = await fetch(`${hostname}/greeting/`);
+ body = await response.clone().text();
+ });
+
+ it('should return a 200 status', function(done) {
+ expect(response.status).to.equal(200);
+ done();
+ });
+
+ it('should return the correct content type', function(done) {
+ expect(response.headers.get('content-type')).to.equal('text/html');
+ done();
+ });
+
+ it('should return the correct response body', function(done) {
+ const dom = new JSDOM(body);
+ const card = new JSDOM(dom.window.document.querySelectorAll('app-card template[shadowrootmode="open"]')[0].innerHTML);
+ const heading = card.window.document.querySelector('h2');
+ const image = card.window.document.querySelector('img');
+
+ expect(heading.textContent).to.equal('Hello, World!');
+ expect(image.getAttribute('href')).to.equal('/path/to/image.webp');
+
+ done();
+ });
+ });
+ });
+
+ after(function() {
+ runner.stopCommand();
+ runner.teardown([
+ path.join(outputPath, '.greenwood'),
+ path.join(outputPath, 'node_modules')
+ ]);
+ });
+});
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/api/fragment.js b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/api/fragment.js
new file mode 100644
index 000000000..a37a035db
--- /dev/null
+++ b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/api/fragment.js
@@ -0,0 +1,17 @@
+import { renderFromHTML } from 'wc-compiler';
+
+export async function handler(request) {
+ const params = new URLSearchParams(request.url.slice(request.url.indexOf('?')));
+ const name = params.has('name') ? params.get('name') : 'World';
+ const { html } = await renderFromHTML(`
+
+ `, [
+ new URL('../components/card/card.js', import.meta.url)
+ ]);
+
+ return new Response(html, {
+ headers: new Headers({
+ 'Content-Type': 'text/html'
+ })
+ });
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.css b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.css
new file mode 100644
index 000000000..2ace1c18d
--- /dev/null
+++ b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.css
@@ -0,0 +1,3 @@
+:host {
+ color: red;
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.js b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.js
new file mode 100644
index 000000000..49a154086
--- /dev/null
+++ b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.js
@@ -0,0 +1,27 @@
+import sheet from './card.css' with { type: 'css' };
+import data from './card.json' with { type: 'json' };
+
+export default class Card extends HTMLElement {
+
+ connectedCallback() {
+ if (!this.shadowRoot) {
+ const name = this.getAttribute('name') || 'World';
+ const template = document.createElement('template');
+
+ template.innerHTML = `
+
+
+
Hello, ${name}!
+
+
+ `;
+
+ this.attachShadow({ mode: 'open' });
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
+ }
+
+ this.shadowRoot.adoptedStyleSheets = [sheet];
+ }
+}
+
+customElements.define('app-card', Card);
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.json b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.json
new file mode 100644
index 000000000..cf759ab71
--- /dev/null
+++ b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/components/card/card.json
@@ -0,0 +1,5 @@
+{
+ "image": {
+ "url": "/path/to/image.webp"
+ }
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/pages/greeting.js b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/pages/greeting.js
new file mode 100644
index 000000000..4e69e3014
--- /dev/null
+++ b/packages/cli/test/cases/loaders-develop.ssr-import-attributes/src/pages/greeting.js
@@ -0,0 +1,10 @@
+import '../components/card/card.js';
+
+export default class GreetingPage extends HTMLElement {
+
+ async connectedCallback() {
+ this.innerHTML = `
+
+ `;
+ }
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/loaders-serve.default.ssr-import-attributes.spec.js b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/loaders-serve.default.ssr-import-attributes.spec.js
new file mode 100644
index 000000000..816e2ee91
--- /dev/null
+++ b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/loaders-serve.default.ssr-import-attributes.spec.js
@@ -0,0 +1,167 @@
+/*
+ * Use Case
+ * Run Greenwood serve command with no config for using import attributes with API Routes and SSR pages..
+ *
+ * User Result
+ * Should start the development server and render a bare bones Greenwood build.
+ *
+ * User Command
+ * greenwood serve
+ *
+ * User Config
+ * {}
+ *
+ * User Workspace
+ * src/
+ * api/
+ * fragment.js
+ * components/
+ * card/
+ * card.css
+ * card.js
+ * card.json
+ * pages/
+ * greeting.js
+ *
+ */
+import chai from 'chai';
+import fs from 'fs';
+import glob from 'glob-promise';
+import { JSDOM } from 'jsdom';
+import path from 'path';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Serve Greenwood With: ', function() {
+ const LABEL = 'Import Attributes used in API Routes and SSR Pages';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ const hostname = 'http://localhost:8080';
+ let runner;
+
+ before(function() {
+ this.context = {
+ hostname
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+
+ before(async function() {
+ runner.setup(outputPath);
+ runner.runCommand(cliPath, 'build');
+
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, 10000);
+
+ runner.runCommand(cliPath, 'serve', { async: true });
+ });
+ });
+
+ describe('API Route specific behaviors for an HTML ("fragment") API', function() {
+ const name = 'Greenwood';
+ let response = {};
+ let body;
+ let scripts;
+
+ before(async function() {
+ response = await fetch(`${hostname}/api/fragment?name=${name}`);
+ body = await response.clone().text();
+ scripts = await glob.promise(path.join(outputPath, 'public/api/card.*.js'));
+ });
+
+ it('should return a 200 status', function(done) {
+ expect(response.status).to.equal(200);
+ done();
+ });
+
+ it('should return the correct content type', function(done) {
+ expect(response.headers.get('content-type')).to.equal('text/html');
+ done();
+ });
+
+ it('should return the correct response body', function(done) {
+ const dom = new JSDOM(body);
+ const card = new JSDOM(dom.window.document.querySelectorAll('app-card template[shadowrootmode="open"]')[0].innerHTML);
+ const heading = card.window.document.querySelector('h2');
+ const image = card.window.document.querySelector('img');
+
+ expect(heading.textContent).to.equal(`Hello, ${name}!`);
+ expect(image.getAttribute('href')).to.equal('/path/to/image.webp');
+
+ done();
+ });
+
+ it('should have the expected output from importing hero.css as a Constructable Stylesheet', function() {
+ const scriptContents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(scriptContents).to.contain('const sheet = new CSSStyleSheet();sheet.replaceSync(`:host { color: red; }`);');
+ });
+
+ it('should have the expected output from importing hero.json', function() {
+ const scriptContents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(scriptContents).to.contain('var data = {"image":{"url":"/path/to/image.webp"}};');
+ });
+ });
+
+ describe('SSR route specific behaviors when using a custom element as the page', function() {
+ let response = {};
+ let body;
+ let scripts;
+
+ before(async function() {
+ response = await fetch(`${hostname}/greeting/`);
+ body = await response.clone().text();
+ scripts = await glob.promise(path.join(outputPath, 'public/greeting.route.chunk.*.js'));
+ });
+
+ it('should return a 200 status', function(done) {
+ expect(response.status).to.equal(200);
+ done();
+ });
+
+ it('should return the correct content type', function(done) {
+ expect(response.headers.get('content-type')).to.equal('text/html');
+ done();
+ });
+
+ it('should return the correct response body', function(done) {
+ const dom = new JSDOM(body);
+ const card = new JSDOM(dom.window.document.querySelectorAll('app-card template[shadowrootmode="open"]')[0].innerHTML);
+ const heading = card.window.document.querySelector('h2');
+ const image = card.window.document.querySelector('img');
+
+ expect(heading.textContent).to.equal('Hello, World!');
+ expect(image.getAttribute('href')).to.equal('/path/to/image.webp');
+
+ done();
+ });
+
+ it('should have the expected output from importing hero.css as a Constructable Stylesheet', function() {
+ const scriptContents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(scriptContents).to.contain('const sheet = new CSSStyleSheet();sheet.replaceSync(`:host { color: red; }`);');
+ });
+
+ it('should have the expected output from importing hero.json', function() {
+ const scriptContents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(scriptContents).to.contain('var data = {"image":{"url":"/path/to/image.webp"}};');
+ });
+ });
+ });
+
+ after(function() {
+ runner.stopCommand();
+ runner.teardown([
+ path.join(outputPath, '.greenwood'),
+ path.join(outputPath, 'node_modules')
+ ]);
+ });
+});
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/api/fragment.js b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/api/fragment.js
new file mode 100644
index 000000000..a37a035db
--- /dev/null
+++ b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/api/fragment.js
@@ -0,0 +1,17 @@
+import { renderFromHTML } from 'wc-compiler';
+
+export async function handler(request) {
+ const params = new URLSearchParams(request.url.slice(request.url.indexOf('?')));
+ const name = params.has('name') ? params.get('name') : 'World';
+ const { html } = await renderFromHTML(`
+
+ `, [
+ new URL('../components/card/card.js', import.meta.url)
+ ]);
+
+ return new Response(html, {
+ headers: new Headers({
+ 'Content-Type': 'text/html'
+ })
+ });
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.css b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.css
new file mode 100644
index 000000000..2ace1c18d
--- /dev/null
+++ b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.css
@@ -0,0 +1,3 @@
+:host {
+ color: red;
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.js b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.js
new file mode 100644
index 000000000..49a154086
--- /dev/null
+++ b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.js
@@ -0,0 +1,27 @@
+import sheet from './card.css' with { type: 'css' };
+import data from './card.json' with { type: 'json' };
+
+export default class Card extends HTMLElement {
+
+ connectedCallback() {
+ if (!this.shadowRoot) {
+ const name = this.getAttribute('name') || 'World';
+ const template = document.createElement('template');
+
+ template.innerHTML = `
+
+
+
Hello, ${name}!
+
+
+ `;
+
+ this.attachShadow({ mode: 'open' });
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
+ }
+
+ this.shadowRoot.adoptedStyleSheets = [sheet];
+ }
+}
+
+customElements.define('app-card', Card);
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.json b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.json
new file mode 100644
index 000000000..cf759ab71
--- /dev/null
+++ b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/components/card/card.json
@@ -0,0 +1,5 @@
+{
+ "image": {
+ "url": "/path/to/image.webp"
+ }
+}
\ No newline at end of file
diff --git a/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/pages/greeting.js b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/pages/greeting.js
new file mode 100644
index 000000000..4e69e3014
--- /dev/null
+++ b/packages/cli/test/cases/loaders-serve.default.ssr-import-attributes/src/pages/greeting.js
@@ -0,0 +1,10 @@
+import '../components/card/card.js';
+
+export default class GreetingPage extends HTMLElement {
+
+ async connectedCallback() {
+ this.innerHTML = `
+
+ `;
+ }
+}
\ No newline at end of file
diff --git a/packages/plugin-babel/src/index.js b/packages/plugin-babel/src/index.js
index d4881e915..a3a6b3178 100644
--- a/packages/plugin-babel/src/index.js
+++ b/packages/plugin-babel/src/index.js
@@ -37,11 +37,11 @@ class BabelResource extends ResourceInterface {
this.contentType = ['text/javascript'];
}
- async shouldIntercept(url) {
+ async shouldPreIntercept(url) {
return url.pathname.split('.').pop() === this.extensions[0] && !url.pathname.startsWith('/node_modules/');
}
- async intercept(url, request, response) {
+ async preIntercept(url, request, response) {
const config = await getConfig(this.compilation, this.options.extendConfig);
const body = await response.text();
const result = await babel.transform(body, config);
diff --git a/packages/plugin-graphql/README.md b/packages/plugin-graphql/README.md
index 21f37bc41..243446981 100644
--- a/packages/plugin-graphql/README.md
+++ b/packages/plugin-graphql/README.md
@@ -45,7 +45,7 @@ This will then allow you to use GraphQL to query your content from your client s
```js
import client from '@greenwood/plugin-graphql/src/core/client.js';
-import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql';
+import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql' with { type: 'gql' };
class HeaderComponent extends HTMLElement {
constructor() {
@@ -167,7 +167,7 @@ query($name: String!) {
And then you can use it in your code as such:
```js
import client from '@greenwood/plugin-graphql/src/core/client.js';
-import GalleryQuery from '../relative/path/to/data/queries/gallery.gql';
+import GalleryQuery from '../relative/path/to/data/queries/gallery.gql' with { type: 'gql' };
client.query({
query: GalleryQuery,
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/greenwood.config.js b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/greenwood.config.js
similarity index 100%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/greenwood.config.js
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/greenwood.config.js
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/exp-prerender.query-children.spec.js b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/loaders-prerender.query-children.spec.js
similarity index 100%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/exp-prerender.query-children.spec.js
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/loaders-prerender.query-children.spec.js
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/package.json b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/package.json
similarity index 100%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/package.json
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/package.json
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/src/components/posts-list.js b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/components/posts-list.js
similarity index 95%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/src/components/posts-list.js
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/components/posts-list.js
index 6cf450ec1..32acb60d8 100644
--- a/packages/plugin-graphql/test/cases/exp-prerender.query-children/src/components/posts-list.js
+++ b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/components/posts-list.js
@@ -1,5 +1,5 @@
import client from '@greenwood/plugin-graphql/src/core/client.js';
-import ChildrenQuery from '@greenwood/plugin-graphql/src/queries/children.gql';
+import ChildrenQuery from '@greenwood/plugin-graphql/src/queries/children.gql' with { type: 'gql' };
export default class PostsList extends HTMLElement {
async connectedCallback() {
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/src/pages/blog/first-post/index.md b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/pages/blog/first-post/index.md
similarity index 100%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/src/pages/blog/first-post/index.md
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/pages/blog/first-post/index.md
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/src/pages/blog/second-post/index.md b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/pages/blog/second-post/index.md
similarity index 100%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/src/pages/blog/second-post/index.md
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/pages/blog/second-post/index.md
diff --git a/packages/plugin-graphql/test/cases/exp-prerender.query-children/src/pages/index.html b/packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/pages/index.html
similarity index 100%
rename from packages/plugin-graphql/test/cases/exp-prerender.query-children/src/pages/index.html
rename to packages/plugin-graphql/test/cases/loaders-prerender.query-children/src/pages/index.html
diff --git a/packages/plugin-import-css/README.md b/packages/plugin-import-css/README.md
index 0304e04a0..0b1d603ab 100644
--- a/packages/plugin-import-css/README.md
+++ b/packages/plugin-import-css/README.md
@@ -1,5 +1,7 @@
# @greenwood/plugin-import-css
+> _**THIS PACKAGE HAS BEEN DEPRECATED**_
+
## Overview
A Greenwood plugin to allow you use ESM (`import`) syntax to load your CSS.
diff --git a/packages/plugin-import-css/package.json b/packages/plugin-import-css/package.json
index 15733c402..f56454d1c 100644
--- a/packages/plugin-import-css/package.json
+++ b/packages/plugin-import-css/package.json
@@ -1,6 +1,7 @@
{
"name": "@greenwood/plugin-import-css",
"version": "0.30.0-alpha.1",
+ "private": true,
"description": "A Greenwood plugin to allow you to use ESM (import) syntax to load your CSS.",
"repository": "https://github.com/ProjectEvergreen/greenwood",
"homepage": "https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-css",
@@ -20,9 +21,6 @@
"files": [
"src/"
],
- "publishConfig": {
- "access": "public"
- },
"peerDependencies": {
"@greenwood/cli": "^0.4.0"
},
diff --git a/packages/plugin-import-css/test/cases/default/default.spec.js b/packages/plugin-import-css/test/cases/default/default.spec.js
index ea53973b3..c8bf0c527 100644
--- a/packages/plugin-import-css/test/cases/default/default.spec.js
+++ b/packages/plugin-import-css/test/cases/default/default.spec.js
@@ -35,7 +35,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;
-describe('Build Greenwood With: ', function() {
+xdescribe('Build Greenwood With: ', function() {
const LABEL = 'Import CSS Plugin with default options';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-css/test/cases/develop.default/develop.default.spec.js b/packages/plugin-import-css/test/cases/develop.default/develop.default.spec.js
index 75e21bc9e..c622637c0 100644
--- a/packages/plugin-import-css/test/cases/develop.default/develop.default.spec.js
+++ b/packages/plugin-import-css/test/cases/develop.default/develop.default.spec.js
@@ -30,7 +30,7 @@ import { runSmokeTest } from '../../../../../test/smoke-test.js';
const expect = chai.expect;
-describe('Develop Greenwood With: ', function() {
+xdescribe('Develop Greenwood With: ', function() {
const LABEL = 'Import CSS plugin for using ESM with .css files';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-css/test/cases/exp-build.prerender/exp-build.prerender.spec.js b/packages/plugin-import-css/test/cases/exp-build.prerender/exp-build.prerender.spec.js
index ff1a89771..659ffc324 100644
--- a/packages/plugin-import-css/test/cases/exp-build.prerender/exp-build.prerender.spec.js
+++ b/packages/plugin-import-css/test/cases/exp-build.prerender/exp-build.prerender.spec.js
@@ -39,7 +39,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;
-describe('(Experimental) Build Greenwood With: ', function() {
+xdescribe('(Experimental) Build Greenwood With: ', function() {
const LABEL = 'Import CSS Plugin with static pre-rendering';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-css/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js b/packages/plugin-import-css/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
index f6a59d218..63bd0373d 100644
--- a/packages/plugin-import-css/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
+++ b/packages/plugin-import-css/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
@@ -38,7 +38,7 @@ import { fileURLToPath } from 'url';
const expect = chai.expect;
-describe('Serve Greenwood With: ', function() {
+xdescribe('Serve Greenwood With: ', function() {
const LABEL = 'A Server Rendered Application (SSR) with API Routes importing CSS';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-json/README.md b/packages/plugin-import-json/README.md
index d46f15169..d9b9cd077 100644
--- a/packages/plugin-import-json/README.md
+++ b/packages/plugin-import-json/README.md
@@ -1,5 +1,7 @@
# @greenwood/plugin-import-json
+> _**THIS PACKAGE HAS BEEN DEPRECATED**_
+
## Overview
A Greenwood plugin to allow you use ESM (`import`) syntax to load your JSON.
diff --git a/packages/plugin-import-json/package.json b/packages/plugin-import-json/package.json
index dfc168f34..4083ef1a0 100644
--- a/packages/plugin-import-json/package.json
+++ b/packages/plugin-import-json/package.json
@@ -1,6 +1,7 @@
{
"name": "@greenwood/plugin-import-json",
"version": "0.30.0-alpha.1",
+ "private": true,
"description": "A Greenwood plugin to allow you to use ESM (import) syntax to load your JSON.",
"repository": "https://github.com/ProjectEvergreen/greenwood",
"homepage": "https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-json",
@@ -20,9 +21,6 @@
"files": [
"src/"
],
- "publishConfig": {
- "access": "public"
- },
"peerDependencies": {
"@greenwood/cli": "^0.12.3"
},
diff --git a/packages/plugin-import-json/test/cases/default/default.spec.js b/packages/plugin-import-json/test/cases/default/default.spec.js
index fb168439a..dfd8a1aeb 100644
--- a/packages/plugin-import-json/test/cases/default/default.spec.js
+++ b/packages/plugin-import-json/test/cases/default/default.spec.js
@@ -37,7 +37,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;
-describe('Build Greenwood With: ', function() {
+xdescribe('Build Greenwood With: ', function() {
const LABEL = 'Import JSON Plugin with default options';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-json/test/cases/develop.default/develop.default.spec.js b/packages/plugin-import-json/test/cases/develop.default/develop.default.spec.js
index a0b298cdc..b96adc6c1 100644
--- a/packages/plugin-import-json/test/cases/develop.default/develop.default.spec.js
+++ b/packages/plugin-import-json/test/cases/develop.default/develop.default.spec.js
@@ -31,7 +31,7 @@ import { runSmokeTest } from '../../../../../test/smoke-test.js';
const expect = chai.expect;
-describe('Develop Greenwood With: ', function() {
+xdescribe('Develop Greenwood With: ', function() {
const LABEL = 'Import JSON plugin for using ESM with .json files';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-json/test/cases/exp-build.prerender/exp-build.prerender.spec.js b/packages/plugin-import-json/test/cases/exp-build.prerender/exp-build.prerender.spec.js
index c33d8f616..28bd48bff 100644
--- a/packages/plugin-import-json/test/cases/exp-build.prerender/exp-build.prerender.spec.js
+++ b/packages/plugin-import-json/test/cases/exp-build.prerender/exp-build.prerender.spec.js
@@ -39,7 +39,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;
-describe('(Experimental) Build Greenwood With: ', function() {
+xdescribe('(Experimental) Build Greenwood With: ', function() {
const LABEL = 'Import JSON Plugin with static pre-rendering';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-json/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js b/packages/plugin-import-json/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
index 770c4c163..bc4b70af5 100644
--- a/packages/plugin-import-json/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
+++ b/packages/plugin-import-json/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
@@ -35,7 +35,7 @@ import { fileURLToPath } from 'url';
const expect = chai.expect;
-describe('Serve Greenwood With: ', function() {
+xdescribe('Serve Greenwood With: ', function() {
const LABEL = 'A Server Rendered Application (SSR) with API Routes importing JSON';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-jsx/README.md b/packages/plugin-import-jsx/README.md
index 9de639612..f9dab1e06 100644
--- a/packages/plugin-import-jsx/README.md
+++ b/packages/plugin-import-jsx/README.md
@@ -51,11 +51,10 @@ export default class FooterComponent extends HTMLElement {
customElements.define('app-footer', FooterComponent);
```
-A couple notes:
+### Notes
+
- For SSR and `prerender` use cases, [follow these steps](/docs/server-rendering/#custom-imports-experimental)
-- For client side / browser code specifically, it is recommended to append `?type=jsx`, e.g.
+- For client side / browser code specifically, it is recommended to use import attributes syntax, e.g.
```js
- import '../path/to/footer.jsx?type=jsx';
- ```
-
-> _The plan is to coalesce around [import assertions](https://github.com/ProjectEvergreen/greenwood/issues/923) in time for the v1.0 release so the same standard syntax can be used on the client and the server._
\ No newline at end of file
+ import '../path/to/footer.jsx' with { type: 'jsx' };
+ ```
\ No newline at end of file
diff --git a/packages/plugin-import-jsx/package.json b/packages/plugin-import-jsx/package.json
index b51e9d4cb..6c8803ac3 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.12.1"
+ "wc-compiler": "~0.13.0"
},
"devDependencies": {
"@greenwood/cli": "^0.30.0-alpha.1"
diff --git a/packages/plugin-import-jsx/src/index.js b/packages/plugin-import-jsx/src/index.js
index ac02dc6c4..36b678721 100644
--- a/packages/plugin-import-jsx/src/index.js
+++ b/packages/plugin-import-jsx/src/index.js
@@ -15,13 +15,14 @@ class ImportJsxResource extends ResourceInterface {
}
async shouldServe(url) {
- const { pathname } = url;
+ const { pathname, protocol } = url;
+ const ext = pathname.split('.').pop();
- return pathname.split('.').pop() === this.extensions[0] && (url.searchParams.has('type') && url.searchParams.get('type') === this.extensions[0]);
+ return protocol === 'file:' && ext === this.extensions[0];
}
async serve(url) {
- // TODO refactor when WCC refactors
+ // refactor when WCC refactors
// https://github.com/ProjectEvergreen/wcc/issues/116
const tree = parseJsx(url);
const result = escodegen.generate(tree);
diff --git a/packages/plugin-import-jsx/test/cases/default/src/templates/app.html b/packages/plugin-import-jsx/test/cases/default/src/templates/app.html
index 970f7016c..2d99e73e2 100644
--- a/packages/plugin-import-jsx/test/cases/default/src/templates/app.html
+++ b/packages/plugin-import-jsx/test/cases/default/src/templates/app.html
@@ -1,7 +1,7 @@
My Personal Website
-
+
diff --git a/packages/plugin-import-jsx/test/cases/exp-build.prerender/greenwood.config.js b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/greenwood.config.js
similarity index 100%
rename from packages/plugin-import-jsx/test/cases/exp-build.prerender/greenwood.config.js
rename to packages/plugin-import-jsx/test/cases/loaders-build.prerender/greenwood.config.js
diff --git a/packages/plugin-import-jsx/test/cases/exp-build.prerender/exp-build.prerender.spec.js b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/loaders-build.prerender.spec.js
similarity index 97%
rename from packages/plugin-import-jsx/test/cases/exp-build.prerender/exp-build.prerender.spec.js
rename to packages/plugin-import-jsx/test/cases/loaders-build.prerender/loaders-build.prerender.spec.js
index dc6914c57..bcb0e615c 100644
--- a/packages/plugin-import-jsx/test/cases/exp-build.prerender/exp-build.prerender.spec.js
+++ b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/loaders-build.prerender.spec.js
@@ -27,6 +27,7 @@
* index.md
* templates/
* app.html
+ * main.js
*/
import chai from 'chai';
import glob from 'glob-promise';
@@ -39,7 +40,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;
-describe('(Experimental) Build Greenwood With: ', function() {
+describe('Build Greenwood With: ', function() {
const LABEL = 'Import JSX Plugin with static pre-rendering';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
diff --git a/packages/plugin-import-jsx/test/cases/exp-build.prerender/package.json b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/package.json
similarity index 100%
rename from packages/plugin-import-jsx/test/cases/exp-build.prerender/package.json
rename to packages/plugin-import-jsx/test/cases/loaders-build.prerender/package.json
diff --git a/packages/plugin-import-jsx/test/cases/exp-build.prerender/src/components/footer.jsx b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/components/footer.jsx
similarity index 100%
rename from packages/plugin-import-jsx/test/cases/exp-build.prerender/src/components/footer.jsx
rename to packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/components/footer.jsx
diff --git a/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/main.js b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/main.js
new file mode 100644
index 000000000..52c14ef72
--- /dev/null
+++ b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/main.js
@@ -0,0 +1 @@
+import './components/footer.jsx' with { type: 'jsx' };
\ No newline at end of file
diff --git a/packages/plugin-import-jsx/test/cases/exp-build.prerender/src/pages/index.md b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/pages/index.md
similarity index 100%
rename from packages/plugin-import-jsx/test/cases/exp-build.prerender/src/pages/index.md
rename to packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/pages/index.md
diff --git a/packages/plugin-import-jsx/test/cases/exp-build.prerender/src/templates/app.html b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/templates/app.html
similarity index 61%
rename from packages/plugin-import-jsx/test/cases/exp-build.prerender/src/templates/app.html
rename to packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/templates/app.html
index b17ccc360..636405140 100644
--- a/packages/plugin-import-jsx/test/cases/exp-build.prerender/src/templates/app.html
+++ b/packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/templates/app.html
@@ -1,7 +1,7 @@
My Personal Website
-
+
diff --git a/packages/plugin-import-raw/README.md b/packages/plugin-import-raw/README.md
new file mode 100644
index 000000000..61c33e867
--- /dev/null
+++ b/packages/plugin-import-raw/README.md
@@ -0,0 +1,63 @@
+# @greenwood/plugin-import-raw
+
+## Overview
+
+A Greenwood plugin to use ESM (`import`) syntax to load any file contents as a string exported as a JavaScript module. Inspired by **webpack**'s [raw loader](https://v4.webpack.js.org/loaders/raw-loader/).
+
+> This package assumes you already have `@greenwood/cli` installed.
+
+## Installation
+You can use your favorite JavaScript package manager to install this package.
+
+_examples:_
+```bash
+# npm
+npm install @greenwood/plugin-import-raw --save-dev
+
+# yarn
+yarn add @greenwood/plugin-import-raw --dev
+```
+
+## Usage
+Add this plugin to your _greenwood.config.js_ and spread the `export`.
+
+```javascript
+import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
+
+export default {
+ // ...
+
+ plugins: [
+ greenwoodPluginImportRaw()
+ ]
+}
+```
+
+This will then allow you to use ESM (`import`) to include any file as an arbitrary string exported as a JavaScript module.
+```js
+import css from '../path/to/styles.css?type=raw'; // must be a relative path per ESM spec
+
+console.log(css); // h1 { color: red }
+```
+
+> For libraries like Material Web Components, this plugin will [resolve references to _some-file.css_ if the equivalent exists that ends in _.js_ (e.g. _styles.css.js_)](https://github.com/ProjectEvergreen/greenwood/issues/700).
+
+## Options
+
+### Matches
+
+Optionally, you can provide an array of "matcher" patterns for the plugin to transform custom paths, which can be useful for handling imports you can't change, like third party files in _node_modules_.
+
+```javascript
+import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
+
+export default {
+ plugins: [
+ greenwoodPluginImportRaw({
+ matches: [
+ '/node_modules/some-package/dist/styles.css'
+ ]
+ })
+ ]
+}
+```
\ No newline at end of file
diff --git a/packages/plugin-import-raw/package.json b/packages/plugin-import-raw/package.json
new file mode 100644
index 000000000..c6d8a568c
--- /dev/null
+++ b/packages/plugin-import-raw/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@greenwood/plugin-import-raw",
+ "version": "0.30.0-alpha.1",
+ "description": "A Greenwood plugin to allow you to use ESM (import) syntax to load any file content as a string.",
+ "repository": "https://github.com/ProjectEvergreen/greenwood",
+ "homepage": "https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-raw",
+ "author": "Owen Buckley ",
+ "license": "MIT",
+ "keywords": [
+ "Greenwood",
+ "Static Site Generator",
+ "Full Stack Web Development",
+ "Web Components",
+ "NodeJS",
+ "ESM"
+ ],
+ "main": "src/index.js",
+ "type": "module",
+ "files": [
+ "src/"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "peerDependencies": {
+ "@greenwood/cli": "^0.4.0"
+ },
+ "devDependencies": {
+ "@greenwood/cli": "^0.30.0-alpha.1"
+ }
+}
diff --git a/packages/plugin-import-raw/src/index.js b/packages/plugin-import-raw/src/index.js
new file mode 100644
index 000000000..499b7e382
--- /dev/null
+++ b/packages/plugin-import-raw/src/index.js
@@ -0,0 +1,67 @@
+/*
+ *
+ * Enables using JavaScript to import any type of file as a string using ESM syntax.
+ *
+ */
+import { ResourceInterface } from '@greenwood/cli/src/lib/resource-interface.js';
+
+class ImportRawResource extends ResourceInterface {
+ constructor(compilation, options) {
+ super(compilation, options);
+
+ this.contentType = 'text/javascript';
+ }
+
+ async shouldResolve(url) {
+ const matches = (this.options.matches || []).filter(matcher => url.href.indexOf(matcher) >= 0);
+
+ if (matches.length > 0 && !url.searchParams.has('type')) {
+ return true;
+ }
+ }
+
+ async resolve(url) {
+ const { projectDirectory } = this.compilation.context;
+ const { pathname, searchParams } = url;
+ const params = url.searchParams.size > 0
+ ? `${searchParams.toString()}&type=raw`
+ : 'type=raw';
+ const root = pathname.startsWith('file://')
+ ? new URL(`file://${pathname}`).href
+ : pathname.startsWith('/node_modules')
+ ? new URL(`.${pathname}`, projectDirectory).href
+ : new URL(`file://${pathname}`);
+ const matchedUrl = new URL(`${root}?${params}`);
+
+ return new Request(matchedUrl);
+ }
+
+ async shouldIntercept(url, request) {
+ const matches = (this.options.matches || []).filter(matcher => url.href.indexOf(matcher) >= 0);
+ const type = url.searchParams.get('type');
+ const dest = request.headers.get('Sec-Fetch-Dest');
+
+ return (url.protocol === 'file:' && type === 'raw' && dest === 'empty') || matches.length > 0;
+ }
+
+ async intercept(url, request, response) {
+ const body = await response.text();
+ const contents = `const raw = \`${body.replace(/\r?\n|\r/g, ' ').replace(/\\/g, '\\\\')}\`;\nexport default raw;`;
+
+ return new Response(contents, {
+ headers: new Headers({
+ 'Content-Type': this.contentType
+ })
+ });
+ }
+}
+
+const greenwoodPluginImportRaw = (options = {}) => {
+ return [{
+ type: 'resource',
+ name: 'plugin-import-raw:resource',
+ provider: (compilation) => new ImportRawResource(compilation, options)
+ }];
+};
+
+export { greenwoodPluginImportRaw };
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/build.matchers/build.matchers.spec.js b/packages/plugin-import-raw/test/cases/build.matchers/build.matchers.spec.js
new file mode 100644
index 000000000..8580fe09b
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/build.matchers/build.matchers.spec.js
@@ -0,0 +1,84 @@
+/*
+ * Use Case
+ * Run Greenwood and be able to load arbitrary content as a string using ESM.
+ *
+ * User Result
+ * Should generate a bare bones Greenwood build without erroring when using ESM (import) as a string value.
+ *
+ * User Command
+ * greenwood build
+ *
+ * User Config
+ * import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
+ *
+ * {
+ * plugins: [{
+ * greenwoodPluginImportRaw({
+ * matches: [
+ * 'eve-container.css'
+ * ]
+ * })
+ * }]
+ * }
+ *
+ * User Workspace
+ * src/
+ * pages/
+ * index.html
+ * main.js
+ */
+import chai from 'chai';
+import fs from 'fs';
+import glob from 'glob-promise';
+import path from 'path';
+import { runSmokeTest } from '../../../../../test/smoke-test.js';
+import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Build Greenwood With: ', function() {
+ const LABEL = 'Import Raw Plugin with default options';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner();
+ });
+
+ describe(LABEL, function() {
+ before(function() {
+ runner.setup(outputPath, getSetupFiles(outputPath));
+ runner.runCommand(cliPath, 'build');
+ });
+
+ runSmokeTest(['public', 'index'], LABEL);
+
+ describe('Importing a string of CSS using ESM (import)', function() {
+ let scripts;
+
+ before(async function() {
+ scripts = await glob.promise(path.join(this.context.publicDir, '*.js'));
+ });
+
+ it('should contain one (CSS-in) JavaScript file in the output directory', function() {
+ expect(scripts.length).to.be.equal(1);
+ });
+
+ it('should have the expected output from importing styles.css in main.js', function() {
+ const contents = fs.readFileSync(scripts[0], 'utf-8');
+
+ expect(contents).to.contain('console.log({css:"@custom-media --screen-xs');
+ });
+ });
+ });
+
+ after(function() {
+ runner.teardown(getOutputTeardownFiles(outputPath));
+ });
+});
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/build.matchers/greenwood.config.js b/packages/plugin-import-raw/test/cases/build.matchers/greenwood.config.js
new file mode 100644
index 000000000..0cc263059
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/build.matchers/greenwood.config.js
@@ -0,0 +1,12 @@
+import { greenwoodPluginImportRaw } from '../../../src/index.js';
+
+export default {
+
+ plugins: [
+ greenwoodPluginImportRaw({
+ matches: [
+ 'eve-container.css'
+ ]
+ })
+ ]
+};
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/build.matchers/src/main.js b/packages/plugin-import-raw/test/cases/build.matchers/src/main.js
new file mode 100644
index 000000000..e90390161
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/build.matchers/src/main.js
@@ -0,0 +1,3 @@
+import css from '@evergreen-wc/eve-container/src/eve-container.css';
+
+console.log({ css });
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/build.matchers/src/pages/index.html b/packages/plugin-import-raw/test/cases/build.matchers/src/pages/index.html
new file mode 100644
index 000000000..e58731458
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/build.matchers/src/pages/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/default/default.spec.js b/packages/plugin-import-raw/test/cases/default/default.spec.js
new file mode 100644
index 000000000..3aa11e5e8
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/default/default.spec.js
@@ -0,0 +1,83 @@
+/*
+ * Use Case
+ * Run Greenwood and be able to load arbitrary content as a string using ESM.
+ *
+ * User Result
+ * Should generate a bare bones Greenwood build without erroring when using ESM (import) as a string value.
+ *
+ * User Command
+ * greenwood build
+ *
+ * User Config
+ * import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
+ *
+ * {
+ * plugins: [{
+ * greenwoodPluginImportRaw()
+ * }]
+ * }
+ *
+ * User Workspace
+ * src/
+ * pages/
+ * index.html
+ * main.js
+ * styles.css
+ */
+import chai from 'chai';
+import fs from 'fs';
+import glob from 'glob-promise';
+import path from 'path';
+import { runSmokeTest } from '../../../../../test/smoke-test.js';
+import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Build Greenwood With: ', function() {
+ const LABEL = 'Import Raw Plugin with default options';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner();
+ });
+
+ describe(LABEL, function() {
+ before(function() {
+ runner.setup(outputPath, getSetupFiles(outputPath));
+ runner.runCommand(cliPath, 'build');
+ });
+
+ runSmokeTest(['public', 'index'], LABEL);
+
+ describe('Importing a string of CSS using ESM (import)', function() {
+ let scripts;
+
+ before(async function() {
+ scripts = await glob.promise(path.join(this.context.publicDir, '*.js'));
+ });
+
+ it('should contain one (CSS-in) JavaScript file in the output directory', function() {
+ expect(scripts.length).to.be.equal(1);
+ });
+
+ it('should have the expected output from importing styles.css in main.js', function() {
+ const contents = fs.readFileSync(scripts[0], 'utf-8');
+
+ // TODO minify CSS-in-JS?
+ expect(contents).to.contain('import from styles.css: p { color: red; }"');
+ });
+ });
+ });
+
+ after(function() {
+ runner.teardown(getOutputTeardownFiles(outputPath));
+ });
+
+});
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/default/greenwood.config.js b/packages/plugin-import-raw/test/cases/default/greenwood.config.js
new file mode 100644
index 000000000..b1c45a9a5
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/default/greenwood.config.js
@@ -0,0 +1,8 @@
+import { greenwoodPluginImportRaw } from '../../../src/index.js';
+
+export default {
+
+ plugins: [
+ greenwoodPluginImportRaw()
+ ]
+};
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/default/src/main.js b/packages/plugin-import-raw/test/cases/default/src/main.js
new file mode 100644
index 000000000..a60786bca
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/default/src/main.js
@@ -0,0 +1,3 @@
+import stylesCss from './styles.css?type=raw';
+
+document.getElementsByTagName('span')[0].innerHTML = `import from styles.css: ${stylesCss}`;
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/default/src/pages/index.html b/packages/plugin-import-raw/test/cases/default/src/pages/index.html
new file mode 100644
index 000000000..e58731458
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/default/src/pages/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/default/src/styles.css b/packages/plugin-import-raw/test/cases/default/src/styles.css
new file mode 100644
index 000000000..e21e2c285
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/default/src/styles.css
@@ -0,0 +1,3 @@
+p {
+ color: red;
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/develop.default/develop.default.spec.js b/packages/plugin-import-raw/test/cases/develop.default/develop.default.spec.js
new file mode 100644
index 000000000..eb99f4e35
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/develop.default/develop.default.spec.js
@@ -0,0 +1,126 @@
+/*
+ * Use Case
+ * Run Greenwood develop command with no raw plugin.
+ *
+ * User Result
+ * Should start the development server and render a bare bones Greenwood build and return CSS file as a string using ESM.
+ *
+ * User Command
+ * greenwood develop
+ *
+ * User Config
+ * import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
+ *
+ * {
+ * plugins: [{
+ * greenwoodPluginImportRaw()
+ * }]
+ * }
+ *
+ * User Workspace
+ * src/
+ * main.css
+ * style.css.js
+ *
+ */
+import chai from 'chai';
+import path from 'path';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+import { runSmokeTest } from '../../../../../test/smoke-test.js';
+
+const expect = chai.expect;
+
+describe('Develop Greenwood With: ', function() {
+ const LABEL = 'Import Raw plugin for using ESM with arbitrary files as strings';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ const hostname = 'http://localhost';
+ const port = 1984;
+ let runner;
+
+ before(function() {
+ this.context = {
+ hostname: `${hostname}:${port}`
+ };
+ runner = new Runner();
+ });
+
+ describe(LABEL, function() {
+
+ before(async function() {
+ runner.setup(outputPath);
+
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, 5000);
+
+ runner.runCommand(cliPath, 'develop', { async: true });
+ });
+ });
+
+ runSmokeTest(['serve'], LABEL);
+
+ describe('Develop command with raw ESM behaviors with CSS', function() {
+ let response = {};
+ let data;
+
+ before(async function() {
+ response = await fetch(`${hostname}:${port}/main.css?type=raw`, {
+ headers: {
+ 'Sec-Fetch-Dest': 'empty'
+ }
+ });
+ data = await response.text();
+ });
+
+ it('should return a 200', function() {
+ expect(response.status).to.equal(200);
+ });
+
+ it('should return the correct content type', function() {
+ expect(response.headers.get('content-type')).to.equal('text/javascript');
+ });
+
+ // https://github.com/ProjectEvergreen/greenwood/issues/766
+ // https://unpkg.com/browse/bootstrap@4.6.1/dist/css/bootstrap.css
+ // https://unpkg.com/browse/font-awesome@4.7.0/css/font-awesome.css
+ it('should return an ECMASCript module', function() {
+ expect(data.replace('\n', '').replace(/ /g, '').trim())
+ .to.equal('constraw=`*{background-image:url("/assets/background.jpg");font-family:\'Arial\'}.blockquote-footer::before{content:"\\\\2014\\\\00A0";}.fa-chevron-right:before{content:"\\\\f054";}`;exportdefaultraw;'); // eslint-disable-line max-len
+ });
+ });
+
+ // https://github.com/ProjectEvergreen/greenwood/pull/747
+ // https://unpkg.com/browse/@material/mwc-button@0.22.1/styles.css.js
+ xdescribe('Develop command for .css.js files behaviors (CSS in disguise)', function() {
+ let response = {};
+ let data;
+
+ before(async function() {
+ response = await fetch(`${hostname}:${port}/styles.css.js`);
+ data = await response.text();
+ });
+
+ it('should return a 200', function() {
+ expect(response.status).to.equal(200);
+ });
+
+ it('should return the correct content type', function() {
+ expect(response.headers.get('content-type')).to.equal('text/javascript');
+ });
+
+ it('should return an ECMASCript module', function() {
+ expect(data).to.equal('export const styles = css `.mdc-touch-target-wrapper{display:inline}`;');
+ });
+ });
+ });
+
+ after(function() {
+ runner.stopCommand();
+ runner.teardown([
+ path.join(outputPath, '.greenwood')
+ ]);
+ });
+});
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/develop.default/greenwood.config.js b/packages/plugin-import-raw/test/cases/develop.default/greenwood.config.js
new file mode 100644
index 000000000..da910c5a6
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/develop.default/greenwood.config.js
@@ -0,0 +1,7 @@
+import { greenwoodPluginImportRaw } from '../../../src/index.js';
+
+export default {
+ plugins: [
+ greenwoodPluginImportRaw()
+ ]
+};
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/develop.default/package.json b/packages/plugin-import-raw/test/cases/develop.default/package.json
new file mode 100644
index 000000000..1105aa77c
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/develop.default/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "test-plugin-import-raw-css-develop-default",
+ "type": "module"
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/develop.default/src/main.css b/packages/plugin-import-raw/test/cases/develop.default/src/main.css
new file mode 100644
index 000000000..f5ae38ad4
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/develop.default/src/main.css
@@ -0,0 +1,12 @@
+* {
+ background-image: url("/assets/background.jpg");
+ font-family: 'Arial'
+}
+
+.blockquote-footer::before {
+ content: "\2014\00A0";
+}
+
+.fa-chevron-right:before {
+ content: "\f054";
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/develop.default/src/styles.css.js b/packages/plugin-import-raw/test/cases/develop.default/src/styles.css.js
new file mode 100644
index 000000000..12bcd6b16
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/develop.default/src/styles.css.js
@@ -0,0 +1 @@
+export const styles = css `.mdc-touch-target-wrapper{display:inline}`;
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/greenwood.config.js b/packages/plugin-import-raw/test/cases/loaders-build.prerender/greenwood.config.js
new file mode 100644
index 000000000..e7c9f2d37
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/greenwood.config.js
@@ -0,0 +1,8 @@
+import { greenwoodPluginImportRaw } from '../../../src/index.js';
+
+export default {
+ prerender: true,
+ plugins: [
+ greenwoodPluginImportRaw()
+ ]
+};
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/loaders-build.prerender.spec.js b/packages/plugin-import-raw/test/cases/loaders-build.prerender/loaders-build.prerender.spec.js
new file mode 100644
index 000000000..ccbb5efe8
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/loaders-build.prerender.spec.js
@@ -0,0 +1,90 @@
+/*
+ * Use Case
+ * Run Greenwood with a plugin during prerendering to be able to import arbitrary text as a string using ESM.
+ *
+ * User Result
+ * Should generate a static Greenwood build with CSS properly prerendered.
+ *
+ * User Command
+ * greenwood build
+ *
+ * User Config
+ * import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
+ *
+ * {
+ * prerender: true,
+ * plugins: [{
+ * greenwoodPluginImportRaw()
+ * }]
+ * }
+ *
+ * User Workspace
+ * src/
+ * components/
+ * footer.css
+ * footer.js
+ * pages/
+ * index.md
+ * templates/
+ * app.html
+ */
+import chai from 'chai';
+import glob from 'glob-promise';
+import { JSDOM } from 'jsdom';
+import path from 'path';
+import { runSmokeTest } from '../../../../../test/smoke-test.js';
+import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Build Greenwood With: ', function() {
+ const LABEL = 'Import Raw Plugin with static pre-rendering for CSS as a string';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+ before(function() {
+ runner.setup(outputPath, getSetupFiles(outputPath));
+ runner.runCommand(cliPath, 'build');
+ });
+
+ runSmokeTest(['public'], LABEL);
+
+ describe('Importing CSS as a string using ESM (import)', function() {
+ let dom;
+ let scripts;
+
+ before(async function() {
+ scripts = await glob.promise(path.join(this.context.publicDir, '*.js'));
+ dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './index.html'));
+ });
+
+ it('should contain no (CSS-in) JavaScript file in the output directory', function() {
+ expect(scripts.length).to.be.equal(0);
+ });
+
+ it('should have the expected output from importing styles.css in index.html', function() {
+ const styles = dom.window.document.querySelectorAll('style');
+
+ // TODO minify CSS-in-JS?
+ expect(styles.length).to.equal(1);
+ expect(styles[0].textContent).to.contain('.footer { width: 90%; margin: 0 auto; padding: 0; text-align: center; }');
+ });
+ });
+ });
+
+ after(function() {
+ runner.teardown(getOutputTeardownFiles(outputPath));
+ });
+
+});
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/package.json b/packages/plugin-import-raw/test/cases/loaders-build.prerender/package.json
new file mode 100644
index 000000000..606abcb6a
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "test-plugin-import-raw-css-build-prerender",
+ "type": "module"
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/components/footer.css b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/components/footer.css
new file mode 100644
index 000000000..9141c1418
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/components/footer.css
@@ -0,0 +1 @@
+.footer { width: 90%; margin: 0 auto; padding: 0; text-align: center; }
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/components/footer.js b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/components/footer.js
new file mode 100644
index 000000000..388ad54f6
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/components/footer.js
@@ -0,0 +1,25 @@
+import css from './footer.css?type=raw';
+
+export default class FooterComponent extends HTMLElement {
+ connectedCallback() {
+ this.innerHTML = this.getTemplate();
+ }
+
+ getTemplate() {
+ const year = new Date().getFullYear();
+
+ return `
+
+
+
+ `;
+ }
+}
+
+customElements.define('app-footer', FooterComponent);
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/pages/index.md b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/pages/index.md
new file mode 100644
index 000000000..82c330a89
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/pages/index.md
@@ -0,0 +1,3 @@
+# Home Page
+
+Welcome to the home page!
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/templates/app.html b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/templates/app.html
new file mode 100644
index 000000000..7c394fe4b
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-build.prerender/src/templates/app.html
@@ -0,0 +1,12 @@
+
+
+ My Personal Website
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/greenwood.config.js b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/greenwood.config.js
new file mode 100644
index 000000000..da910c5a6
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/greenwood.config.js
@@ -0,0 +1,7 @@
+import { greenwoodPluginImportRaw } from '../../../src/index.js';
+
+export default {
+ plugins: [
+ greenwoodPluginImportRaw()
+ ]
+};
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/loaders-serve.ssr.spec.js b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/loaders-serve.ssr.spec.js
new file mode 100644
index 000000000..9c6c84a5e
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/loaders-serve.ssr.spec.js
@@ -0,0 +1,152 @@
+/*
+ * Use Case
+ * Run Greenwood with an API and SSR routes that import raw CSS as a string.
+ *
+ * User Result
+ * Should generate a Greenwood build that correctly builds and bundles all assets.
+ *
+ * User Command
+ * greenwood build
+ *
+ * User Config
+ * {
+ * plugins: [
+ * greenwoodPluginImportRaw()
+ * ]
+ * }
+ *
+ * User Workspace
+ * src/
+ * api/
+ * fragment.js
+ * components/
+ * card.js
+ * card.css
+ * pages/
+ * products.js
+ * services/
+ * products.js
+ * styles/
+ * some.css
+ */
+import chai from 'chai';
+import { JSDOM } from 'jsdom';
+import path from 'path';
+import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
+import { Runner } from 'gallinago';
+import { fileURLToPath } from 'url';
+
+const expect = chai.expect;
+
+describe('Serve Greenwood With: ', function() {
+ const LABEL = 'A Server Rendered Application (SSR) with API Routes importing raw CSS';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ const hostname = 'http://localhost:8080';
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public'),
+ hostname
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+
+ before(async function() {
+ runner.setup(outputPath, getSetupFiles(outputPath));
+ runner.runCommand(cliPath, 'build');
+
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, 10000);
+
+ runner.runCommand(cliPath, 'serve', { async: true });
+ });
+ });
+
+ describe('Serve command with HTML route response for products page', function() {
+ let response = {};
+ let data;
+ let productsPageDom;
+
+ before(async function() {
+ response = await fetch(`${hostname}/products/`);
+ data = await response.text();
+ productsPageDom = new JSDOM(data);
+ });
+
+ it('should return a 200 status', function() {
+ expect(response.status).to.equal(200);
+ });
+
+ it('should return the correct content type', function() {
+ expect(response.headers.get('content-type')).to.equal('text/html');
+ });
+
+ it('should return a response body', function() {
+ expect(data).to.not.be.undefined;
+ });
+
+ it('should have the expected import CSS in the page in the response body', function(done) {
+ const styleTag = productsPageDom.window.document.querySelectorAll('body > style');
+
+ expect(styleTag.length).to.equal(1);
+ expect(styleTag[0].textContent.replace(/ /g, '').replace(/\n/, '')).contain('h1{color:red;}');
+ done();
+ });
+
+ it('should make sure to have the expected CSS inlined into the page for each ', function(done) {
+ const cardComponents = productsPageDom.window.document.querySelectorAll('body app-card');
+
+ expect(cardComponents.length).to.equal(2);
+ Array.from(cardComponents).forEach((card) => {
+ expect(card.innerHTML).contain('display: flex;');
+ });
+ done();
+ });
+ });
+
+ describe('Serve command with API specific behaviors for an HTML ("fragment") API', function() {
+ let response = {};
+ let fragmentsApiDom;
+
+ before(async function() {
+ response = await fetch(`${hostname}/api/fragment`);
+ const body = await response.clone().text();
+ fragmentsApiDom = new JSDOM(body);
+ });
+
+ it('should return a 200 status', function() {
+ expect(response.status).to.equal(200);
+ });
+
+ it('should return a custom status message', function() {
+ expect(response.statusText).to.equal('OK');
+ });
+
+ it('should return the correct content type', function() {
+ expect(response.headers.get('content-type')).to.equal('text/html');
+ });
+
+ it('should make sure to have the expected CSS inlined into the page for each ', function(done) {
+ const cardComponents = fragmentsApiDom.window.document.querySelectorAll('body > app-card');
+
+ expect(cardComponents.length).to.equal(2);
+ Array.from(cardComponents).forEach((card) => {
+ expect(card.innerHTML).contain('display: flex;');
+ });
+ done();
+ });
+ });
+ });
+
+ after(function() {
+ runner.teardown(getOutputTeardownFiles(outputPath));
+ runner.stopCommand();
+ });
+
+});
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/package.json b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/package.json
new file mode 100644
index 000000000..31d099455
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "test-plugin-import-raw-css-serve-ssr",
+ "type": "module"
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/api/fragment.js b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/api/fragment.js
new file mode 100644
index 000000000..af4ced829
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/api/fragment.js
@@ -0,0 +1,28 @@
+import { renderFromHTML } from 'wc-compiler';
+import { getProducts } from '../services/products.js';
+
+export async function handler() {
+ const products = await getProducts();
+ const { html } = await renderFromHTML(`
+ ${
+ products.map((product) => {
+ const { name, thumbnail } = product;
+
+ return `
+
+ `;
+ }).join('')
+ }
+ `, [
+ new URL('../components/card.js', import.meta.url)
+ ]);
+
+ return new Response(html, {
+ headers: new Headers({
+ 'Content-Type': 'text/html'
+ })
+ });
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/components/card.css b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/components/card.css
new file mode 100644
index 000000000..db18c7c4a
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/components/card.css
@@ -0,0 +1,44 @@
+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;
+ }
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/components/card.js b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/components/card.js
new file mode 100644
index 000000000..5ccf5dee5
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/components/card.js
@@ -0,0 +1,31 @@
+import styles from './card.css?type=raw';
+
+export default class Card extends HTMLElement {
+
+ selectItem() {
+ alert(`selected item is => ${this.getAttribute('title')}!`);
+ }
+
+ connectedCallback() {
+ if (!this.shadowRoot) {
+ const thumbnail = this.getAttribute('thumbnail');
+ const title = this.getAttribute('title');
+ const template = document.createElement('template');
+
+ template.innerHTML = `
+
+
+
${title}
+
+
View Item Details
+
+ `;
+ this.attachShadow({ mode: 'open' });
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
+ }
+ }
+}
+
+customElements.define('app-card', Card);
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/pages/products.js b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/pages/products.js
new file mode 100644
index 000000000..09ff462c8
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/pages/products.js
@@ -0,0 +1,31 @@
+import '../components/card.js';
+import { getProducts } from '../services/products.js';
+import styles from '../styles/some.css?type=raw';
+
+export default class ProductsPage extends HTMLElement {
+ async connectedCallback() {
+ const products = await getProducts();
+ const html = products.map(product => {
+ const { name, thumbnail } = product;
+
+ return `
+
+
+ `;
+ }).join('');
+
+ this.innerHTML = `
+ SSR Page (w/ WCC)
+ List of Products: ${products.length}
+
+
+ ${html}
+
+ `;
+ }
+}
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/services/products.js b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/services/products.js
new file mode 100644
index 000000000..96c999dac
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/services/products.js
@@ -0,0 +1,11 @@
+async function getProducts() {
+ return [{
+ name: 'iPhone 12',
+ thumbnail: 'iphone-12.png'
+ }, {
+ name: 'Samsung Galaxy',
+ thumbnail: 'samsung-galaxy.png'
+ }];
+}
+
+export { getProducts };
\ No newline at end of file
diff --git a/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/styles/some.css b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/styles/some.css
new file mode 100644
index 000000000..9054080ff
--- /dev/null
+++ b/packages/plugin-import-raw/test/cases/loaders-serve.ssr/src/styles/some.css
@@ -0,0 +1,3 @@
+h1 {
+ color: red;
+}
\ No newline at end of file
diff --git a/packages/plugin-postcss/README.md b/packages/plugin-postcss/README.md
index df3ff3079..739cc2c05 100644
--- a/packages/plugin-postcss/README.md
+++ b/packages/plugin-postcss/README.md
@@ -32,8 +32,6 @@ export default {
}
```
-> 👉 _If you are using this along with [**plugin-import-css**](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-css), make sure **plugin-postcss** comes first. All non standard transformations need to come last._
-
Optionally, to use your own PostCSS configuration, you'll need to create _two (2)_ config files in the root of your project, by which you can provide your own custom plugins / settings that you've installed.
- _postcss.config.js_
- _postcss.config.mjs_
diff --git a/packages/plugin-postcss/src/index.js b/packages/plugin-postcss/src/index.js
index ab4280257..305bb21f4 100644
--- a/packages/plugin-postcss/src/index.js
+++ b/packages/plugin-postcss/src/index.js
@@ -33,11 +33,13 @@ class PostCssResource extends ResourceInterface {
this.contentType = ['text/css'];
}
- async shouldIntercept(url) {
- return url.protocol === 'file:' && url.pathname.split('.').pop() === this.extensions[0];
+ async shouldPreIntercept(url, request, response) {
+ return url.protocol === 'file:'
+ && url.pathname.split('.').pop() === this.extensions[0]
+ && (request?.headers?.get('Content-Type')?.includes('text/css') || response?.headers?.get('Content-Type')?.includes('text/css'));
}
- async intercept(url, request, response) {
+ async preIntercept(url, request, response) {
const config = await getConfig(this.compilation, this.options.extendConfig);
const plugins = config.plugins || [];
const body = await response.text();
diff --git a/packages/plugin-renderer-lit/README.md b/packages/plugin-renderer-lit/README.md
index c5f867b51..8cb8e1ba6 100644
--- a/packages/plugin-renderer-lit/README.md
+++ b/packages/plugin-renderer-lit/README.md
@@ -38,8 +38,9 @@ yarn add @greenwood/plugin-renderer-lit --dev
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
+1. Lit only supports templates on the server side for HTML 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. Lit does not support [`CSSStyleSheet` (aka CSS Modules) in their SSR DOM shim](https://github.com/lit/lit/issues/2631#issuecomment-1065400805).
+1. Full hydration support is not available yet. See [this Greenwood issue](https://github.com/ProjectEvergreen/greenwood/issues/880) to follow along with 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.
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 34ac418e6..4c5455bcb 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
@@ -10,7 +10,7 @@
* greenwood build
*
* User Config
- * import { greenwoodPluginIncludeHTML } from '@greenwood/plugin-include-html';
+ * import { greenwoodPluginRendererLit } from '@greenwood/plugin-renderer-lit';
*
* {
* plugins: [{
@@ -166,7 +166,7 @@ describe('Build Greenwood With Custom Lit Renderer for SSG prerendering: ', func
dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './index.html'));
});
- it('should have expected footer tag content in the ', function() {
+ it('should have no script tags in the ', function() {
const scripTags = dom.window.document.querySelectorAll('body script');
expect(scripTags.length).to.be.equal(0);
@@ -182,7 +182,7 @@ describe('Build Greenwood With Custom Lit Renderer for SSG prerendering: ', func
body = dom.window.document.querySelector('body');
});
- it('should have expected footer tag content in the ', function() {
+ it('should have expected tag content in the ', function() {
const html = body.innerHTML.trim();
expect(html).to.contain('');
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/greenwood.config.js b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/greenwood.config.js
new file mode 100644
index 000000000..4b8dff4c9
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/greenwood.config.js
@@ -0,0 +1,9 @@
+import { greenwoodPluginRendererLit } from '../../../src/index.js';
+
+export default {
+ plugins: [
+ greenwoodPluginRendererLit({
+ prerender: true
+ })
+ ]
+};
\ No newline at end of file
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/loaders-build.prerender.import-attributes.spec.js b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/loaders-build.prerender.import-attributes.spec.js
new file mode 100644
index 000000000..9e06e55ae
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/loaders-build.prerender.import-attributes.spec.js
@@ -0,0 +1,193 @@
+/*
+ * Use Case
+ * Run Greenwood build command with a static site and only prerendering the content (no JS!) and using import attributes
+ *
+ * User Result
+ * Should generate a bare bones Greenwood build with correctly templated out HTML from a LitElement.
+ *
+ * User Command
+ * greenwood build
+ *
+ * User Config
+ * import { greenwoodPluginRendererLit } from '@greenwood/plugin-renderer-lit';
+ *
+ * {
+ * plugins: [{
+ * greenwoodPluginRendererLit({
+ * prerender: true
+ * })
+ * }]
+ * }
+ *
+ * User Workspace
+ * src/
+ * components/
+ * header/
+ * header.js
+ * header.css
+ * nav.json
+ * pages/
+ * index.html
+ */
+import chai from 'chai';
+import { JSDOM } from 'jsdom';
+import path from 'path';
+import { runSmokeTest } from '../../../../../test/smoke-test.js';
+import { getDependencyFiles, getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
+import { Runner } from 'gallinago';
+import { fileURLToPath, URL } from 'url';
+
+const expect = chai.expect;
+
+describe('Build Greenwood With Custom Lit Renderer for SSG prerendering: ', function() {
+ const LABEL = 'For SSG prerendering of Getting Started example';
+ const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
+ const outputPath = fileURLToPath(new URL('.', import.meta.url));
+ let runner;
+
+ before(function() {
+ this.context = {
+ publicDir: path.join(outputPath, 'public')
+ };
+ runner = new Runner(false, true);
+ });
+
+ describe(LABEL, function() {
+
+ before(async function() {
+ const lit = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit/*.js`,
+ `${outputPath}/node_modules/lit/`
+ );
+ const litDecorators = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit/decorators/*.js`,
+ `${outputPath}/node_modules/lit/decorators/`
+ );
+ const litDirectives = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit/directives/*.js`,
+ `${outputPath}/node_modules/lit/directives/`
+ );
+ const litPackageJson = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit/package.json`,
+ `${outputPath}/node_modules/lit/`
+ );
+ const litElement = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit-element/*.js`,
+ `${outputPath}/node_modules/lit-element/`
+ );
+ const litElementPackageJson = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit-element/package.json`,
+ `${outputPath}/node_modules/lit-element/`
+ );
+ const litElementDecorators = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit-element/decorators/*.js`,
+ `${outputPath}/node_modules/lit-element/decorators/`
+ );
+ const litHtml = await getDependencyFiles(
+ `${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/`
+ );
+ const litHtmlDirectives = await getDependencyFiles(
+ `${process.cwd()}/node_modules/lit-html/directives/*.js`,
+ `${outputPath}/node_modules/lit-html/directives/`
+ );
+ const litReactiveElement = await getDependencyFiles(
+ `${process.cwd()}/node_modules/@lit/reactive-element/*.js`,
+ `${outputPath}/node_modules/@lit/reactive-element/`
+ );
+ const litReactiveElementDecorators = await getDependencyFiles(
+ `${process.cwd()}/node_modules/@lit/reactive-element/decorators/*.js`,
+ `${outputPath}/node_modules/@lit/reactive-element/decorators/`
+ );
+ const litReactiveElementPackageJson = await getDependencyFiles(
+ `${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/`
+ );
+ const trustedTypes = await getDependencyFiles(
+ `${process.cwd()}/node_modules/@types/trusted-types/package.json`,
+ `${outputPath}/node_modules/@types/trusted-types/`
+ );
+
+ runner.setup(outputPath, [
+ ...getSetupFiles(outputPath),
+ ...lit,
+ ...litPackageJson,
+ ...litDirectives,
+ ...litDecorators,
+ ...litElementPackageJson,
+ ...litElement,
+ ...litElementDecorators,
+ ...litHtmlPackageJson,
+ ...litHtml,
+ ...litHtmlNode,
+ ...litHtmlNodeDirectives,
+ ...litHtmlDirectives,
+ ...trustedTypes,
+ ...litReactiveElement,
+ ...litReactiveElementDecorators,
+ ...litReactiveElementPackageJson,
+ ...litReactiveElementNode,
+ ...litHtmlSourceMap
+ ]);
+ runner.runCommand(cliPath, 'build');
+ });
+
+ runSmokeTest(['public', 'index'], LABEL);
+
+ describe(' of the page with data-gwd-opt="static" script tags removed', function() {
+ let dom;
+
+ before(async function() {
+ dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './index.html'));
+ });
+
+ it('should have no script tags in the ', function() {
+ const scripTags = dom.window.document.querySelectorAll('body script');
+
+ expect(scripTags.length).to.be.equal(0);
+ });
+ });
+
+ describe('LitElement statically rendered into index.html', function() {
+ let dom;
+
+ before(async function() {
+ dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './index.html'));
+ });
+
+ it('should have expected header content in the ', function() {
+ const wrapper = new JSDOM(dom.window.document.querySelectorAll('app-header template[shadowrootmode="open"]')[0].innerHTML);
+ const nav = wrapper.window.document.querySelectorAll('header nav ul li');
+
+ expect(nav.length).to.equal(2);
+ expect(nav[0].textContent).to.equal('Home');
+ expect(nav[1].textContent).to.equal('About');
+ });
+ });
+ });
+
+ after(function() {
+ runner.teardown(getOutputTeardownFiles(outputPath));
+ });
+});
\ No newline at end of file
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/package.json b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/package.json
new file mode 100644
index 000000000..3b95281c1
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "plugin-prerender-lit-build-prerender-import-attributes",
+ "type": "module",
+ "dependencies": {
+ "lit": "^3.1.0"
+ }
+}
\ No newline at end of file
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/header.css b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/header.css
new file mode 100644
index 000000000..2ed644613
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/header.css
@@ -0,0 +1,5 @@
+:host {
+ header {
+ color: red;
+ }
+}
\ No newline at end of file
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/header.js b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/header.js
new file mode 100644
index 000000000..42bd1291f
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/header.js
@@ -0,0 +1,27 @@
+import { html, LitElement } from 'lit';
+import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
+import nav from './nav.json' with { type: 'json' };
+
+// CSSStyleSheet is not supported by Lit
+// https://github.com/lit/lit/issues/2631#issuecomment-1065400805
+// import sheet from './header.css' with { type: 'css' };
+
+class HeaderComponent extends LitElement {
+
+ // static styles = [sheet];
+
+ render() {
+ return html`
+
+ This is the header component.
+
+
+ ${nav.items.map(item => unsafeHTML(`${item} `))}
+
+
+
+ `;
+ }
+}
+
+customElements.define('app-header', HeaderComponent);
\ No newline at end of file
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/nav.json b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/nav.json
new file mode 100644
index 000000000..5a3922f92
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/components/header/nav.json
@@ -0,0 +1,3 @@
+{
+ "items": ["Home", "About"]
+}
\ No newline at end of file
diff --git a/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/pages/index.html b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/pages/index.html
new file mode 100644
index 000000000..1e7535331
--- /dev/null
+++ b/packages/plugin-renderer-lit/test/cases/loaders-build.prerender.import-attributes/src/pages/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 5219f773b..a43738ed2 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
@@ -9,7 +9,15 @@
* greenwood build
*
* User Config
- * {}
+ * import { greenwoodPluginRendererLit } from '@greenwood/plugin-renderer-lit';
+ *
+ * {
+ * plugins: [{
+ * greenwoodPluginRendererLit({
+ * prerender: true
+ * })
+ * }]
+ * }
*
* User Workspace
* src/
diff --git a/packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/greenwood.config.js b/packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/greenwood.config.js
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/greenwood.config.js
rename to packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/greenwood.config.js
diff --git a/packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/exp-prerender.serve.ssr.spec.js b/packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/loaders-serve.prerender-ssr.spec.js
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/exp-prerender.serve.ssr.spec.js
rename to packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/loaders-serve.prerender-ssr.spec.js
diff --git a/packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/package.json b/packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/package.json
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/package.json
rename to packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/package.json
diff --git a/packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/src/components/card/card.ts b/packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/src/components/card/card.ts
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/src/components/card/card.ts
rename to packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/src/components/card/card.ts
diff --git a/packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/src/pages/index.html b/packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/src/pages/index.html
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-prerender.serve.ssr/src/pages/index.html
rename to packages/plugin-typescript/test/cases/loaders-serve.prerender-ssr/src/pages/index.html
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/greenwood.config.js b/packages/plugin-typescript/test/cases/loaders-serve.ssr/greenwood.config.js
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/greenwood.config.js
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/greenwood.config.js
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js b/packages/plugin-typescript/test/cases/loaders-serve.ssr/loaders-serve.ssr.spec.js
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/exp-serve.ssr.spec.js
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/loaders-serve.ssr.spec.js
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/package.json b/packages/plugin-typescript/test/cases/loaders-serve.ssr/package.json
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/package.json
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/package.json
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/src/api/fragment.js b/packages/plugin-typescript/test/cases/loaders-serve.ssr/src/api/fragment.js
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/src/api/fragment.js
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/src/api/fragment.js
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/src/components/card/card.ts b/packages/plugin-typescript/test/cases/loaders-serve.ssr/src/components/card/card.ts
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/src/components/card/card.ts
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/src/components/card/card.ts
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/src/components/card/logo.png b/packages/plugin-typescript/test/cases/loaders-serve.ssr/src/components/card/logo.png
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/src/components/card/logo.png
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/src/components/card/logo.png
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/src/components/card/styles.ts b/packages/plugin-typescript/test/cases/loaders-serve.ssr/src/components/card/styles.ts
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/src/components/card/styles.ts
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/src/components/card/styles.ts
diff --git a/packages/plugin-typescript/test/cases/exp-serve.ssr/src/pages/index.html b/packages/plugin-typescript/test/cases/loaders-serve.ssr/src/pages/index.html
similarity index 100%
rename from packages/plugin-typescript/test/cases/exp-serve.ssr/src/pages/index.html
rename to packages/plugin-typescript/test/cases/loaders-serve.ssr/src/pages/index.html
diff --git a/tsconfig.json b/tsconfig.json
index a178f9dcd..b9781270a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,5 +1,8 @@
{
"compilerOptions": {
- "experimentalDecorators": true
+ "allowImportingTsExtensions": true,
+ "experimentalDecorators": true,
+ "module": "NodeNext",
+ "noEmit": true
}
}
\ No newline at end of file
diff --git a/www/components/banner/banner.js b/www/components/banner/banner.js
index 1638d9bde..e28e27d5a 100644
--- a/www/components/banner/banner.js
+++ b/www/components/banner/banner.js
@@ -1,6 +1,6 @@
import { css, html, LitElement, unsafeCSS } from 'lit';
-import bannerCss from './banner.css?type=css';
-import buttonCss from './button.css?type=css';
+import bannerCss from './banner.css?type=raw';
+import buttonCss from './button.css?type=raw';
import './eve-button.js';
class Banner extends LitElement {
diff --git a/www/components/banner/eve-button.js b/www/components/banner/eve-button.js
index bb01dbb4d..6d1ebba24 100644
--- a/www/components/banner/eve-button.js
+++ b/www/components/banner/eve-button.js
@@ -1,5 +1,5 @@
import { css, html, LitElement, unsafeCSS } from 'lit';
-import eveButtonCss from './eve-button.css?type=css';
+import eveButtonCss from './eve-button.css?type=raw';
class Button extends LitElement {
diff --git a/www/components/card/card.js b/www/components/card/card.js
index d5a56b72f..dd99d3331 100644
--- a/www/components/card/card.js
+++ b/www/components/card/card.js
@@ -1,5 +1,5 @@
import { css, html, LitElement, unsafeCSS } from 'lit';
-import cardCss from './card.css?type=css';
+import cardCss from './card.css?type=raw';
class Card extends LitElement {
diff --git a/www/components/header/header.js b/www/components/header/header.js
index 08ac20552..4cc34950a 100644
--- a/www/components/header/header.js
+++ b/www/components/header/header.js
@@ -1,7 +1,7 @@
import { css, html, LitElement, unsafeCSS } from 'lit';
import client from '@greenwood/plugin-graphql/src/core/client.js';
import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql';
-import headerCss from './header.css?type=css';
+import headerCss from './header.css?type=raw';
import '../social-icons/social-icons.js';
class HeaderComponent extends LitElement {
diff --git a/www/components/shelf/shelf.js b/www/components/shelf/shelf.js
index 1b555977a..902e48acf 100644
--- a/www/components/shelf/shelf.js
+++ b/www/components/shelf/shelf.js
@@ -1,7 +1,7 @@
import { css, html, LitElement, unsafeCSS } from 'lit';
import client from '@greenwood/plugin-graphql/src/core/client.js';
import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql';
-import shelfCss from './shelf.css?type=css';
+import shelfCss from './shelf.css?type=raw';
import chevronRt from '../icons/chevron-right.js';
import chevronDwn from '../icons/chevron-down.js';
diff --git a/www/components/social-icons/social-icons.js b/www/components/social-icons/social-icons.js
index 2a841f60e..12cbe1bbc 100644
--- a/www/components/social-icons/social-icons.js
+++ b/www/components/social-icons/social-icons.js
@@ -1,5 +1,5 @@
import { css, html, LitElement, unsafeCSS } from 'lit';
-import socialCss from './social-icons.css?type=css';
+import socialCss from './social-icons.css?type=raw';
import githubIcon from '../icons/github-icon.js';
import twitterIcon from '../icons/twitter-icon.js';
import slackIcon from '../icons/slack-icon.js';
diff --git a/www/pages/docs/scripts.md b/www/pages/docs/scripts.md
index 75bcc9e44..62f6c7ffb 100644
--- a/www/pages/docs/scripts.md
+++ b/www/pages/docs/scripts.md
@@ -7,6 +7,7 @@ linkheadings: 3
---
## Scripts and Imports
+
**Greenwood** generally does not have any opinion on how you structure your site, aside from the pre-determined _pages/_ and (optional) _templates/_ directories. It supports all standard files that you can open in a web browser.
@@ -34,6 +35,7 @@ Script tags can be done in any standards compliant way that will work in a brows
```
### Imports
+
Greenwood also supports (and recommends) usage of ECMAScript Modules (ESM), like in the example below.
```html
@@ -41,13 +43,7 @@ Greenwood also supports (and recommends) usage of ECMAScript Modules (ESM), like
-
-
-
+
@@ -57,6 +53,19 @@ Greenwood also supports (and recommends) usage of ECMAScript Modules (ESM), like
```
+### Import Attributes
+
+[Import Attributes](https://github.com/tc39/proposal-import-attributes) are also supported on the client and on [the server](docs/server-rendering/#custom-imports). By default automatically handles CSS and JSON modules and for CSS, emits a [`CSSStylesheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/CSSStyleSheet).
+
+```js
+import sheet from './styles.css' with { type: 'css' };
+import data from './data.json' with { type: 'json' };
+
+console.log({ sheet, data });
+```
+
+Combined with Greenwood's [custom import resource plugins](https://www.greenwoodjs.io/plugins/custom-plugins/) (or your own!), Greenwood can handle loading custom file extensions for the client or the server using ESM for just about anything you could need!
+
### Extensions and Bare Imports
One important note to consider is that ESM by spec definition, expects a couple important characteristics from an `import` path:
diff --git a/www/pages/docs/server-rendering.md b/www/pages/docs/server-rendering.md
index 411cc06fe..b2252324e 100644
--- a/www/pages/docs/server-rendering.md
+++ b/www/pages/docs/server-rendering.md
@@ -238,25 +238,24 @@ export const isolation = true;
### Custom Imports
-> ⚠️ _This feature is experimental._
->
-> _**Note**: At this time, [WCC can't handle non-standard javaScript formats](https://github.com/ProjectEvergreen/greenwood/issues/1004), though we hope to enable this by the 1.0 release._
+To enable custom [imports](/docs/scripts/#imports) on the server side for prerendering or SSR use cases, you will need to invoke Greenwood using `node` on the CLI and pass it the `--loaders` flag.
-Combined with Greenwood's [custom import resource plugins](https://www.greenwoodjs.io/plugins/custom-plugins/) (or your own!), Greenwood can handle loading custom file extensions on the server side using ESM, like CSS and JSON!
+```shell
+$ node --loader ./node_modules/@greenwood/cli/src/loader.js ./node_modules/.bin/greenwood
+```
-For example, you can now import JSON in your SSR pages and components.
+Then you will be able to run this code with NodeJS, or for any custom format you want using a plugin.
```js
-import json from '../path/to/data.json';
+import sheet from './styles.css' with { type: 'css' };
+import data from './data.json' with { type: 'json' };
-console.log(json); // { status: 200, message: 'some data' }
+console.log({ sheet, data });
```
-**Steps**
-1. Make sure you are using Node `v18.15.0`
-1. Run the Greenwood CLI using the `--experimental-loaders` flag and pass Greenwood's custom loader
- ```shell
- $ node --experimental-loader ./node_modules/@greenwood/cli/src/loader.js ./node_modules/.bin/greenwood
- ```
+_**Notes**_
+
+- At this time, [WCC can't handle non-standard JavaScript formats](https://github.com/ProjectEvergreen/greenwood/issues/1004), though we hope to enable this by the 1.0 release.
+- We would like to explore ways to [improve the DX here](https://github.com/ProjectEvergreen/greenwood/discussions/1217), and not require having to manually invoke `node`
### Hybrid Projects
diff --git a/www/pages/plugins/custom-plugins.md b/www/pages/plugins/custom-plugins.md
index 711be0d2d..8be242786 100644
--- a/www/pages/plugins/custom-plugins.md
+++ b/www/pages/plugins/custom-plugins.md
@@ -18,9 +18,8 @@ The available plugins built and maintained by Greenwood team and contributors ha
| [Google Analytics](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-google-analytics) | Easily add usage tracking to your site with Google Analytics. |
| [Include HTML](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-include-html) | Provides additional methods for generating static HTML at build time, inspired by the original [HTML Imports spec](https://www.html5rocks.com/en/tutorials/webcomponents/imports/). |
| [Import CommonJs](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-commonjs) | Enables usage of `import` syntax for loading CommonJS modules from _node_modules_. |
-| [Import CSS](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-css) | Enables usage of `import` syntax for loading CSS files. |
-| [Import JSON](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-json) | Enables usage of `import` syntax for loading JSON files. |
| [Import JSX](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-jsx) | Enables usage of `import` syntax for loading JSX rendering Web Components compatible with [**WCC**](https://github.com/ProjectEvergreen/wcc). |
+| [Import Raw](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-raw) | Enables usage of `import` syntax for loading arbitrary file contents as a string. |
| [Polyfills](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-polyfills) | Although most modern browsers now support the APIs that make up Web Component, for older browsers use this plugin to Let Greenwood automatically take care of progressively loading polyfills for you. |
| [PostCSS](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-postcss) | Allows usage of [**PostCSS**](https://postcss.org/) plugins and configuration in your project. |
| [Renderer Lit](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-renderer-lit) | A server-side rendering plugin for Lit based Greenwood projects. |
diff --git a/www/pages/plugins/resource.md b/www/pages/plugins/resource.md
index 15ba350d6..bdfc96fc2 100644
--- a/www/pages/plugins/resource.md
+++ b/www/pages/plugins/resource.md
@@ -41,18 +41,22 @@ export function myResourcePlugin(options = {}) {
};
```
+
### Lifecycles
-A resource in Greenwood has access to four lifecycles, in this order:
-1. `resolve`
-1. `serve`
-1. `intercept`
-1. `optimize` (only runs at build time)
-Each lifecycle also supports a predicate like function, e.g. `shouldResolve` that returns a boolean of `true|false` if this plugin's lifecycle should be invoked for this resource. You can think of these lifecycles effectively as middleware.
+A resource plugin in Greenwood has access to four lifecycles, in this order:
+
+1. `resolve` - Where the resource is located, e.g. on disk
+1. `serve` - What are the contents of a resource
+1. `preIntercept` - transforming the response of a _served_ resource before Greenwood can `intercept` it
+1. `intercept` - transforming the response of a _served_ resource
+1. `optimize` - transforming the response of resource after `intercept` lifecycle has run (only runs at build time)
+
+Each lifecycle also supports a corresponding predicate function, e.g. `shouldResolve` that should return a boolean of `true|false` if this plugin's lifecycle should be invoked for the given resource.
#### Resolve
-When requesting a file, such as `/main.js`, Greenwood needs to know _where_ this resource is located. This is the first lifecycle that is run and takes in a `URL` and `Request` as parameters, and should return an of a `Request` object. Below is an example from [Greenwood's codebase](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/cli/src/plugins/resource/plugin-user-workspace.js).
+When requesting a resource like a file, such as `/main.js`, Greenwood needs to know _where_ this resource is located. This is the first lifecycle that is run and takes in a `URL` and `Request` as parameters, and should return a `Request` object. Below is an example from [Greenwood's codebase](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/cli/src/plugins/resource/plugin-user-workspace.js).
```js
@@ -85,7 +89,9 @@ class UserWorkspaceResource extends ResourceInterface {
#### Serve
-When requesting a file, such as `/main.js`, Greenwood needs to return a response so that the contents can be served or bundled appropriately. This is done by passing an instance of `URL` and `Request` and returning an instance of `Response`. For example, Greenwood uses this lifecycle extensively to serve all the standard web content types like HTML, JS, CSS, images, fonts, etc and also providing the appropriate `Content-Type` header. If you are supporting custom extensions, this is where you would transform the contents into something a browser would understand; like compiling from TypeScript to JavaScript.
+When requesting a file and after knowing where to resolve it, such as `/path/to/user-workspace/main/scripts/main.js`, Greenwood needs to return the contents of that resource so can be served to a browser or bundled appropriately. This is done by passing an instance of `URL` and `Request` and returning an instance of `Response`. For example, Greenwood uses this lifecycle extensively to serve all the standard web content types like HTML, JS, CSS, images, fonts, etc and also providing the appropriate `Content-Type` header.
+
+If you are supporting _non standard_ file formats, like TypeScript (`.ts`) or JSX (`.jsx`), this is where you would want to handle providing the contents of this file transformed into something a browser could understand; like compiling the TypeScript to JavaScript.
Below is an example from [Greenwood's codebase](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/cli/src/plugins/resource/plugin-standard-javascript.js) for serving JavaScript files.
@@ -113,40 +119,74 @@ class StandardJavaScriptResource extends ResourceInterface {
```
-> If this was for a TypeScript file (_.ts_) for example, this would be the lifecycle where you would run `tsc`.
+> If this was a TypeScript file, this would be the lifecycle where you would run `tsc`.
-#### Intercept
+#### Pre Intercept
+
+After the `serve` lifecycle comes the `preIntercept` lifecycle. This lifecycle is useful for transforming an already served resource _Greenwood_ or any other plugins try and `intercept` it the contents. It takes in as parameters an instance of `URL`, `Request`, and `Response`.
-After the `serve` lifecycle comes the `intercept` lifecycle. This lifecycle is useful for transforming an already handled resource, or to in anyway augment an already handled response before it is served or bundle. This can be done by returning an instance of a `Response`. It takes in as parameters an instance of `URL`, `Request`, and `Response`.
+This lifecycle is useful for augmenting _standard_ web formats prior to Greenwood operating on them. A good example of this is wanting to run pre-processors like Babel, ESBuild, or PostCSS to "downlevel" non-standard syntax _into_ standard syntax before other plugins can operate on it.
-Below is an example from [Greenwood's codebase](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/plugin-import-css/src/index.js) for converting a standard CSS file response into ESM so that you can `import` _.css_ files. You'll see in this example we're return a module instead of just a CSS string, and changing the `Content-Type` of the response to `text/javascript`.
+Below is an example of Greenwood's PostCSS plugin using `preIntercept` on CSS files.
```js
-import { ResourceInterface } from '@greenwood/cli/src/lib/resource-interface.js';
-
-class ImportCssResource extends ResourceInterface {
+class PostCssResource extends ResourceInterface {
constructor(compilation, options) {
super(compilation, options);
+ this.extensions = ['css'];
+ this.contentType = ['text/css'];
}
- // ...
+ async shouldPreIntercept(url) {
+ return url.protocol === 'file:' && url.pathname.split('.').pop() === this.extensions[0];
+ }
- async shouldIntercept(url, request, response) {
- const { pathname } = url;
- const accepts = request.headers.get('accept') || '';
- const notFromBrowser = accepts.indexOf('text/css') < 0 && accepts.indexOf('application/signed-exchange') < 0;
+ async preIntercept(url, request, response) {
+ const config = await getConfig(this.compilation, this.options.extendConfig);
+ const plugins = config.plugins || [];
+ const body = await response.text();
+ const css = plugins.length > 0
+ ? (await postcss(plugins).process(body, { from: normalizePathnameForWindows(url) })).css
+ : body;
+
+ return new Response(css);
+ }
+}
+```
+
+
+#### Intercept
+
+After the `preIntercept` lifecycle comes the `intercept` lifecycle. This lifecycle is useful for transforming already served resources and returning an instance of a `Response` with the new transformation. It takes in as parameters an instance of `URL`, `Request`, and `Response`.
+
+This lifecycle is useful for augmenting _standard_ web formats, where Greenwood can handle resolving and serving the standard contents, allowing plugins to handle any one-off transformations.
+
+A good example of this is [Greenwood's "raw" plugin](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/plugin-import-raw/src/index.js) which can take a standard web format like CSS, and convert it onto a standard ES Module when a `?type=raw` is added to any `import`, which would be useful for CSS-in-JS use cases, for example:
+
+
+```js
+import styles from './hero.css?type=raw';
+```
+
+
+
+```js
+import { ResourceInterface } from '@greenwood/cli/src/lib/resource-interface.js';
+
+class ImportRawResource extends ResourceInterface {
+ async shouldIntercept(url) {
+ const { protocol, searchParams } = url;
+ const type = searchParams.get('type');
- // https://github.com/ProjectEvergreen/greenwood/issues/492
- return pathname.split('.').pop() === 'css' &&
- (notFromBrowser || url.searchParams.has('type') && url.searchParams.get('type') === 'css');
+ return protocol === 'file:' && type === 'raw';
}
async intercept(url, request, response) {
const body = await response.text();
- const cssInJsBody = `const css = \`${body.replace(/\r?\n|\r/g, ' ').replace(/\\/g, '\\\\')}\`;\nexport default css;`;
+ const contents = `const raw = \`${body.replace(/\r?\n|\r/g, ' ').replace(/\\/g, '\\\\')}\`;\nexport default raw;`;
- return new Response(cssInJsBody, {
+ return new Response(contents, {
headers: new Headers({
'Content-Type': 'text/javascript'
})
@@ -158,9 +198,9 @@ class ImportCssResource extends ResourceInterface {
#### Optimize
-This lifecycle is only run during a build and after the `intercept` lifecycle, and as the name implies is a way to do any final production ready optimizations or transformations. It takes as parameters an instance of `URL` and `Response` and should return an instance of `Response`.
+This lifecycle is only run during a build (`greenwood build`) and after the `intercept` lifecycle, and as the name implies is a way to do any final production ready optimizations or transformations. It takes as parameters an instance of `URL` and `Response` and should return an instance of `Response`.
-Below is an example from [Greenwood's codebase](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/plugin-import-css/src/index.js) for minifying CSS. (The actual function for minifying has been ommitted for brevity)
+Below is an example from [Greenwood's codebase](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/plugin-import-css/src/index.js) for minifying CSS. (The actual function for minifying has been omitted for brevity)
```js
diff --git a/yarn.lock b/yarn.lock
index 7e8057dcb..752ec426f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,6 +7,14 @@
resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
+"@ampproject/remapping@^2.2.0":
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
+ integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
"@apollo/client@^3.7.14":
version "3.7.14"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.7.14.tgz#40ef90390e6690e94917457cd82bdeb29e8b6af9"
@@ -99,11 +107,24 @@
dependencies:
"@babel/highlight" "^7.22.5"
+"@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
+ version "7.24.2"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
+ integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
+ dependencies:
+ "@babel/highlight" "^7.24.2"
+ picocolors "^1.0.0"
+
"@babel/compat-data@^7.13.0", "@babel/compat-data@^7.13.5":
version "7.13.6"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.6.tgz#11972d07db4c2317afdbf41d6feb3a730301ef4e"
integrity sha512-VhgqKOWYVm7lQXlvbJnWOzwfAQATd2nV52koT0HZ/LdDH0m4DUDwkKYsH+IwpXb+bKPyBJzawA4I6nBKqZcpQw==
+"@babel/compat-data@^7.23.5":
+ version "7.24.4"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a"
+ integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==
+
"@babel/core@>=7.9.0":
version "7.12.9"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8"
@@ -148,6 +169,36 @@
semver "7.0.0"
source-map "^0.5.0"
+"@babel/core@^7.24.4":
+ version "7.24.4"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717"
+ integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.24.2"
+ "@babel/generator" "^7.24.4"
+ "@babel/helper-compilation-targets" "^7.23.6"
+ "@babel/helper-module-transforms" "^7.23.3"
+ "@babel/helpers" "^7.24.4"
+ "@babel/parser" "^7.24.4"
+ "@babel/template" "^7.24.0"
+ "@babel/traverse" "^7.24.1"
+ "@babel/types" "^7.24.0"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
+
+"@babel/eslint-parser@^7.24.1":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz#e27eee93ed1d271637165ef3a86e2b9332395c32"
+ integrity sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==
+ dependencies:
+ "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1"
+ eslint-visitor-keys "^2.1.0"
+ semver "^6.3.1"
+
"@babel/generator@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de"
@@ -176,6 +227,16 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
+"@babel/generator@^7.24.1", "@babel/generator@^7.24.4":
+ version "7.24.4"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498"
+ integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==
+ dependencies:
+ "@babel/types" "^7.24.0"
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.25"
+ jsesc "^2.5.1"
+
"@babel/helper-annotate-as-pure@^7.12.13":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab"
@@ -183,6 +244,13 @@
dependencies:
"@babel/types" "^7.12.13"
+"@babel/helper-annotate-as-pure@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
+ integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
"@babel/helper-builder-binary-assignment-operator-visitor@^7.12.13":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz#6bc20361c88b0a74d05137a65cac8d3cbf6f61fc"
@@ -201,6 +269,17 @@
browserslist "^4.14.5"
semver "7.0.0"
+"@babel/helper-compilation-targets@^7.23.6":
+ version "7.23.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991"
+ integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==
+ dependencies:
+ "@babel/compat-data" "^7.23.5"
+ "@babel/helper-validator-option" "^7.23.5"
+ browserslist "^4.22.2"
+ lru-cache "^5.1.1"
+ semver "^6.3.1"
+
"@babel/helper-create-class-features-plugin@^7.13.0":
version "7.13.0"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.0.tgz#28d04ad9cfbd1ed1d8b988c9ea7b945263365846"
@@ -327,6 +406,13 @@
dependencies:
"@babel/types" "^7.22.15"
+"@babel/helper-module-imports@^7.22.15":
+ version "7.24.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128"
+ integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==
+ dependencies:
+ "@babel/types" "^7.24.0"
+
"@babel/helper-module-transforms@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c"
@@ -357,6 +443,17 @@
"@babel/types" "^7.13.0"
lodash "^4.17.19"
+"@babel/helper-module-transforms@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1"
+ integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-module-imports" "^7.22.15"
+ "@babel/helper-simple-access" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ "@babel/helper-validator-identifier" "^7.22.20"
+
"@babel/helper-optimise-call-expression@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673"
@@ -381,6 +478,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz#174254d0f2424d8aefb4dd48057511247b0a9eeb"
integrity sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==
+"@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a"
+ integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==
+
"@babel/helper-remap-async-to-generator@^7.13.0":
version "7.13.0"
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz#376a760d9f7b4b2077a9dd05aa9c3927cadb2209"
@@ -434,6 +536,13 @@
dependencies:
"@babel/types" "^7.12.13"
+"@babel/helper-simple-access@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
+ integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
"@babel/helper-skip-transparent-expression-wrappers@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf"
@@ -467,6 +576,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+"@babel/helper-string-parser@^7.23.4":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e"
+ integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==
+
"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
@@ -492,6 +606,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831"
integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==
+"@babel/helper-validator-option@^7.23.5":
+ version "7.23.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
+ integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
+
"@babel/helper-wrap-function@^7.13.0":
version "7.13.0"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz#bdb5c66fda8526ec235ab894ad53a1235c79fcc4"
@@ -520,6 +639,15 @@
"@babel/traverse" "^7.13.0"
"@babel/types" "^7.13.0"
+"@babel/helpers@^7.24.4":
+ version "7.24.4"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6"
+ integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==
+ dependencies:
+ "@babel/template" "^7.24.0"
+ "@babel/traverse" "^7.24.1"
+ "@babel/types" "^7.24.0"
+
"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.13":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
@@ -547,6 +675,16 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
+"@babel/highlight@^7.24.2":
+ version "7.24.2"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26"
+ integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.22.20"
+ chalk "^2.4.2"
+ js-tokens "^4.0.0"
+ picocolors "^1.0.0"
+
"@babel/parser@^7.10.4":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
@@ -577,6 +715,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+"@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4":
+ version "7.24.4"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
+ integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==
+
"@babel/parser@^7.7.0":
version "7.14.1"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.1.tgz#1bd644b5db3f5797c4479d89ec1817fe02b84c47"
@@ -717,6 +860,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
+"@babel/plugin-syntax-import-assertions@^7.24.1":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971"
+ integrity sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.24.0"
+
"@babel/plugin-syntax-json-strings@^7.8.0":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
@@ -724,6 +874,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
+"@babel/plugin-syntax-jsx@^7.23.3":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10"
+ integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.24.0"
+
"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
@@ -956,6 +1113,39 @@
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
+"@babel/plugin-transform-react-display-name@^7.24.1":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz#554e3e1a25d181f040cf698b93fd289a03bfdcdb"
+ integrity sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.24.0"
+
+"@babel/plugin-transform-react-jsx-development@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87"
+ integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==
+ dependencies:
+ "@babel/plugin-transform-react-jsx" "^7.22.5"
+
+"@babel/plugin-transform-react-jsx@^7.22.5", "@babel/plugin-transform-react-jsx@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312"
+ integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-module-imports" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-jsx" "^7.23.3"
+ "@babel/types" "^7.23.4"
+
+"@babel/plugin-transform-react-pure-annotations@^7.24.1":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz#c86bce22a53956331210d268e49a0ff06e392470"
+ integrity sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.24.0"
+
"@babel/plugin-transform-regenerator@^7.12.13":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.13.tgz#b628bcc9c85260ac1aeb05b45bde25210194a2f5"
@@ -1118,6 +1308,18 @@
"@babel/types" "^7.4.4"
esutils "^2.0.2"
+"@babel/preset-react@^7.24.1":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95"
+ integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.24.0"
+ "@babel/helper-validator-option" "^7.23.5"
+ "@babel/plugin-transform-react-display-name" "^7.24.1"
+ "@babel/plugin-transform-react-jsx" "^7.23.4"
+ "@babel/plugin-transform-react-jsx-development" "^7.22.5"
+ "@babel/plugin-transform-react-pure-annotations" "^7.24.1"
+
"@babel/runtime@^7.10.4", "@babel/runtime@^7.8.4":
version "7.13.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a"
@@ -1161,6 +1363,15 @@
"@babel/parser" "^7.22.15"
"@babel/types" "^7.22.15"
+"@babel/template@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
+ integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==
+ dependencies:
+ "@babel/code-frame" "^7.23.5"
+ "@babel/parser" "^7.24.0"
+ "@babel/types" "^7.24.0"
+
"@babel/traverse@^7.12.1", "@babel/traverse@^7.12.13", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.7.0":
version "7.23.2"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
@@ -1177,6 +1388,22 @@
debug "^4.1.0"
globals "^11.1.0"
+"@babel/traverse@^7.24.1":
+ version "7.24.1"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c"
+ integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==
+ dependencies:
+ "@babel/code-frame" "^7.24.1"
+ "@babel/generator" "^7.24.1"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ "@babel/parser" "^7.24.1"
+ "@babel/types" "^7.24.0"
+ debug "^4.3.1"
+ globals "^11.1.0"
+
"@babel/types@^7.10.4", "@babel/types@^7.11.0":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
@@ -1222,6 +1449,15 @@
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
+"@babel/types@^7.23.4", "@babel/types@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
+ integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
+ dependencies:
+ "@babel/helper-string-parser" "^7.23.4"
+ "@babel/helper-validator-identifier" "^7.22.20"
+ to-fast-properties "^2.0.0"
+
"@babel/types@^7.7.0":
version "7.14.1"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.1.tgz#095bd12f1c08ab63eff6e8f7745fa7c9cc15a9db"
@@ -1322,14 +1558,14 @@
gonzales-pe "^4.3.0"
node-source-walk "^6.0.1"
-"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
+"@eslint-community/eslint-utils@^4.2.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
dependencies:
eslint-visitor-keys "^3.3.0"
-"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1":
+"@eslint-community/regexpp@^4.6.1":
version "4.9.1"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4"
integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==
@@ -1606,6 +1842,15 @@
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9"
+"@jridgewell/gen-mapping@^0.3.5":
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
+ integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
+ dependencies:
+ "@jridgewell/set-array" "^1.2.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
"@jridgewell/resolve-uri@3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
@@ -1621,6 +1866,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+"@jridgewell/set-array@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
+ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
+
"@jridgewell/source-map@^0.3.3":
version "0.3.5"
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91"
@@ -1655,6 +1905,14 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
+"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
+ version "0.3.25"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
"@jridgewell/trace-mapping@^0.3.9":
version "0.3.17"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
@@ -3062,6 +3320,13 @@
unixify "^1.0.0"
yargs "^17.0.0"
+"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
+ version "5.1.1-v1"
+ resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
+ integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==
+ dependencies:
+ eslint-scope "5.1.1"
+
"@nodelib/fs.scandir@2.1.3":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
@@ -4030,11 +4295,6 @@
dependencies:
"@types/istanbul-lib-report" "*"
-"@types/json-schema@^7.0.12":
- version "7.0.13"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85"
- integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==
-
"@types/keygrip@*":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
@@ -4167,11 +4427,6 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==
-"@types/semver@^7.5.0":
- version "7.5.3"
- resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.3.tgz#9a726e116beb26c24f1ccd6850201e1246122e04"
- integrity sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==
-
"@types/serve-static@*":
version "1.13.9"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e"
@@ -4221,75 +4476,11 @@
dependencies:
"@types/node" "*"
-"@typescript-eslint/eslint-plugin@^6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz#f4024b9f63593d0c2b5bd6e4ca027e6f30934d4f"
- integrity sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==
- dependencies:
- "@eslint-community/regexpp" "^4.5.1"
- "@typescript-eslint/scope-manager" "6.7.5"
- "@typescript-eslint/type-utils" "6.7.5"
- "@typescript-eslint/utils" "6.7.5"
- "@typescript-eslint/visitor-keys" "6.7.5"
- debug "^4.3.4"
- graphemer "^1.4.0"
- ignore "^5.2.4"
- natural-compare "^1.4.0"
- semver "^7.5.4"
- ts-api-utils "^1.0.1"
-
-"@typescript-eslint/parser@^6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.5.tgz#8d7ca3d1fbd9d5a58cc4d30b2aa797a760137886"
- integrity sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==
- dependencies:
- "@typescript-eslint/scope-manager" "6.7.5"
- "@typescript-eslint/types" "6.7.5"
- "@typescript-eslint/typescript-estree" "6.7.5"
- "@typescript-eslint/visitor-keys" "6.7.5"
- debug "^4.3.4"
-
-"@typescript-eslint/scope-manager@6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz#1cf33b991043886cd67f4f3600b8e122fc14e711"
- integrity sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==
- dependencies:
- "@typescript-eslint/types" "6.7.5"
- "@typescript-eslint/visitor-keys" "6.7.5"
-
-"@typescript-eslint/type-utils@6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz#0a65949ec16588d8956f6d967f7d9c84ddb2d72a"
- integrity sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==
- dependencies:
- "@typescript-eslint/typescript-estree" "6.7.5"
- "@typescript-eslint/utils" "6.7.5"
- debug "^4.3.4"
- ts-api-utils "^1.0.1"
-
"@typescript-eslint/types@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
-"@typescript-eslint/types@6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.5.tgz#4571320fb9cf669de9a95d9849f922c3af809790"
- integrity sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==
-
-"@typescript-eslint/typescript-estree@6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz#4578de1a26e9f24950f029a4f00d1bfe41f15a39"
- integrity sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==
- dependencies:
- "@typescript-eslint/types" "6.7.5"
- "@typescript-eslint/visitor-keys" "6.7.5"
- debug "^4.3.4"
- globby "^11.1.0"
- is-glob "^4.0.3"
- semver "^7.5.4"
- ts-api-utils "^1.0.1"
-
"@typescript-eslint/typescript-estree@^5.59.5":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
@@ -4303,19 +4494,6 @@
semver "^7.3.7"
tsutils "^3.21.0"
-"@typescript-eslint/utils@6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.5.tgz#ab847b53d6b65e029314b8247c2336843dba81ab"
- integrity sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==
- dependencies:
- "@eslint-community/eslint-utils" "^4.4.0"
- "@types/json-schema" "^7.0.12"
- "@types/semver" "^7.5.0"
- "@typescript-eslint/scope-manager" "6.7.5"
- "@typescript-eslint/types" "6.7.5"
- "@typescript-eslint/typescript-estree" "6.7.5"
- semver "^7.5.4"
-
"@typescript-eslint/visitor-keys@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e"
@@ -4324,14 +4502,6 @@
"@typescript-eslint/types" "5.62.0"
eslint-visitor-keys "^3.3.0"
-"@typescript-eslint/visitor-keys@6.7.5":
- version "6.7.5"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz#84c68d6ceb5b12d5246b918b84f2b79affd6c2f1"
- integrity sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==
- dependencies:
- "@typescript-eslint/types" "6.7.5"
- eslint-visitor-keys "^3.4.1"
-
"@ungap/promise-all-settled@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
@@ -4521,6 +4691,11 @@ acorn-globals@^6.0.0:
acorn "^7.1.1"
acorn-walk "^7.1.1"
+acorn-import-attributes@^1.9.5:
+ version "1.9.5"
+ resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef"
+ integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
+
acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
@@ -5529,6 +5704,16 @@ browserslist@^4.17.5:
node-releases "^2.0.1"
picocolors "^1.0.0"
+browserslist@^4.22.2:
+ version "4.23.0"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab"
+ integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
+ dependencies:
+ caniuse-lite "^1.0.30001587"
+ electron-to-chromium "^1.4.668"
+ node-releases "^2.0.14"
+ update-browserslist-db "^1.0.13"
+
btoa-lite@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
@@ -5812,6 +5997,11 @@ caniuse-lite@^1.0.30001272, caniuse-lite@^1.0.30001280:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001282.tgz#38c781ee0a90ccfe1fe7fefd00e43f5ffdcb96fd"
integrity sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg==
+caniuse-lite@^1.0.30001587:
+ version "1.0.30001612"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz#d34248b4ec1f117b70b24ad9ee04c90e0b8a14ae"
+ integrity sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==
+
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -6496,6 +6686,11 @@ convert-source-map@^1.6.0, convert-source-map@^1.7.0:
dependencies:
safe-buffer "~5.1.1"
+convert-source-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
+ integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -6830,7 +7025,7 @@ debug@3.1.0, debug@~3.1.0:
dependencies:
ms "2.0.0"
-debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.2, debug@^4.3.4:
+debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -7288,6 +7483,11 @@ electron-to-chromium@^1.3.896:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.904.tgz#52a353994faeb0f2a9fab3606b4e0614d1af7b58"
integrity sha512-x5uZWXcVNYkTh4JubD7KSC1VMKz0vZwJUqVwY3ihsW0bst1BXDe494Uqbg3Y0fDGVjJqA8vEeGuvO5foyH2+qw==
+electron-to-chromium@^1.4.668:
+ version "1.4.746"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.746.tgz#787213e75f6c7bccb55dfe8b68170555c548d093"
+ integrity sha512-jeWaIta2rIG2FzHaYIhSuVWqC6KJYo7oSBX4Jv7g+aVujKztfvdpf+n6MGwZdC5hQXbax4nntykLH2juIQrfPg==
+
elegant-spinner@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
@@ -7481,12 +7681,10 @@ es-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f"
integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==
-es-module-shims@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/es-module-shims/-/es-module-shims-1.2.0.tgz#f3b447826c4f4b9d9597b24a7aaa0c639893de2f"
- integrity sha512-Kupc9HFwmScot1v8vO/3CX9MjNprarG4wdlBk2bv5R76SD63UBhXG53MUTjg8USgHaCMLBOQyGSl7lAEqGUb1g==
- dependencies:
- rimraf "^3.0.2"
+es-module-shims@^1.8.3:
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/es-module-shims/-/es-module-shims-1.8.3.tgz#e3e61c54f197b5868d6d9c399168d1c27b3aaaf9"
+ integrity sha512-NOE2WomYkoXeae8FcwPwZApxDwKerEWGOiqNo/P2JCBkJgKCLA5+PMZs8sr/1SPk9a8E+hUE9Wc+YZyGEiWHkw==
es-to-primitive@^1.2.1:
version "1.2.1"
@@ -7568,6 +7766,14 @@ eslint-plugin-no-only-tests@^2.6.0:
resolved "https://registry.yarnpkg.com/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-2.6.0.tgz#19f6c9620bda02b9b9221b436c5f070e42628d76"
integrity sha512-T9SmE/g6UV1uZo1oHAqOvL86XWl7Pl2EpRpnLI8g/bkJu+h7XBCB+1LnubRZ2CUQXj805vh4/CYZdnqtVaEo2Q==
+eslint-scope@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
eslint-scope@^7.2.2:
version "7.2.2"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
@@ -7581,6 +7787,11 @@ eslint-visitor-keys@^1.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+eslint-visitor-keys@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
+ integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+
eslint-visitor-keys@^3.3.0:
version "3.4.2"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz#8c2095440eca8c933bedcadf16fefa44dbe9ba5f"
@@ -7662,6 +7873,11 @@ esrecurse@^4.3.0:
dependencies:
estraverse "^5.2.0"
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
estraverse@^5.1.0, estraverse@^5.2.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
@@ -10476,7 +10692,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-json5@^2.1.2:
+json5@^2.1.2, json5@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
@@ -12210,6 +12426,11 @@ node-releases@^2.0.1:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
+node-releases@^2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
+ integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+
node-source-walk@^6.0.0, node-source-walk@^6.0.1, node-source-walk@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-6.0.2.tgz#ba81bc4bc0f6f05559b084bea10be84c3f87f211"
@@ -14856,14 +15077,14 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
-semver@7.5.4, semver@^7.0.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4:
+semver@7.5.4, semver@^7.0.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
-semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0:
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
@@ -16226,11 +16447,6 @@ trough@^1.0.0:
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
-ts-api-utils@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331"
- integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==
-
ts-invariant@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c"
@@ -16639,6 +16855,14 @@ upath@^1.2.0:
resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
+update-browserslist-db@^1.0.13:
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
+ integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
update-notifier@6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-6.0.2.tgz#a6990253dfe6d5a02bd04fbb6a61543f55026b60"
@@ -16831,14 +17055,15 @@ wait-port@1.0.4:
commander "^9.3.0"
debug "^4.3.4"
-wc-compiler@~0.12.1:
- version "0.12.1"
- resolved "https://registry.yarnpkg.com/wc-compiler/-/wc-compiler-0.12.1.tgz#cf34a1a9758c0085580ddc82b5aa6312d3de20bf"
- integrity sha512-+uEK9cL9MHIWnXoD11cQ77omBLekw1Oih2wqbrM2jBFGTPHvPauq3jtdWzlkg/0OwOJOyYqbBlQfZb/oA+HuNg==
+wc-compiler@~0.13.0:
+ version "0.13.0"
+ resolved "https://registry.yarnpkg.com/wc-compiler/-/wc-compiler-0.13.0.tgz#6194bf03663f62d0d3a8276ae49966c66ddcaeb1"
+ integrity sha512-yyFr9MqBrlLM0vEWLL5fHTHgmM66R9BCStIqH8mFA3iJ9EKRk8hRb+wBzDSIE3B6TLsgxYKMPX3fy6ftiujNKg==
dependencies:
"@projectevergreen/acorn-jsx-esm" "~0.1.0"
"@projectevergreen/escodegen-esm" "~0.1.0"
acorn "^8.7.0"
+ acorn-import-attributes "^1.9.5"
acorn-walk "^8.2.0"
parse5 "^6.0.1"