diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 43fe700..0000000 --- a/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -tap-snapshots -node_modules -fixtures -modules -utils -dist -tmp \ No newline at end of file diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index b53fbca..0000000 --- a/.eslintrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "env": { - "es6": true, - "node": true, - "browser": false - }, - "parserOptions": { - "ecmaVersion": 2020 - }, - "extends": "airbnb-base", - "rules": { - "indent": [1, 4], - "import/prefer-default-export": [0], - "import/extensions": [0] - } -} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..98196d4 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,29 @@ +import prettierConfig from "eslint-config-prettier"; +import prettierPlugin from "eslint-plugin-prettier/recommended"; +import globals from "globals"; +import js from "@eslint/js"; + +export default [ + js.configs.recommended, + prettierConfig, + prettierPlugin, + { + languageOptions: { + globals: { + ...globals.node, + ...globals.browser, + global: true, + }, + }, + }, + { + ignores: [ + "tap-snapshots/*", + "node_modules/*", + "modules/*", + "utils/*", + "dist/*", + "tmp/*", + ], + }, +]; diff --git a/fixtures/index.js b/fixtures/index.js index 5b98474..0af136a 100644 --- a/fixtures/index.js +++ b/fixtures/index.js @@ -1,23 +1,21 @@ // import _ from 'lodash'; -import { h, Component, render } from 'https://unpkg.com/preact?module'; -import foo from './module.js'; +import { h, render } from "https://unpkg.com/preact?module"; +import foo from "./module.js"; - - function component() { - const element = document.createElement('div'); +function component() { + const element = document.createElement("div"); // Lodash, currently included via a script, is required for this line to work // Lodash, now imported by this script - element.innerHTML = ['Hello', 'webpack', foo()].join(' '); - + element.innerHTML = ["Hello", "webpack", foo()].join(" "); // Create your app - const app = h('h1', null, 'Hello World!'); + const app = h("h1", null, "Hello World!"); render(app, document.body); - return element; - } + return element; +} - document.body.appendChild(component()); +document.body.appendChild(component()); diff --git a/fixtures/module.js b/fixtures/module.js index 14a272d..df4145c 100644 --- a/fixtures/module.js +++ b/fixtures/module.js @@ -1,5 +1,5 @@ const foo = () => { - return 'foo'; -} + return "foo"; +}; -export default foo \ No newline at end of file +export default foo; diff --git a/fixtures/modules/basic/main.js b/fixtures/modules/basic/main.js index 382a68b..1ac5232 100644 --- a/fixtures/modules/basic/main.js +++ b/fixtures/modules/basic/main.js @@ -1,6 +1,6 @@ -import { html } from 'lit-element'; +import { html } from "lit-element"; const render = (world) => { - return html`
Hello ${world}!
`; + return html`Hello ${world}!
`; }; render(); diff --git a/fixtures/modules/file/main.js b/fixtures/modules/file/main.js index 09566ed..1794915 100644 --- a/fixtures/modules/file/main.js +++ b/fixtures/modules/file/main.js @@ -1,13 +1,19 @@ -import { html } from 'lit-html/lit-html'; -import { css } from 'lit-html'; -import { LitElement } from 'lit-element'; +import { html } from "lit-html/lit-html"; +import { css } from "lit-html"; +import { LitElement } from "lit-element"; export default class Inner extends LitElement { - static get styles() { - return [css`:host { color: red; }`]; - } + static get styles() { + return [ + css` + :host { + color: red; + } + `, + ]; + } - render(world) { - return html`Hello ${world}!
`; - } + render(world) { + return html`Hello ${world}!
`; + } } diff --git a/fixtures/modules/simple/app/app.js b/fixtures/modules/simple/app/app.js index b042816..787f884 100644 --- a/fixtures/modules/simple/app/app.js +++ b/fixtures/modules/simple/app/app.js @@ -1,21 +1,21 @@ -import { replaceElement } from '../utils/dom.js'; -import view from './views.js'; -import data from '../data/data.js'; +import { replaceElement } from "../utils/dom.js"; +import view from "./views.js"; +import data from "../data/data.js"; export default class App { - constructor(root) { - this.root = root; - } + constructor(root) { + this.root = root; + } - render() { - const items = data(); - const el = view(items); - this.root = replaceElement(this.root, el); - } + render() { + const items = data(); + const el = view(items); + this.root = replaceElement(this.root, el); + } - update() { - setInterval(() => { - this.render(); - }, 1000); - } + update() { + setInterval(() => { + this.render(); + }, 1000); + } } diff --git a/fixtures/modules/simple/app/views.js b/fixtures/modules/simple/app/views.js index 2462283..7b354de 100644 --- a/fixtures/modules/simple/app/views.js +++ b/fixtures/modules/simple/app/views.js @@ -1,5 +1,5 @@ -import { html, css } from 'lit-element'; +import { html } from "lit-element"; export default function view(items) { - return html`Hello ${items[0]}!
`; + return html`Hello ${items[0]}!
`; } diff --git a/fixtures/modules/simple/data/data.js b/fixtures/modules/simple/data/data.js index d1e16d2..f5a8420 100644 --- a/fixtures/modules/simple/data/data.js +++ b/fixtures/modules/simple/data/data.js @@ -1,13 +1,13 @@ function random(min, max) { - return Math.floor(min + Math.random() * (max + 1 - min)); + return Math.floor(min + Math.random() * (max + 1 - min)); } export default function data() { - return [ - random(0, 20), - random(20, 40), - random(40, 60), - random(60, 80), - random(80, 100), - ]; + return [ + random(0, 20), + random(20, 40), + random(40, 60), + random(60, 80), + random(80, 100), + ]; } diff --git a/fixtures/modules/simple/main.js b/fixtures/modules/simple/main.js index 929fc84..8eff3f9 100644 --- a/fixtures/modules/simple/main.js +++ b/fixtures/modules/simple/main.js @@ -1,19 +1,19 @@ -import { firstElement } from './utils/dom.js'; -import App from './app/app.js'; +import { firstElement } from "./utils/dom.js"; +import App from "./app/app.js"; const ready = () => { - return new Promise((resolve) => { - document.addEventListener('DOMContentLoaded', () => { - const el = document.getElementById('app'); - resolve(firstElement(el)); - }); + return new Promise((resolve) => { + document.addEventListener("DOMContentLoaded", () => { + const el = document.getElementById("app"); + resolve(firstElement(el)); }); + }); }; const start = async () => { - const el = await ready(); - const app = new App(el); - app.render(); - app.update(); + const el = await ready(); + const app = new App(el); + app.render(); + app.update(); }; start(); diff --git a/fixtures/modules/simple/utils/dom.js b/fixtures/modules/simple/utils/dom.js index 1c822c2..b9ea410 100644 --- a/fixtures/modules/simple/utils/dom.js +++ b/fixtures/modules/simple/utils/dom.js @@ -1,8 +1,8 @@ export function replaceElement(target, element) { - target.replaceWith(element); - return element; + target.replaceWith(element); + return element; } export function firstElement(element) { - return element.firstElementChild; + return element.firstElementChild; } diff --git a/package.json b/package.json index ecce597..89b4c25 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,7 @@ "scripts": { "test": "tap --no-coverage", "test:snapshot": "TAP_SNAPSHOT=1 tap --no-coverage", - "lint": "eslint . --ext=js,cjs", - "lint:fix": "eslint . --fix --ext=js,cjs" + "lint": "eslint ." }, "repository": { "type": "git", @@ -36,10 +35,11 @@ "@semantic-release/git": "10.0.1", "webpack": "5.91.0", "webpack-cli": "5.1.4", - "eslint": "8.57.0", - "eslint-config-airbnb-base": "15.0.0", - "eslint-plugin-import": "2.29.1", + "eslint": "9.6.0", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-prettier": "5.1.3", "fastify": "4.28.1", + "globals": "15.8.0", "semantic-release": "21.1.2", "tap": "16.3.10", "memfs": "4.9.3" diff --git a/release.config.cjs b/release.config.cjs index aa91e6e..e9355c6 100644 --- a/release.config.cjs +++ b/release.config.cjs @@ -1,25 +1,22 @@ module.exports = { - plugins: [ - '@semantic-release/commit-analyzer', - '@semantic-release/release-notes-generator', - '@semantic-release/changelog', - [ - '@semantic-release/npm', - { - tarballDir: 'release', - }, - ], - [ - '@semantic-release/github', - { - assets: 'release/*.tgz', - }, - ], - '@semantic-release/git', + plugins: [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + [ + "@semantic-release/npm", + { + tarballDir: "release", + }, ], - preset: 'angular', - branches: [ - { name: 'main' }, - { name: 'next', prerelease: true }, + [ + "@semantic-release/github", + { + assets: "release/*.tgz", + }, ], + "@semantic-release/git", + ], + preset: "angular", + branches: [{ name: "main" }, { name: "next", prerelease: true }], }; diff --git a/src/builders.cjs b/src/builders.cjs index d26d18d..26580a5 100644 --- a/src/builders.cjs +++ b/src/builders.cjs @@ -1,44 +1,47 @@ -const parsers = require('./parsers.cjs'); +const parsers = require("./parsers.cjs"); const RX_SIDE_EFFECTS_IMPORT = parsers.sideEffectsImport(); const RX_STANDARD_IMPORT = parsers.standardImport(); const RX_DYNAMIC_IMPORT = parsers.dynamicImport(); -const standardImport = ({ dictionary = new Map(), source = '' }) => { - const result = source.replace(RX_STANDARD_IMPORT, (replacer, g1, g2, g3, g4) => { - const dep = dictionary.get(g4) || g4; - return `${g1} ${g2} ${g3} '${dep}'`; - }); +const standardImport = ({ dictionary = new Map(), source = "" }) => { + const result = source.replace( + RX_STANDARD_IMPORT, + (replacer, g1, g2, g3, g4) => { + const dep = dictionary.get(g4) || g4; + return `${g1} ${g2} ${g3} '${dep}'`; + }, + ); - return { - source: result, - dictionary, - }; + return { + source: result, + dictionary, + }; }; module.exports.standardImport = standardImport; -const dynamicImport = ({ dictionary = new Map(), source = '' }) => { - const result = source.replace(RX_DYNAMIC_IMPORT, (replacer, g1, g2) => { - const dep = dictionary.get(g2) || g2; - return `${g1}('${dep}')`; - }); +const dynamicImport = ({ dictionary = new Map(), source = "" }) => { + const result = source.replace(RX_DYNAMIC_IMPORT, (replacer, g1, g2) => { + const dep = dictionary.get(g2) || g2; + return `${g1}('${dep}')`; + }); - return { - source: result, - dictionary, - }; + return { + source: result, + dictionary, + }; }; module.exports.dynamicImport = dynamicImport; -const sideEffectsImport = ({ dictionary = new Map(), source = '' }) => { - const result = source.replace(RX_SIDE_EFFECTS_IMPORT, (replacer, g1, g2) => { - const dep = dictionary.get(g2) || g2; - return `${g1} '${dep}'`; - }); +const sideEffectsImport = ({ dictionary = new Map(), source = "" }) => { + const result = source.replace(RX_SIDE_EFFECTS_IMPORT, (replacer, g1, g2) => { + const dep = dictionary.get(g2) || g2; + return `${g1} '${dep}'`; + }); - return { - source: result, - dictionary, - }; + return { + source: result, + dictionary, + }; }; module.exports.sideEffectsImport = sideEffectsImport; diff --git a/src/loader.cjs b/src/loader.cjs index 57eab43..8d7a6a9 100644 --- a/src/loader.cjs +++ b/src/loader.cjs @@ -1,58 +1,68 @@ -const { helpers } = require('@eik/common'); -const utils = require('./utils.cjs'); -const { standardImport, dynamicImport, sideEffectsImport } = require('./builders.cjs'); +const { helpers } = require("@eik/common"); +const utils = require("./utils.cjs"); +const { + standardImport, + dynamicImport, + sideEffectsImport, +} = require("./builders.cjs"); const dictionary = new Map(); let cold = true; async function loader(source) { - const options = this.getOptions(); - const callback = this.async(); - - if (cold) { - const pPath = options.path ? options.path : process.cwd(); - const pMaps = Array.isArray(options.maps) ? options.maps : [options.maps]; - const pUrls = Array.isArray(options.urls) ? options.urls : [options.urls]; - - // Filter out any empty (undefined, null) values in the option arrays - const urls = pUrls.filter((item) => { - if (item) return true; - return false; - }); + const options = this.getOptions(); + const callback = this.async(); - const maps = pMaps.filter((item) => { - if (item) return true; - return false; - }); + if (cold) { + const pPath = options.path ? options.path : process.cwd(); + const pMaps = Array.isArray(options.maps) ? options.maps : [options.maps]; + const pUrls = Array.isArray(options.urls) ? options.urls : [options.urls]; - // Load eik config from eik.json or package.json - const eikConfig = await helpers.getDefaults(pPath); + // Filter out any empty (undefined, null) values in the option arrays + const urls = pUrls.filter((item) => { + if (item) return true; + return false; + }); - // Merge map from eik config and the plugin options and Fetch all import maps over http - const fetchedMaps = await utils.fetchImportMaps([...eikConfig.map, ...urls]); + const maps = pMaps.filter((item) => { + if (item) return true; + return false; + }); - // Validate each import map and push each import statement into a dictionary - maps.concat(fetchedMaps).map((item) => utils.validate(item)).forEach((item) => { - item.forEach((obj) => { - dictionary.set(obj.key, obj.value); - }); - }); + // Load eik config from eik.json or package.json + const eikConfig = await helpers.getDefaults(pPath); - // Loading of config and import maps should only happen once - cold = false; - } + // Merge map from eik config and the plugin options and Fetch all import maps over http + const fetchedMaps = await utils.fetchImportMaps([ + ...eikConfig.map, + ...urls, + ]); - new Promise((resolve) => { - resolve({ - dictionary, - source, - }); - }) - .then(standardImport) - .then(dynamicImport) - .then(sideEffectsImport) - .then((obj) => { - callback(null, obj.source); + // Validate each import map and push each import statement into a dictionary + maps + .concat(fetchedMaps) + .map((item) => utils.validate(item)) + .forEach((item) => { + item.forEach((obj) => { + dictionary.set(obj.key, obj.value); }); + }); + + // Loading of config and import maps should only happen once + cold = false; + } + + new Promise((resolve) => { + resolve({ + dictionary, + source, + }); + }) + .then(standardImport) + .then(dynamicImport) + .then(sideEffectsImport) + .then((obj) => { + callback(null, obj.source); + }); } module.exports = loader; diff --git a/src/parsers.cjs b/src/parsers.cjs index 02c07a6..b6ac86a 100644 --- a/src/parsers.cjs +++ b/src/parsers.cjs @@ -1,8 +1,14 @@ -const standardImport = (flags = 'sgm') => new RegExp('(import)\\s*([\\w{},\\n\\s\\[\\]\\*\\.]+?)\\s*(from)\\s*[\'"]([\\w@\\-\\./]+?)[\'"]', flags); +const standardImport = (flags = "sgm") => + new RegExp( + "(import)\\s*([\\w{},\\n\\s\\[\\]\\*\\.]+?)\\s*(from)\\s*['\"]([\\w@\\-\\./]+?)['\"]", + flags, + ); module.exports.standardImport = standardImport; -const dynamicImport = (flags = 'gm') => new RegExp('(import)[(][\'"](.+?)[\'"][)]', flags); +const dynamicImport = (flags = "gm") => + new RegExp("(import)[(]['\"](.+?)['\"][)]", flags); module.exports.dynamicImport = dynamicImport; -const sideEffectsImport = (flags = 'gm') => new RegExp('(import)\\s*[\'"](.+?)[\'"]', flags); +const sideEffectsImport = (flags = "gm") => + new RegExp("(import)\\s*['\"](.+?)['\"]", flags); module.exports.sideEffectsImport = sideEffectsImport; diff --git a/src/utils.cjs b/src/utils.cjs index a5c2744..07be5c2 100644 --- a/src/utils.cjs +++ b/src/utils.cjs @@ -1,50 +1,56 @@ -const { request } = require('undici'); +const { request } = require("undici"); const isBare = (str) => { - if (str.startsWith('/') || str.startsWith('./') || str.startsWith('../') || str.substr(0, 7) === 'http://' || str.substr(0, 8) === 'https://') { - return false; - } - return true; + if ( + str.startsWith("/") || + str.startsWith("./") || + str.startsWith("../") || + str.substr(0, 7) === "http://" || + str.substr(0, 8) === "https://" + ) { + return false; + } + return true; }; module.exports.isBare = isBare; -const isString = (str) => typeof str === 'string'; +const isString = (str) => typeof str === "string"; module.exports.isString = isString; -const validate = (map) => Object.keys(map.imports).map((key) => { +const validate = (map) => + Object.keys(map.imports).map((key) => { const value = map.imports[key]; if (isBare(value)) { - throw Error(`Import specifier can NOT be mapped to a bare import statement. Import specifier "${key}" is being wrongly mapped to "${value}"`); + throw Error( + `Import specifier can NOT be mapped to a bare import statement. Import specifier "${key}" is being wrongly mapped to "${value}"`, + ); } return { key, value }; -}); + }); module.exports.validate = validate; const fetchImportMaps = async (urls = []) => { - try { - const maps = urls.map(async (map) => { - const { - statusCode, - body, - } = await request(map, { maxRedirections: 2 }); - - if (statusCode === 404) { - throw new Error('Import map could not be found on server'); - } else if (statusCode >= 400 && statusCode < 500) { - throw new Error('Server rejected client request'); - } else if (statusCode >= 500) { - throw new Error('Server error'); - } - - return body.json(); - }); - return await Promise.all(maps); - } catch (err) { - throw new Error( - `Unable to load import map file from server: ${err.message}`, - ); - } + try { + const maps = urls.map(async (map) => { + const { statusCode, body } = await request(map, { maxRedirections: 2 }); + + if (statusCode === 404) { + throw new Error("Import map could not be found on server"); + } else if (statusCode >= 400 && statusCode < 500) { + throw new Error("Server rejected client request"); + } else if (statusCode >= 500) { + throw new Error("Server error"); + } + + return body.json(); + }); + return await Promise.all(maps); + } catch (err) { + throw new Error( + `Unable to load import map file from server: ${err.message}`, + ); + } }; module.exports.fetchImportMaps = fetchImportMaps; diff --git a/test/builders.js b/test/builders.js index 9daec49..dc6c6fd 100644 --- a/test/builders.js +++ b/test/builders.js @@ -1,8 +1,12 @@ -import tap from 'tap'; -import { standardImport, dynamicImport, sideEffectsImport } from '../src/builders.cjs'; +import tap from "tap"; +import { + standardImport, + dynamicImport, + sideEffectsImport, +} from "../src/builders.cjs"; -tap.test('.standardImport() - Replace module name', (t) => { - const source = ` +tap.test(".standardImport() - Replace module name", (t) => { + const source = ` import{ export1 }from "module-a"; import {export2} from 'module-b'; import { @@ -10,57 +14,66 @@ tap.test('.standardImport() - Replace module name', (t) => { export4, } from "module-c"; `; - const dictionary = new Map([ - ['module-a', './REPLACED-A.js'], - ['module-c', './REPLACED-C.js'], - ]); + const dictionary = new Map([ + ["module-a", "./REPLACED-A.js"], + ["module-c", "./REPLACED-C.js"], + ]); - const result = standardImport({ - dictionary, - source, - }); + const result = standardImport({ + dictionary, + source, + }); - t.matchSnapshot(result.source, 'should replaced matched values with dictionary values'); - t.end(); + t.matchSnapshot( + result.source, + "should replaced matched values with dictionary values", + ); + t.end(); }); -tap.test('.dynamicImport() - Replace module name', (t) => { - const source = ` +tap.test(".dynamicImport() - Replace module name", (t) => { + const source = ` var a = import("module-a") let b = await import("module-b"); import('module-c').then((module) => { // Do something with the module. }); `; - const dictionary = new Map([ - ['module-a', './REPLACED-A.js'], - ['module-c', './REPLACED-C.js'], - ]); + const dictionary = new Map([ + ["module-a", "./REPLACED-A.js"], + ["module-c", "./REPLACED-C.js"], + ]); - const result = dynamicImport({ - dictionary, - source, - }); + const result = dynamicImport({ + dictionary, + source, + }); - t.matchSnapshot(result.source, 'should replaced matched values with dictionary values'); - t.end(); + t.matchSnapshot( + result.source, + "should replaced matched values with dictionary values", + ); + t.end(); }); -tap.test('.sideEffectsImport() - Replace module name', (t) => { - const source = ` +tap.test(".sideEffectsImport() - Replace module name", (t) => { + const source = ` import 'module-a';import 'module-b' import "module-c"; `; - const dictionary = new Map([ - ['module-a', './REPLACED-A.js'], - ['module-c', './REPLACED-C.js'], - ]); + const dictionary = new Map([ + ["module-a", "./REPLACED-A.js"], + ["module-c", "./REPLACED-C.js"], + ]); - const result = sideEffectsImport({ - dictionary, - source, - }); + const result = sideEffectsImport({ + dictionary, + source, + }); - t.matchSnapshot(result.source, 'should replaced matched values with dictionary values'); - t.end(); + t.matchSnapshot( + result.source, + "should replaced matched values with dictionary values", + ); + t.end(); }); diff --git a/test/loader.js b/test/loader.js index 06ef23b..72a8734 100644 --- a/test/loader.js +++ b/test/loader.js @@ -1,271 +1,305 @@ -import { createFsFromVolume, Volume } from 'memfs'; -import { URL } from 'node:url'; -import webpack from 'webpack'; -import fastify from 'fastify'; -import path from 'node:path'; -import tap from 'tap'; -import fs from 'node:fs'; +import { createFsFromVolume, Volume } from "memfs"; +import { URL } from "node:url"; +import webpack from "webpack"; +import fastify from "fastify"; +import path from "node:path"; +import tap from "tap"; +import fs from "node:fs"; -const LOADER = new URL('../src/loader.cjs', import.meta.url).pathname; -const FILE = new URL('../fixtures/modules/simple/main.js', import.meta.url).pathname; +const LOADER = new URL("../src/loader.cjs", import.meta.url).pathname; +const FILE = new URL("../fixtures/modules/simple/main.js", import.meta.url) + .pathname; /* * When running tests on Windows, the output code get some extra \r on each line. * Remove these so snapshots work on all OSes. */ -const clean = (str) => str.split('\r').join(''); +const clean = (str) => str.split("\r").join(""); const build = ({ - options = {}, - outputFileName = 'bundle.js', - outputPath = '/', - inputEntry = '', -} = {}) => new Promise((resolve, reject) => { + options = {}, + outputFileName = "bundle.js", + outputPath = "/", + inputEntry = "", +} = {}) => + new Promise((resolve, reject) => { const compiler = webpack({ - experiments: { - outputModule: true, + experiments: { + outputModule: true, + }, + entry: inputEntry, + mode: "production", + output: { + environment: { + module: true, }, - entry: inputEntry, - mode: 'production', - output: { - environment: { - module: true, + filename: outputFileName, + path: outputPath, + }, + module: { + rules: [ + { + test: /\.js$/, + use: { + loader: LOADER, + options, }, - filename: outputFileName, - path: outputPath, - }, - module: { - rules: [ - { - test: /\.js$/, - use: { - loader: LOADER, - options, - }, - }, - ], - }, + }, + ], + }, }); const fileSystem = createFsFromVolume(new Volume()); compiler.outputFileSystem = fileSystem; compiler.run((err, stats) => { - if (err) reject(err); - if (stats.hasErrors()) reject(stats.toJson().errors); + if (err) reject(err); + if (stats.hasErrors()) reject(stats.toJson().errors); - const content = fileSystem.readFileSync('/bundle.js', 'utf8'); - resolve(content); + const content = fileSystem.readFileSync("/bundle.js", "utf8"); + resolve(content); }); -}); + }); -tap.test('loader() - import map fetched from a URL', async (t) => { - const app = fastify(); - app.server.keepAliveTimeout = 20; - app.get('/one', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v2', - }, - }); +tap.test("loader() - import map fetched from a URL", async (t) => { + const app = fastify(); + app.server.keepAliveTimeout = 20; + app.get("/one", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v2", + }, }); - app.get('/two', (request, reply) => { - reply.send({ - imports: { - 'lit-html': 'https://cdn.eik.dev/lit-html/v1', - }, - }); + }); + app.get("/two", (request, reply) => { + reply.send({ + imports: { + "lit-html": "https://cdn.eik.dev/lit-html/v1", + }, }); - const address = await app.listen(); + }); + const address = await app.listen(); - const bundle = await build({ - inputEntry: FILE, - options: { - maps: [{ - imports: { - 'lit-html/lit-html': 'https://cdn.eik.dev/lit-html/v2', - }, - }], - urls: [`${address}/one`, `${address}/two`], + const bundle = await build({ + inputEntry: FILE, + options: { + maps: [ + { + imports: { + "lit-html/lit-html": "https://cdn.eik.dev/lit-html/v2", + }, }, - }); + ], + urls: [`${address}/one`, `${address}/two`], + }, + }); - t.matchSnapshot(clean(bundle), 'import maps from urls'); - await app.close(); - t.end(); + t.matchSnapshot(clean(bundle), "import maps from urls"); + await app.close(); + t.end(); }); -tap.test('loader() - import map fetched from a URL via eik.json', async (t) => { - const app = fastify(); - app.server.keepAliveTimeout = 20; - app.get('/one', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v2', - 'lit-html': 'https://cdn.eik.dev/lit-html/v1', - 'lit-html/lit-html': 'https://cdn.eik.dev/lit-html/v2', - }, - }); +tap.test("loader() - import map fetched from a URL via eik.json", async (t) => { + const app = fastify(); + app.server.keepAliveTimeout = 20; + app.get("/one", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v2", + "lit-html": "https://cdn.eik.dev/lit-html/v1", + "lit-html/lit-html": "https://cdn.eik.dev/lit-html/v2", + }, }); - const address = await app.listen(); + }); + const address = await app.listen(); - await fs.promises.writeFile(path.join(process.cwd(), 'eik.json'), JSON.stringify({ - name: 'test', - server: address, - version: '1.0.0', - files: { - '/css': '/src/css/**/*', - '/js': '/src/js/**/*', - }, - 'import-map': `${address}/one`, - })); + await fs.promises.writeFile( + path.join(process.cwd(), "eik.json"), + JSON.stringify({ + name: "test", + server: address, + version: "1.0.0", + files: { + "/css": "/src/css/**/*", + "/js": "/src/js/**/*", + }, + "import-map": `${address}/one`, + }), + ); - const bundle = await build({ - inputEntry: FILE, - }); + const bundle = await build({ + inputEntry: FILE, + }); - t.matchSnapshot(clean(bundle), 'eik.json import-map string'); - await app.close(); - await fs.promises.unlink(path.join(process.cwd(), 'eik.json')); - t.end(); + t.matchSnapshot(clean(bundle), "eik.json import-map string"); + await app.close(); + await fs.promises.unlink(path.join(process.cwd(), "eik.json")); + t.end(); }); -tap.test('loader() - Import map defined through option "maps" take precedence over import map defined in eik.json', async (t) => { +tap.test( + 'loader() - Import map defined through option "maps" take precedence over import map defined in eik.json', + async (t) => { const app = fastify(); app.server.keepAliveTimeout = 20; - app.get('/one', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v1', - }, - }); + app.get("/one", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v1", + }, + }); }); const address = await app.listen(); - await fs.promises.writeFile(path.join(process.cwd(), 'eik.json'), JSON.stringify({ - name: 'test', + await fs.promises.writeFile( + path.join(process.cwd(), "eik.json"), + JSON.stringify({ + name: "test", server: address, - version: '1.0.0', + version: "1.0.0", files: { - '/css': '/src/css/', - '/js': '/src/js/', + "/css": "/src/css/", + "/js": "/src/js/", }, - 'import-map': `${address}/one`, - })); + "import-map": `${address}/one`, + }), + ); const bundle = await build({ - inputEntry: FILE, - options: { - maps: [{ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v2', - }, - }], - }, + inputEntry: FILE, + options: { + maps: [ + { + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v2", + }, + }, + ], + }, }); - t.matchSnapshot(clean(bundle), 'Should rewrite import statement to https://cdn.eik.dev/lit-element/v2'); + t.matchSnapshot( + clean(bundle), + "Should rewrite import statement to https://cdn.eik.dev/lit-element/v2", + ); await app.close(); - await fs.promises.unlink(path.join(process.cwd(), 'eik.json')); + await fs.promises.unlink(path.join(process.cwd(), "eik.json")); t.end(); -}); + }, +); -tap.test('loader() - Import map defined through option "urls" argument take precedence over import map defined in eik.json', async (t) => { +tap.test( + 'loader() - Import map defined through option "urls" argument take precedence over import map defined in eik.json', + async (t) => { const app = fastify(); app.server.keepAliveTimeout = 20; - app.get('/one', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v1', - }, - }); + app.get("/one", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v1", + }, + }); }); - app.get('/two', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v2', - }, - }); + app.get("/two", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v2", + }, + }); }); const address = await app.listen(); - await fs.promises.writeFile(path.join(process.cwd(), 'eik.json'), JSON.stringify({ - name: 'test', + await fs.promises.writeFile( + path.join(process.cwd(), "eik.json"), + JSON.stringify({ + name: "test", server: address, - version: '1.0.0', + version: "1.0.0", files: { - '/css': '/src/css/', - '/js': '/src/js/', + "/css": "/src/css/", + "/js": "/src/js/", }, - 'import-map': `${address}/one`, - })); + "import-map": `${address}/one`, + }), + ); const bundle = await build({ - inputEntry: FILE, - options: { - urls: [ - `${address}/two`, - ], - }, + inputEntry: FILE, + options: { + urls: [`${address}/two`], + }, }); - t.matchSnapshot(clean(bundle), 'Should rewrite import statement to https://cdn.eik.dev/lit-element/v2'); + t.matchSnapshot( + clean(bundle), + "Should rewrite import statement to https://cdn.eik.dev/lit-element/v2", + ); await app.close(); - await fs.promises.unlink(path.join(process.cwd(), 'eik.json')); + await fs.promises.unlink(path.join(process.cwd(), "eik.json")); t.end(); -}); + }, +); -tap.test('loader() - Import map defined through option "maps" argument take precedence over import map defined through option "urls" argument', async (t) => { +tap.test( + 'loader() - Import map defined through option "maps" argument take precedence over import map defined through option "urls" argument', + async (t) => { const app = fastify(); app.server.keepAliveTimeout = 20; - app.get('/one', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v0', - }, - }); + app.get("/one", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v0", + }, + }); }); - app.get('/two', (request, reply) => { - reply.send({ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v1', - }, - }); + app.get("/two", (request, reply) => { + reply.send({ + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v1", + }, + }); }); const address = await app.listen(); - await fs.promises.writeFile(path.join(process.cwd(), 'eik.json'), JSON.stringify({ - name: 'test', + await fs.promises.writeFile( + path.join(process.cwd(), "eik.json"), + JSON.stringify({ + name: "test", server: address, - version: '1.0.0', + version: "1.0.0", files: { - '/css': '/src/css/', - '/js': '/src/js/', + "/css": "/src/css/", + "/js": "/src/js/", }, - 'import-map': `${address}/one`, - })); + "import-map": `${address}/one`, + }), + ); const bundle = await build({ - inputEntry: FILE, - options: { - maps: [{ - imports: { - 'lit-element': 'https://cdn.eik.dev/lit-element/v2', - }, - }], - urls: [ - `${address}/two`, - ], - }, + inputEntry: FILE, + options: { + maps: [ + { + imports: { + "lit-element": "https://cdn.eik.dev/lit-element/v2", + }, + }, + ], + urls: [`${address}/two`], + }, }); - t.matchSnapshot(clean(bundle), 'Should rewrite import statement to https://cdn.eik.dev/lit-element/v2'); + t.matchSnapshot( + clean(bundle), + "Should rewrite import statement to https://cdn.eik.dev/lit-element/v2", + ); await app.close(); - await fs.promises.unlink(path.join(process.cwd(), 'eik.json')); + await fs.promises.unlink(path.join(process.cwd(), "eik.json")); t.end(); -}); + }, +); diff --git a/test/parsers.js b/test/parsers.js index 3aabae7..afb21e5 100644 --- a/test/parsers.js +++ b/test/parsers.js @@ -1,169 +1,201 @@ -import tap from 'tap'; -import { standardImport, dynamicImport, sideEffectsImport } from '../src/parsers.cjs'; +import tap from "tap"; +import { + standardImport, + dynamicImport, + sideEffectsImport, +} from "../src/parsers.cjs"; // Standard examples from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import -tap.test('.standardImport() - import defaultExport from "module-name";', (t) => { - const rx = standardImport('sm'); +tap.test( + '.standardImport() - import defaultExport from "module-name";', + (t) => { + const rx = standardImport("sm"); const str = 'import defaultExport from "module-name";'; const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'defaultExport', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "defaultExport", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); t.end(); -}); + }, +); tap.test('.standardImport() - import * as name from "module-name";', (t) => { - const rx = standardImport('sm'); - const str = 'import * as name from "module-name";'; - const grp = str.match(rx); - - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '* as name', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); - t.end(); + const rx = standardImport("sm"); + const str = 'import * as name from "module-name";'; + const grp = str.match(rx); + + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "* as name", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); + t.end(); }); tap.test('.standardImport() - import { export1 } from "module-name";', (t) => { - const rx = standardImport('sm'); - const str = 'import { export1 } from "module-name";'; - const grp = str.match(rx); - - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{ export1 }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); - t.end(); + const rx = standardImport("sm"); + const str = 'import { export1 } from "module-name";'; + const grp = str.match(rx); + + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "{ export1 }", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.standardImport() - import { export1 as alias1 } from "module-name";', (t) => { - const rx = standardImport('sm'); +tap.test( + '.standardImport() - import { export1 as alias1 } from "module-name";', + (t) => { + const rx = standardImport("sm"); const str = 'import { export1 as alias1 } from "module-name";'; const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{ export1 as alias1 }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "{ export1 as alias1 }", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); t.end(); -}); + }, +); -tap.test('.standardImport() - import { export1 , export2 } from "module-name";', (t) => { - const rx = standardImport('sm'); +tap.test( + '.standardImport() - import { export1 , export2 } from "module-name";', + (t) => { + const rx = standardImport("sm"); const str = 'import { export1 , export2 } from "module-name";'; const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{ export1 , export2 }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "{ export1 , export2 }", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); t.end(); -}); - -tap.test('.standardImport() - import { export1 , export2 as alias2 , [...] } from "module-name";', (t) => { - const rx = standardImport('sm'); - const str = 'import { export1 , export2 as alias2 , [...] } from "module-name";'; + }, +); + +tap.test( + '.standardImport() - import { export1 , export2 as alias2 , [...] } from "module-name";', + (t) => { + const rx = standardImport("sm"); + const str = + 'import { export1 , export2 as alias2 , [...] } from "module-name";'; const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{ export1 , export2 as alias2 , [...] }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal( + grp[2], + "{ export1 , export2 as alias2 , [...] }", + 'should be the "export" group', + ); + t.equal(grp[4], "module-name", 'should be the "module name" group'); t.end(); -}); - -tap.test('.standardImport() - import defaultExport, { export1 [ , [...] ] } from "module-name";', (t) => { - const rx = standardImport('sm'); - const str = 'import defaultExport, { export1 [ , [...] ] } from "module-name";'; + }, +); + +tap.test( + '.standardImport() - import defaultExport, { export1 [ , [...] ] } from "module-name";', + (t) => { + const rx = standardImport("sm"); + const str = + 'import defaultExport, { export1 [ , [...] ] } from "module-name";'; const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'defaultExport, { export1 [ , [...] ] }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal( + grp[2], + "defaultExport, { export1 [ , [...] ] }", + 'should be the "export" group', + ); + t.equal(grp[4], "module-name", 'should be the "module name" group'); t.end(); -}); + }, +); -tap.test('.standardImport() - import defaultExport, * as name from "module-name";', (t) => { - const rx = standardImport('sm'); +tap.test( + '.standardImport() - import defaultExport, * as name from "module-name";', + (t) => { + const rx = standardImport("sm"); const str = 'import defaultExport, * as name from "module-name";'; const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'defaultExport, * as name', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "defaultExport, * as name", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); t.end(); -}); + }, +); tap.test('.dynamicImport() - var promise = import("module-name");', (t) => { - const rx = dynamicImport('m'); - const str = 'var promise = import("module-name");'; - const grp = str.match(rx); + const rx = dynamicImport("m"); + const str = 'var promise = import("module-name");'; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); tap.test('.sideEffectsImport() - import "module-name";', (t) => { - const rx = sideEffectsImport('m'); - const str = 'import "module-name";'; - const grp = str.match(rx); + const rx = sideEffectsImport("m"); + const str = 'import "module-name";'; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); // Different formating structures -tap.test('.standardImport() - No spacing', (t) => { - const rx = standardImport('sm'); - const str = 'import{export1}from"module-name";'; - const grp = str.match(rx); +tap.test(".standardImport() - No spacing", (t) => { + const rx = standardImport("sm"); + const str = 'import{export1}from"module-name";'; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{export1}', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "{export1}", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.standardImport() - Single qoutes', (t) => { - const rx = standardImport('sm'); - const str = 'import { export1 } from \'module-name\';'; - const grp = str.match(rx); +tap.test(".standardImport() - Single qoutes", (t) => { + const rx = standardImport("sm"); + const str = "import { export1 } from 'module-name';"; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{ export1 }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "{ export1 }", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.standardImport() - Missing ending semicolon', (t) => { - const rx = standardImport('sm'); - const str = 'import { export1 } from "module-name"'; - const grp = str.match(rx); +tap.test(".standardImport() - Missing ending semicolon", (t) => { + const rx = standardImport("sm"); + const str = 'import { export1 } from "module-name"'; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '{ export1 }', 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "{ export1 }", 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); + t.end(); }); tap.test('.standardImport() - Multiline "export" values', (t) => { - const rx = standardImport('sm'); - const str = `import { + const rx = standardImport("sm"); + const str = `import { export1, export2, export3, } from "module-name";`; - const grp = str.match(rx); + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.matchSnapshot(grp[2], 'should be the "export" group'); - t.equal(grp[4], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.matchSnapshot(grp[2], 'should be the "export" group'); + t.equal(grp[4], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.standardImport() - Multiple import statements on new lines', (t) => { - const rx = standardImport(); - const str = ` +tap.test(".standardImport() - Multiple import statements on new lines", (t) => { + const rx = standardImport(); + const str = ` import{ export1 }from "module-a"; import {export2} from"module-b" import { @@ -171,156 +203,222 @@ tap.test('.standardImport() - Multiple import statements on new lines', (t) => { export4, } from "module-c"; `; - const grp = [...str.matchAll(rx)]; - - t.equal(grp[0][1], 'import', 'should be the "import" group'); - t.equal(grp[0][2], '{ export1 }', 'should be the "export" group of the 1st import'); - t.equal(grp[0][4], 'module-a', 'should be the "module name" group of the 1st import'); - - t.equal(grp[1][1], 'import', 'should be the "import" group'); - t.equal(grp[1][2], '{export2}', 'should be the "export" group of the 2nd import'); - t.equal(grp[1][4], 'module-b', 'should be the "module name" group of the 2nd import'); - - t.equal(grp[2][1], 'import', 'should be the "import" group'); - t.matchSnapshot(grp[2][2], 'should be the "export" group'); - t.equal(grp[2][4], 'module-c', 'should be the "module name" group of the 3rd import'); - t.end(); + const grp = [...str.matchAll(rx)]; + + t.equal(grp[0][1], "import", 'should be the "import" group'); + t.equal( + grp[0][2], + "{ export1 }", + 'should be the "export" group of the 1st import', + ); + t.equal( + grp[0][4], + "module-a", + 'should be the "module name" group of the 1st import', + ); + + t.equal(grp[1][1], "import", 'should be the "import" group'); + t.equal( + grp[1][2], + "{export2}", + 'should be the "export" group of the 2nd import', + ); + t.equal( + grp[1][4], + "module-b", + 'should be the "module name" group of the 2nd import', + ); + + t.equal(grp[2][1], "import", 'should be the "import" group'); + t.matchSnapshot(grp[2][2], 'should be the "export" group'); + t.equal( + grp[2][4], + "module-c", + 'should be the "module name" group of the 3rd import', + ); + t.end(); }); -tap.test('.standardImport() - Multiple import statements concatinated', (t) => { - const rx = standardImport(); - const str = ` +tap.test(".standardImport() - Multiple import statements concatinated", (t) => { + const rx = standardImport(); + const str = ` import{ export1 }from "module-a";import {export2} from"module-b"import { export3, export4, } from "module-c"; `; - const grp = [...str.matchAll(rx)]; - - t.equal(grp[0][1], 'import', 'should be the "import" group'); - t.equal(grp[0][2], '{ export1 }', 'should be the "export" group of the 1st import'); - t.equal(grp[0][4], 'module-a', 'should be the "module name" group of the 1st import'); - - t.equal(grp[1][1], 'import', 'should be the "import" group'); - t.equal(grp[1][2], '{export2}', 'should be the "export" group of the 2nd import'); - t.equal(grp[1][4], 'module-b', 'should be the "module name" group of the 2nd import'); - - t.equal(grp[2][1], 'import', 'should be the "import" group'); - t.matchSnapshot(grp[2][2], 'should be the "export" group'); - t.equal(grp[2][4], 'module-c', 'should be the "module name" group of the 3rd import'); - t.end(); + const grp = [...str.matchAll(rx)]; + + t.equal(grp[0][1], "import", 'should be the "import" group'); + t.equal( + grp[0][2], + "{ export1 }", + 'should be the "export" group of the 1st import', + ); + t.equal( + grp[0][4], + "module-a", + 'should be the "module name" group of the 1st import', + ); + + t.equal(grp[1][1], "import", 'should be the "import" group'); + t.equal( + grp[1][2], + "{export2}", + 'should be the "export" group of the 2nd import', + ); + t.equal( + grp[1][4], + "module-b", + 'should be the "module name" group of the 2nd import', + ); + + t.equal(grp[2][1], "import", 'should be the "import" group'); + t.matchSnapshot(grp[2][2], 'should be the "export" group'); + t.equal( + grp[2][4], + "module-c", + 'should be the "module name" group of the 3rd import', + ); + t.end(); }); -tap.test('.standardImport() - is lazy', (t) => { - const rx = standardImport(); - const str = 'imported to know which is which from "f asfasdf asdfasdf asdfasdf adsfasdf"'; - const grp = str.match(rx); - t.equal(grp, null, `should not match ${str}`); - t.end(); +tap.test(".standardImport() - is lazy", (t) => { + const rx = standardImport(); + const str = + 'imported to know which is which from "f asfasdf asdfasdf asdfasdf adsfasdf"'; + const grp = str.match(rx); + t.equal(grp, null, `should not match ${str}`); + t.end(); }); -tap.test('.standardImport() - importStar case', (t) => { - const rx = standardImport('sm'); - const str = 'importStar:hf,__importDefault:bf,__classPrivateFieldGet:vf,__classPrivateFieldSet:gf,__classPrivateFieldIn:yf}=ho.default;function vo(e){return e}function go(e,t){t===void 0&&(t=vo);var r=[],n=!1,o={read:function(){if(n)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return r.length?r[r.length-1]:e},useMedium:function(i){var a=t(i,n);return r.push(a),function(){r=r.filter(function(l){return l!==a})}},assignSyncMedium:function(i){for(n=!0;r.length;){var a=r;r=[],a.forEach(i)}r={push:function(l){return i(l)},filter:function(){return r}}},assignMedium:function(i){n=!0;var a=[];if(r.length){var l=r;r=[],l.forEach(i),a=r}var s=function(){var u=a;a=[],u.forEach(i)},c=function(){return Promise.resolve().then(s)};c(),r={push:function(u){a.push(u),c()},filter:function(u){return a=a.filter(u),r}}}};return o}function Ze(e,t){return t===void 0&&(t=vo),go(e,t)}function br(e){e===void 0&&(e={});var t=go(null);return t.options=bo({async:!0,ssr:!1},e),t}var Ct=Ze({},function(e){var t=e.target,r=e.currentTarget;return{target:t,currentTarget:r}}),Pt=Ze(),yo=Ze(),xo=br({async:!0});var Ha=[],vr=O.forwardRef(function(t,r){var n,o=O.useState(),i=o[0],a=o[1],l=O.useRef(),s=O.useRef(!1),c=O.useRef(null),u=t.children,f=t.disabled,d=t.noFocusGuards,m=t.persistentFocus,p=t.crossFrame,h=t.autoFocus,v=t.allowTextSelection,g=t.group,y=t.className,w=t.whiteList,E=t.hasPositiveIndices,A=t.shards,I=A===void 0?Ha:A,q=t.as,D=q===void 0?"div":q,N=t.lockProps,S=N===void 0?{}:N,$=t.sideCar,K=t.returnFocus,W=t.focusOptions,M=t.onActivation,V=t.onDeactivation,Ee=O.useState({}),L=Ee[0],Bt=O.useCallback(function(){c.current=c.current||document&&document.activeElement,l.current&&M&&M(l.current),s.current=!0},[M]),jt=O.useCallback(function(){s.current=!1,V&&V(l.current)},[V]);Ma(function(){f||(c.current=null)},[]);var De=O.useCallback(function(z){var ue=c.current;if(ue&&ue.focus){var Wt=typeof K=="function"?K(ue):K;if(Wt){var $r=typeof Wt=="object"?Wt:void 0;c.current=null,z?Promise.resolve().then(function(){return ue.focus($r)}):ue.focus($r)}}},[K]),it=O.useCallback(function(z){s.current&&Ct.useMedium(z)},[]),at=Pt.useMedium,lt=O.useCallback(function(z){l.current!==z&&(l.current=z,a(z))},[]),st=pe((n={},n[wt]=f&&"disabled",n[Xe]=g,n),S),T=d!==!0,U=T&&d!=="tail",ce=pr([r,lt]);return O.createElement(O.Fragment,null,T&&[O.createElement("div",{key:"guard-first","data-focus-guard":!0,tabIndex:f?-1:0,style:Ae}),E?O.createElement("div",{key:"guard-nearest","data-focus-guard":!0,tabIndex:f?-1:1,style:Ae}):null],!f&&O.createElement($,{id:L,sideCar:xo,observed:i,disabled:f,persistentFocus:m,crossFrame:p,autoFocus:h,whiteList:w,shards:I,onActivation:Bt,onDeactivation:jt,returnFocus:De,focusOptions:W}),O.createElement(D,pe({ref:ce},st,{className:y,onBlur:at,onFocus:it}),u),U&&O.createElement("div",{"data-focus-guard":!0,tabIndex:f?-1:0,style:Ae}))});vr.propTypes={};vr.defaultProps={children:void 0,disabled:!1,returnFocus:!1,focusOptions:void 0,noFocusGuards:!1,autoFocus:!0,persistentFocus:!1,crossFrame:!0,hasPositiveIndices:void 0,allowTextSelection:void 0,group:void 0,className:void 0,whiteList:void 0,shards:void 0,as:"div",lockProps:{},onActivation:void 0,onDeactivation:void 0};var gr=vr;import*as jo from"react"'; - const grp = str.match(rx); +tap.test(".standardImport() - importStar case", (t) => { + const rx = standardImport("sm"); + const str = + 'importStar:hf,__importDefault:bf,__classPrivateFieldGet:vf,__classPrivateFieldSet:gf,__classPrivateFieldIn:yf}=ho.default;function vo(e){return e}function go(e,t){t===void 0&&(t=vo);var r=[],n=!1,o={read:function(){if(n)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return r.length?r[r.length-1]:e},useMedium:function(i){var a=t(i,n);return r.push(a),function(){r=r.filter(function(l){return l!==a})}},assignSyncMedium:function(i){for(n=!0;r.length;){var a=r;r=[],a.forEach(i)}r={push:function(l){return i(l)},filter:function(){return r}}},assignMedium:function(i){n=!0;var a=[];if(r.length){var l=r;r=[],l.forEach(i),a=r}var s=function(){var u=a;a=[],u.forEach(i)},c=function(){return Promise.resolve().then(s)};c(),r={push:function(u){a.push(u),c()},filter:function(u){return a=a.filter(u),r}}}};return o}function Ze(e,t){return t===void 0&&(t=vo),go(e,t)}function br(e){e===void 0&&(e={});var t=go(null);return t.options=bo({async:!0,ssr:!1},e),t}var Ct=Ze({},function(e){var t=e.target,r=e.currentTarget;return{target:t,currentTarget:r}}),Pt=Ze(),yo=Ze(),xo=br({async:!0});var Ha=[],vr=O.forwardRef(function(t,r){var n,o=O.useState(),i=o[0],a=o[1],l=O.useRef(),s=O.useRef(!1),c=O.useRef(null),u=t.children,f=t.disabled,d=t.noFocusGuards,m=t.persistentFocus,p=t.crossFrame,h=t.autoFocus,v=t.allowTextSelection,g=t.group,y=t.className,w=t.whiteList,E=t.hasPositiveIndices,A=t.shards,I=A===void 0?Ha:A,q=t.as,D=q===void 0?"div":q,N=t.lockProps,S=N===void 0?{}:N,$=t.sideCar,K=t.returnFocus,W=t.focusOptions,M=t.onActivation,V=t.onDeactivation,Ee=O.useState({}),L=Ee[0],Bt=O.useCallback(function(){c.current=c.current||document&&document.activeElement,l.current&&M&&M(l.current),s.current=!0},[M]),jt=O.useCallback(function(){s.current=!1,V&&V(l.current)},[V]);Ma(function(){f||(c.current=null)},[]);var De=O.useCallback(function(z){var ue=c.current;if(ue&&ue.focus){var Wt=typeof K=="function"?K(ue):K;if(Wt){var $r=typeof Wt=="object"?Wt:void 0;c.current=null,z?Promise.resolve().then(function(){return ue.focus($r)}):ue.focus($r)}}},[K]),it=O.useCallback(function(z){s.current&&Ct.useMedium(z)},[]),at=Pt.useMedium,lt=O.useCallback(function(z){l.current!==z&&(l.current=z,a(z))},[]),st=pe((n={},n[wt]=f&&"disabled",n[Xe]=g,n),S),T=d!==!0,U=T&&d!=="tail",ce=pr([r,lt]);return O.createElement(O.Fragment,null,T&&[O.createElement("div",{key:"guard-first","data-focus-guard":!0,tabIndex:f?-1:0,style:Ae}),E?O.createElement("div",{key:"guard-nearest","data-focus-guard":!0,tabIndex:f?-1:1,style:Ae}):null],!f&&O.createElement($,{id:L,sideCar:xo,observed:i,disabled:f,persistentFocus:m,crossFrame:p,autoFocus:h,whiteList:w,shards:I,onActivation:Bt,onDeactivation:jt,returnFocus:De,focusOptions:W}),O.createElement(D,pe({ref:ce},st,{className:y,onBlur:at,onFocus:it}),u),U&&O.createElement("div",{"data-focus-guard":!0,tabIndex:f?-1:0,style:Ae}))});vr.propTypes={};vr.defaultProps={children:void 0,disabled:!1,returnFocus:!1,focusOptions:void 0,noFocusGuards:!1,autoFocus:!0,persistentFocus:!1,crossFrame:!0,hasPositiveIndices:void 0,allowTextSelection:void 0,group:void 0,className:void 0,whiteList:void 0,shards:void 0,as:"div",lockProps:{},onActivation:void 0,onDeactivation:void 0};var gr=vr;import*as jo from"react"'; + const grp = str.match(rx); - t.not(grp, null, `should match ${str}`); + t.not(grp, null, `should match ${str}`); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], '*as jo', 'should be the "export" group'); - t.equal(grp[4], 'react', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "*as jo", 'should be the "export" group'); + t.equal(grp[4], "react", 'should be the "module name" group'); + t.end(); }); -tap.test('.dynamicImport() - Single qoutes', (t) => { - const rx = dynamicImport('m'); - const str = 'var promise = import(\'module-name\');'; - const grp = str.match(rx); +tap.test(".dynamicImport() - Single qoutes", (t) => { + const rx = dynamicImport("m"); + const str = "var promise = import('module-name');"; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.dynamicImport() - No ending semicolon', (t) => { - const rx = dynamicImport('m'); - const str = 'var promise = import("module-name")'; - const grp = str.match(rx); +tap.test(".dynamicImport() - No ending semicolon", (t) => { + const rx = dynamicImport("m"); + const str = 'var promise = import("module-name")'; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.dynamicImport() - With async await', (t) => { - const rx = dynamicImport('m'); - const str = 'var promise = await import("module-name");'; - const grp = str.match(rx); +tap.test(".dynamicImport() - With async await", (t) => { + const rx = dynamicImport("m"); + const str = 'var promise = await import("module-name");'; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.dynamicImport() - As promise chain', (t) => { - const rx = dynamicImport('m'); - const str = `import('module-name').then((module) => { +tap.test(".dynamicImport() - As promise chain", (t) => { + const rx = dynamicImport("m"); + const str = `import('module-name').then((module) => { // Do something with the module. });`; - const grp = str.match(rx); + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.dynamicImport() - Multiple imports', (t) => { - const rx = dynamicImport(); - const str = ` +tap.test(".dynamicImport() - Multiple imports", (t) => { + const rx = dynamicImport(); + const str = ` var a = import("module-a") let b = await import("module-b"); import('module-c').then((module) => { // Do something with the module. }); `; - const grp = [...str.matchAll(rx)]; - - t.equal(grp[0][1], 'import', 'should be the "import" group'); - t.equal(grp[0][2], 'module-a', 'should be the "module name" group of the 1st import'); - - t.equal(grp[1][1], 'import', 'should be the "import" group'); - t.equal(grp[1][2], 'module-b', 'should be the "module name" group of the 2nd import'); - - t.equal(grp[2][1], 'import', 'should be the "import" group'); - t.equal(grp[2][2], 'module-c', 'should be the "module name" group of the 3rd import'); - t.end(); + const grp = [...str.matchAll(rx)]; + + t.equal(grp[0][1], "import", 'should be the "import" group'); + t.equal( + grp[0][2], + "module-a", + 'should be the "module name" group of the 1st import', + ); + + t.equal(grp[1][1], "import", 'should be the "import" group'); + t.equal( + grp[1][2], + "module-b", + 'should be the "module name" group of the 2nd import', + ); + + t.equal(grp[2][1], "import", 'should be the "import" group'); + t.equal( + grp[2][2], + "module-c", + 'should be the "module name" group of the 3rd import', + ); + t.end(); }); tap.test('.sideEffectsImport() - Single qoutes";', (t) => { - const rx = sideEffectsImport('m'); - const str = 'import \'module-name\';'; - const grp = str.match(rx); + const rx = sideEffectsImport("m"); + const str = "import 'module-name';"; + const grp = str.match(rx); - t.equal(grp[1], 'import', 'should be the "import" group'); - t.equal(grp[2], 'module-name', 'should be the "module name" group'); - t.end(); + t.equal(grp[1], "import", 'should be the "import" group'); + t.equal(grp[2], "module-name", 'should be the "module name" group'); + t.end(); }); -tap.test('.sideEffectsImport() - Multiple imports', (t) => { - const rx = sideEffectsImport(); - const str = ` +tap.test(".sideEffectsImport() - Multiple imports", (t) => { + const rx = sideEffectsImport(); + const str = ` import 'module-a';import 'module-b' import "module-c"; `; - const grp = [...str.matchAll(rx)]; - - t.equal(grp[0][1], 'import', 'should be the "import" group'); - t.equal(grp[0][2], 'module-a', 'should be the "module name" group of the 1st import'); - - t.equal(grp[1][1], 'import', 'should be the "import" group'); - t.equal(grp[1][2], 'module-b', 'should be the "module name" group of the 2nd import'); - - t.equal(grp[2][1], 'import', 'should be the "import" group'); - t.equal(grp[2][2], 'module-c', 'should be the "module name" group of the 3rd import'); - t.end(); + const grp = [...str.matchAll(rx)]; + + t.equal(grp[0][1], "import", 'should be the "import" group'); + t.equal( + grp[0][2], + "module-a", + 'should be the "module name" group of the 1st import', + ); + + t.equal(grp[1][1], "import", 'should be the "import" group'); + t.equal( + grp[1][2], + "module-b", + 'should be the "module name" group of the 2nd import', + ); + + t.equal(grp[2][1], "import", 'should be the "import" group'); + t.equal( + grp[2][2], + "module-c", + 'should be the "module name" group of the 3rd import', + ); + t.end(); });