diff --git a/.github/workflows/e2e-linux.yml b/.github/workflows/e2e-linux.yml index 3f9770c..f2e6494 100644 --- a/.github/workflows/e2e-linux.yml +++ b/.github/workflows/e2e-linux.yml @@ -29,6 +29,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} diff --git a/.github/workflows/e2e-macOS.yml b/.github/workflows/e2e-macOS.yml index c145068..02a67c0 100644 --- a/.github/workflows/e2e-macOS.yml +++ b/.github/workflows/e2e-macOS.yml @@ -26,6 +26,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml index c784b7c..c5dfce4 100644 --- a/.github/workflows/e2e-windows.yml +++ b/.github/workflows/e2e-windows.yml @@ -26,6 +26,8 @@ jobs: - latest,parcel,typescript - latest,dumber,babel - latest,dumber,typescript + - latest,vite,babel + - latest,vite,typescript steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node_version }} diff --git a/__test__/before-task.spec.js b/__test__/before-task.spec.js index d5af5f0..19576d2 100644 --- a/__test__/before-task.spec.js +++ b/__test__/before-task.spec.js @@ -23,7 +23,7 @@ test('"before" task can select default-esnext preset', async t => { const result = await before({unattended: false, prompts}); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['app', 'webpack', 'babel', 'jest'] + preselectedFeatures: ['app', 'vite', 'babel', 'vitest'] }); }); @@ -40,7 +40,7 @@ test('"before" task can select default-typescript preset', async t => { const result = await before({unattended: false, prompts}); t.deepEqual(result, { silentQuestions: true, - preselectedFeatures: ['app', 'webpack', 'typescript', 'jest'] + preselectedFeatures: ['app', 'vite', 'typescript', 'vitest'] }); }); diff --git a/__test__/transforms.spec.js b/__test__/transforms.spec.js index f14f863..e03af2f 100644 --- a/__test__/transforms.spec.js +++ b/__test__/transforms.spec.js @@ -71,3 +71,67 @@ test.cb('ext-transform translates .ext file to .ts file when typescript is selec contents: Buffer.from('

') })); }); + +test.cb('ext-transform translates css files to .module.css files when css-module is selected', t => { + const jsExt = extTransform({}, ['css-module']); + const files = []; + + jsExt.pipe(new Writable({ + objectMode: true, + write(file, enc, cb) { + files.push(file); + cb(); + } + })); + + jsExt.on('end', () => { + t.is(files.length, 2); + t.is(files[0].path.replace(/\\/g, '/'), 'test/a.module.css'); + t.is(files[0].contents.toString(), '.p { color: green; }'); + t.is(files[1].path.replace(/\\/g, '/'), 'test/b.module.scss'); + t.is(files[1].contents.toString(), '.p { color: red; }'); + t.end(); + }) + + jsExt.write(new Vinyl({ + path: 'test/a.css', + contents: Buffer.from('.p { color: green; }') + })); + + jsExt.end(new Vinyl({ + path: 'test/b.scss', + contents: Buffer.from('.p { color: red; }') + })); +}); + +test.cb('ext-transform leaves css files untouched files when css-module is not selected', t => { + const jsExt = extTransform({}, ['']); + const files = []; + + jsExt.pipe(new Writable({ + objectMode: true, + write(file, enc, cb) { + files.push(file); + cb(); + } + })); + + jsExt.on('end', () => { + t.is(files.length, 2); + t.is(files[0].path.replace(/\\/g, '/'), 'test/a.css'); + t.is(files[0].contents.toString(), '.p { color: green; }'); + t.is(files[1].path.replace(/\\/g, '/'), 'test/b.scss'); + t.is(files[1].contents.toString(), '.p { color: red; }'); + t.end(); + }) + + jsExt.write(new Vinyl({ + path: 'test/a.css', + contents: Buffer.from('.p { color: green; }') + })); + + jsExt.end(new Vinyl({ + path: 'test/b.scss', + contents: Buffer.from('.p { color: red; }') + })); +}); \ No newline at end of file diff --git a/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin b/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin index 9e747ef..ff58ddf 100644 --- a/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin +++ b/app-min/e2e__if_playwright/app.spec.ext__if_not_plugin @@ -1,9 +1,4 @@ -// @if typescript import { test, expect } from '@playwright/test'; -// @endif -// @if babel -const { test, expect } = require('@playwright/test'); -// @endif test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9000'); diff --git a/app-min/test__if_not_no-unit-tests/my-app.spec.ext b/app-min/test__if_not_no-unit-tests/my-app.spec.ext index 60350f5..bc8ccfc 100644 --- a/app-min/test__if_not_no-unit-tests/my-app.spec.ext +++ b/app-min/test__if_not_no-unit-tests/my-app.spec.ext @@ -1,6 +1,9 @@ // @if mocha import { expect } from 'chai'; // @endif +// @if vitest +import { describe, it, expect } from 'vitest'; +// @endif // @if shadow-dom import { CustomElement } from 'aurelia'; // @endif @@ -25,7 +28,7 @@ describe('my-app', () => { // @if !shadow-dom const text = node.textContent; // @endif - // @if jasmine || jest + // @if jasmine || jest || vitest expect(text.trim()).toBe('Hello World!'); // @endif // @if mocha diff --git a/before.js b/before.js index 0abeb26..47b734c 100644 --- a/before.js +++ b/before.js @@ -1,13 +1,18 @@ // Use "before" task to ask user to select a preset (to skip questionnaire). const PRESETS = { - 'default-esnext': ['app', 'webpack', 'babel', 'jest'], - 'default-typescript': ['app', 'webpack', 'typescript', 'jest'], + 'default-esnext': ['app', 'vite', 'babel', 'vitest'], + 'default-typescript': ['app', 'vite', 'typescript', 'vitest'], + // TODO: move plugin to vite+vitest + // FIXME: vite compiles plugin with separate css dist file, and removed + // import('./style.css') from js code, need to: + // 1. hook up a css loader in runtime for normal css and css-module. + // 2. hook up a text loader in runtime for shadow-dom css. 'default-esnext-plugin': ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'], 'default-typescript-plugin': ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'], }; -const REQUIRE_NODEJS_VESION = [14, 15, 0]; +const REQUIRE_NODEJS_VESION = [18, 0, 0]; function isNodejsOutdated() { const version = process.version.slice(1).split('.'); diff --git a/common/package.json b/common/package.json index 7e3dca7..246a4d4 100644 --- a/common/package.json +++ b/common/package.json @@ -5,6 +5,8 @@ // @endif // @if plugin "description": "An Aurelia 2 plugin.", + // TODO: turn on after moved plugin to vite steup + // "type": "module", "main": "dist/index.js", "files": [ "dist" diff --git a/common/src/resource.d.ts__if_typescript b/common/src/resource.d.ts__if_typescript index ef44a5d..d3ef093 100644 --- a/common/src/resource.d.ts__if_typescript +++ b/common/src/resource.d.ts__if_typescript @@ -11,18 +11,18 @@ declare module '*.html' { } // @if css-module -declare module '*.css' { +declare module '*.module.css' { const value: Record; export default value; } // @if less -declare module '*.less' { +declare module '*.module.less' { const value: Record; export default value; } // @endif // @if sass -declare module '*.scss' { +declare module '*.module.scss' { const value: Record; export default value; } diff --git a/dumber/gulpfile.js b/dumber/gulpfile.js index c9f93e3..3e80400 100644 --- a/dumber/gulpfile.js +++ b/dumber/gulpfile.js @@ -143,10 +143,7 @@ function buildHtml(src) { // standard DOM APIs in "closed" mode. .pipe(au2({ defaultShadowOptions: { mode: 'open' }, hmr: false })); // @endif - // @if css-module - .pipe(au2({ useCSSModule: true, hmr: false })); - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom .pipe(au2({ hmr: false })); // @endif } @@ -177,7 +174,8 @@ function buildCss(src) { // improve compatibility on svg. postcssUrl({ url: 'inline', encodeType: 'base64' }) ]))/* @if css-module */ - .pipe(cssModule())/* @endif */; + // Use .module.css naming convention + .pipe(gulpif(f => f.basename.endsWith('.module.css'), cssModule()))/* @endif */; } function build() { diff --git a/e2e-test.js b/e2e-test.js index 2f596e1..084ce37 100644 --- a/e2e-test.js +++ b/e2e-test.js @@ -5,11 +5,9 @@ // Have to run "npm run test:e2e" manually before a release. const spawn = require('cross-spawn'); -const os = require('os'); const fs = require('fs'); const path = require('path'); const test = require('ava'); -const puppeteer = require('puppeteer'); const kill = require('tree-kill'); const {possibleFeatureSelections} = require('makes'); const questions = require('./questions'); @@ -24,7 +22,7 @@ const allSkeletons = possibleFeatureSelections(questions); const isWin32 = process.platform === 'win32'; -const folder = path.join(os.tmpdir(), 'test-skeletons'); +const folder = path.join(__dirname, 'test-skeletons'); console.log('-- cleanup ' + folder); fs.rmSync(folder, {recursive: true, force: true}); fs.mkdirSync(folder); @@ -40,7 +38,7 @@ function killProc(proc) { kill(proc.pid); } -function run(command, dataCB, errorCB) { +function run(command, cwd, dataCB, errorCB) { const [cmd, ...args] = command.split(' '); return new Promise((resolve, reject) => { const env = Object.create(process.env); @@ -49,7 +47,7 @@ function run(command, dataCB, errorCB) { // need to reset NODE_ENV back to development because this whole // test is running in NODE_ENV=test which will affect gulp build env.NODE_ENV = 'development'; - const proc = spawn(cmd, args, {env}); + const proc = spawn(cmd, args, {env, cwd}); proc.on('exit', async (code, signal) => { await delay(1); if (code && signal !== 'SIGTERM' && !win32Killed.has(proc.pid)) { @@ -85,15 +83,6 @@ function run(command, dataCB, errorCB) { }); } -async function takeScreenshot(url, filePath) { - const browser = await puppeteer.launch(); - const page = await browser.newPage(); - await page.goto(url); - await new Promise(r => setTimeout(r, 6000)); - await page.screenshot({path: filePath}); - await browser.close(); -} - const targetFeatures = (process.env.TARGET_FEATURES || '').toLowerCase().split(',').filter(p => p); if (!targetFeatures.includes('playwright')) { targetFeatures.push('playwright'); @@ -111,6 +100,7 @@ if (targetFeatures.length) { function getServerRegex(features) { if (features.includes('webpack')) return /Loopback: (\S+)/; if (features.includes('parcel')) return /Server running at (\S+)/; + if (features.includes('vite')) return /(http:\/\/\S+\/)/; return /Dev server is started at: (\S+)/; } @@ -126,26 +116,24 @@ skeletons.forEach((features, i) => { test.serial(title, async t => { console.log(title); - process.chdir(folder); const makeCmd = `npx makes ${__dirname} ${appName} -s ${features.join(',')}`; console.log('-- ' + makeCmd); - await run(makeCmd); + await run(makeCmd, folder); t.pass('made skeleton'); - process.chdir(appFolder); console.log('-- npm i'); - await run('npm i'); + await run('npm i', appFolder); t.pass('installed deps'); if (!features.includes('no-unit-tests')) { console.log('-- npm test'); - await run('npm test'); + await run('npm test', appFolder); t.pass('finished unit tests'); } console.log('-- npm run build'); - await run('npm run build', null, + await run('npm run build', appFolder, null, (data, kill) => { // Skip parcel warnings. if (features.includes('parcel')) return; @@ -164,32 +152,21 @@ skeletons.forEach((features, i) => { if (!m) return; const url = m[1]; t.pass(m[0]); - - try { - if (!process.env.GITHUB_ACTIONS) { - console.log('-- take screenshot'); - await takeScreenshot(url, path.join(folder, appName + '.png')); - } - kill(); - } catch (e) { - t.fail(e.message); - kill(); - } + kill(); }; // Webpack5 now prints Loopback: http://localhost:5000 in stderr! - await run('npm start', runE2e, runE2e); + await run('npm start', appFolder, runE2e, runE2e); if (features.includes('playwright')) { console.log('-- npx playwright test --project chromium'); - await run('npx playwright install --with-deps'); - await run('npx playwright test --project chromium'); + await run('npx playwright install --with-deps', appFolder); + await run('npx playwright test --project chromium', appFolder); } await delay(1); console.log('-- remove folder ' + appName); - process.chdir(folder); await fs.promises.rm(appFolder, {recursive: true}); }); }); diff --git a/jest/package.json b/jest/package.json index e98647a..26bb496 100644 --- a/jest/package.json +++ b/jest/package.json @@ -25,10 +25,7 @@ // @if shadow-dom "\\.(js|html)$": [ "@aurelia/babel-jest", { defaultShadowOptions: { mode: 'open' } } ] // @endif - // @if css-module - "\\.(js|html)$": [ "@aurelia/babel-jest", { useCSSModule: true } ] - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom "\\.(js|html)$": "@aurelia/babel-jest", // @endif // @endif @@ -36,10 +33,7 @@ // @if shadow-dom "\\.(ts|html)$": [ "@aurelia/ts-jest", { defaultShadowOptions: { mode: 'open' } } ] // @endif - // @if css-module - "\\.(ts|html)$": [ "@aurelia/ts-jest", { useCSSModule: true } ] - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom "\\.(ts|html)$": "@aurelia/ts-jest", // @endif // @endif diff --git a/package.json b/package.json index 35640c7..abe82d4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "glob": "^10.3.1", "makes": "^3.2.0", "npm-check-updates": "^16.10.13", - "puppeteer": "^20.7.3", "semver": "^7.5.3", "standard-changelog": "^3.0.0", "tree-kill": "^1.2.2", diff --git a/parcel/README.md b/parcel/README.md index a43a97c..9eb237b 100644 --- a/parcel/README.md +++ b/parcel/README.md @@ -4,5 +4,5 @@ By Parcel2 conventions, the `index.html` is in `src/` folder. ## Aurelia 2 config -To control the behaviour of ShadownDOM and CSS-Module setup in Aurelia 2, create a section `"aurelia"` in the `package.json` file. +To control the behaviour of ShadownDOM in Aurelia 2, create a section `"aurelia"` in the `package.json` file. https://www.npmjs.com/package/@aurelia/parcel-transformer diff --git a/parcel/package.json b/parcel/package.json index c26d588..5486b68 100644 --- a/parcel/package.json +++ b/parcel/package.json @@ -45,14 +45,7 @@ "hmr": false }, // @endif - // @if css-module - "aurelia": { - "useCSSModule": true, - "hmr": false - }, - "@parcel/transformer-css": { "cssModules": true }, - // @endif - // @if !shadow-dom && !css-module + // @if !shadow-dom "aurelia": { "hmr": false }, diff --git a/playwright/playwright.config.ext b/playwright/playwright.config.mjs similarity index 86% rename from playwright/playwright.config.ext rename to playwright/playwright.config.mjs index 2edccd3..26d7224 100644 --- a/playwright/playwright.config.ext +++ b/playwright/playwright.config.mjs @@ -1,11 +1,4 @@ -// @if typescript -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; -// @endif -// @if babel -// @ts-check -const { devices } = require('@playwright/test'); -// @endif +import { defineConfig, devices } from '@playwright/test'; /** * Read environment variables from file. @@ -16,7 +9,7 @@ const { devices } = require('@playwright/test'); /** * See https://playwright.dev/docs/test-configuration. */ -const config/* @if typescript */: PlaywrightTestConfig/* @endif */ = { +export default defineConfig({ testDir: './e2e', /* Maximum time one test can run for. */ timeout: 30 * 1000, @@ -108,11 +101,4 @@ const config/* @if typescript */: PlaywrightTestConfig/* @endif */ = { command: 'npm start', port: 9000, }, -}; - -// @if typescript -export default config; -// @endif -// @if babel -module.exports = config; -// @endif +}); diff --git a/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext b/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext index 50debb7..4740cec 100644 --- a/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext +++ b/plugin-min/test__if_not_no-unit-tests/hello-world.spec.ext @@ -1,6 +1,9 @@ // @if mocha import { expect } from 'chai'; // @endif +// @if vitest +import { describe, it, expect } from 'vitest'; +// @endif // @if shadow-dom import { CustomElement } from 'aurelia'; // @endif @@ -25,7 +28,7 @@ describe('hello-world', () => { // @if !shadow-dom const text = node.textContent; // @endif - // @if jasmine || jest + // @if jasmine || jest || vitest expect(text.trim()).toBe('Hello World! foo'); // @endif // @if mocha diff --git a/questions.js b/questions.js index a26882e..a470859 100644 --- a/questions.js +++ b/questions.js @@ -16,6 +16,7 @@ module.exports = [ { message: 'Which bundler would you like to use?', choices: [ + {if: 'app', value: 'vite', title: 'Vite', hint: 'Next Generation Frontend Tooling.'}, {value: 'webpack', title: 'Webpack', hint: 'A powerful and popular bundler for modern JavaScript apps.'}, {if: 'app', value: 'dumber', title: 'Dumber', hint: 'A dumb JavasScript bundler, dumber than you and me. The successor of Aurelia CLI built-in bundler.'}, {if: 'app', value: 'parcel', title: 'Parcel', hint: 'Blazing fast, zero configuration web application bundler.'}, @@ -34,7 +35,7 @@ module.exports = [ {title: 'No'}, {if: 'app', value: 'shadow-dom', title: 'Use Shadow DOM', hint: 'Shadow DOM in open mode, shadowRoot is accessible through DOM API.'}, {if: 'plugin', value: 'shadow-dom', title: 'Use Shadow DOM (Recommended for plugin project)', hint: 'Shadow DOM in open mode, shadowRoot is accessible through DOM API.'}, - {value: 'css-module', title: 'Use CSS Module', hint: 'CSS Module is an alternative way to locally scope CSS class names.'}, + {value: 'css-module', title: 'Use CSS Module', hint: 'CSS Module is an alternative way to locally scope CSS class names. We use .module.css/less/scss file name convention.'}, ] }, { @@ -49,9 +50,10 @@ module.exports = [ message: 'What unit testing framework to use?', choices: [ {value: 'no-unit-tests', title: 'None', hint: 'No unit testing'}, - {value: 'jest', title: 'Jest', hint: 'Runs in Node.js, simulates browser by default, with a focus on simplicity.'}, - {value: 'jasmine', title: 'Jasmine', hint: 'Runs in browser, a behavior-driven testing framework.'}, - {value: 'mocha', title: 'Mocha + Chai', hint: 'Runs in browser, a feature-rich JavaScript test framework for node and browsers.'} + {if: '!vite', value: 'jest', title: 'Jest', hint: 'Runs in Node.js, simulates browser by default, with a focus on simplicity.'}, + {if: '!vite', value: 'jasmine', title: 'Jasmine', hint: 'Runs in browser, a behavior-driven testing framework.'}, + {if: '!vite', value: 'mocha', title: 'Mocha + Chai', hint: 'Runs in browser, a feature-rich JavaScript test framework for node and browsers.'}, + {if: 'vite', value: 'vitest', title:'Vitest', hint: 'A Vite-native testing framework.'} ] }, { diff --git a/transforms.js b/transforms.js index 700cb36..2eff04f 100644 --- a/transforms.js +++ b/transforms.js @@ -8,6 +8,10 @@ exports.append = function(properties, features) { if (file.extname === '.ext') { // change .ext to .ts or .js file file.extname = features.includes('typescript') ? '.ts' : '.js'; + } else if (features.includes('css-module')) { + if (['.css', '.less', '.scss'].includes(file.extname)) { + file.extname = `.module${file.extname}`; + } } } cb(null, file); diff --git a/typescript/package.json b/typescript/package.json index 95e9b5d..56c29cc 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,7 +1,8 @@ { "devDependencies": { "@types/node": "^20.12.3", - "typescript": "^5.4.3", + // FIXME: typescript v5.5 has issue with our decorator typing + "typescript": "~5.4.5", "tslib": "^2.6.2", "@typescript-eslint/eslint-plugin": "^7.5.0", "@typescript-eslint/parser": "^7.5.0" diff --git a/vite/index.html b/vite/index.html new file mode 100644 index 0000000..002212d --- /dev/null +++ b/vite/index.html @@ -0,0 +1,22 @@ + + + + + + Aurelia + + + + + + + + + + + + + + + + diff --git a/vite/package.json b/vite/package.json new file mode 100644 index 0000000..bb8eca4 --- /dev/null +++ b/vite/package.json @@ -0,0 +1,31 @@ +{ + "type": "module", + "devDependencies": { + "@aurelia/vite-plugin": /* @if latest */"latest"/* @endif *//* @if dev */"dev"/* @endif */, + "vite": "^5.2.12", + "vite-plugin-node-polyfills": "^0.22.0", + // @if babel + "vite-plugin-babel": "^1.2.0", + // @endif + // @if typescript && plugin + "vite-plugin-dts": "^3.9.1", + // @endif + // @if vitest + "vitest": "^1.6.0", + "jsdom": "^24.1.0", + // @endif + // @if less + "less": "^4.2.0", + // @endif + // @if sass + "sass": "^1.77.3", + // @endif + }, + "scripts": { + "start": "vite", + "build": "vite build", + // @if vitest + "test": "vitest", + // @endif + } +} diff --git a/vite/tsconfig.vitest.json__if_vitest_and_typescript b/vite/tsconfig.vitest.json__if_vitest_and_typescript new file mode 100644 index 0000000..e0a57fe --- /dev/null +++ b/vite/tsconfig.vitest.json__if_vitest_and_typescript @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + "types": ["node", "jsdom"] + } +} \ No newline at end of file diff --git a/vite/vite.config.ext b/vite/vite.config.ext new file mode 100644 index 0000000..8e56609 --- /dev/null +++ b/vite/vite.config.ext @@ -0,0 +1,58 @@ +import { defineConfig } from 'vite'; +import { nodePolyfills } from 'vite-plugin-node-polyfills' +import aurelia from '@aurelia/vite-plugin'; +// @if babel +import babel from 'vite-plugin-babel'; +// @endif +// @if plugin +import { resolve } from 'path'; +// @if typescript +import dts from 'vite-plugin-dts'; +// @endif +// @endif + +export default defineConfig({ + server: { + open: !process.env.CI, + port: 9000, + }, + esbuild: { + target: 'es2022' + }, + // @if plugin + build: { + lib: { + entry: resolve(__dirname, 'src/index./* @if babel */js/* @endif *//* @if typescript */ts/* @endif */'), + // Generate ESM dist file only. + formats: ['es'], + fileName: 'index', + }, + rollupOptions: { + // Add all 3rd party dependencies here to avoid bundling. + external: [/@aurelia\/\w+/, 'aurelia'], + }, + }, + // @endif + plugins: [ + aurelia({ + useDev: true, + // @if plugin + include: '{src,dev-app}/**/*.{ts,js,html}', + // @endif + // @if shadow-dom + // The other possible Shadow DOM mode is 'closed'. + // If you turn on "closed" mode, there will be difficulty to perform e2e + // tests (such as Playwright). Because shadowRoot is not accessible through + // standard DOM APIs in "closed" mode. + defaultShadowOptions: { mode: 'open' }, + // @endif + }), + // @if babel + babel(), + // @endif + nodePolyfills(), + // @if typescript && plugin + dts(), + // @endif + ], +}); diff --git a/vite/vitest.config.ext__if_vitest b/vite/vitest.config.ext__if_vitest new file mode 100644 index 0000000..1261649 --- /dev/null +++ b/vite/vitest.config.ext__if_vitest @@ -0,0 +1,17 @@ +import { fileURLToPath } from "node:url"; +import { mergeConfig, defineConfig/* @if playwright */, configDefaults/* @endif */ } from "vitest/config"; +import viteConfig from "./vite.config"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: "jsdom", + watch: false, + // @if playwright + exclude: [...configDefaults.exclude, "e2e/*"], + // @endif + root: fileURLToPath(new URL("./", import.meta.url)), + }, + }), +); \ No newline at end of file diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js index 216027f..eac1478 100644 --- a/webpack/webpack.config.js +++ b/webpack/webpack.config.js @@ -13,20 +13,6 @@ const WebpackShellPluginNext = require('webpack-shell-plugin-next') const nodeExternals = require('webpack-node-externals'); // @endif -// @if !css-module -const cssLoader = 'css-loader'; -// @endif -// @if css-module -const cssLoader = { - loader: 'css-loader', - options: { - modules: true, - // https://github.com/webpack-contrib/css-loader#importloaders - importLoaders: /* @if css */1/* @endif *//* @if !css */2/* @endif */ - } -}; -// @endif - // @if sass const sassLoader = { loader: 'sass-loader', @@ -113,7 +99,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a }, resolve: { extensions: [/* @if typescript */'.ts', /* @endif */'.js'], - modules: [path.resolve(__dirname, 'src'),/* @if !production */ path.resolve(__dirname, 'dev-app'),/* @endif */ 'node_modules'], + modules: [path.resolve(__dirname, 'src'),/* @if plugin */ path.resolve(__dirname, 'dev-app'),/* @endif */ 'node_modules'], alias: production ? { // add your production aliases here } : { @@ -131,12 +117,12 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset' }, { test: /\.(woff|woff2|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, type: 'asset' }, // @if !shadow-dom - { test: /\.css$/i, use: [ 'style-loader', cssLoader, postcssLoader ] }, + { test: /\.css$/i, use: [ 'style-loader', 'css-loader', postcssLoader ] }, // @if less - { test: /\.less$/i, use: [ 'style-loader', cssLoader, postcssLoader, 'less-loader' ] }, + { test: /\.less$/i, use: [ 'style-loader', 'css-loader', postcssLoader, 'less-loader' ] }, // @endif // @if sass - { test: /\.scss$/i, use: [ 'style-loader', cssLoader, postcssLoader, sassLoader ] }, + { test: /\.scss$/i, use: [ 'style-loader', 'css-loader', postcssLoader, sassLoader ] }, // @endif // @endif // @if shadow-dom @@ -145,7 +131,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in src/main.js, it's not loaded by style-loader. // It's for shared styles for shadow-dom only. issuer: /[/\\]src[/\\]main\.(js|ts)$/, - use: [ cssLoader, postcssLoader ] + use: [ 'css-loader', postcssLoader ] }, // @if less { @@ -153,7 +139,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in src/main.js, it's not loaded by style-loader. // It's for shared styles for shadow-dom only. issuer: /[/\\]src[/\\]main\.(js|ts)$/, - use: [ cssLoader, postcssLoader, 'less-loader' ] + use: [ 'css-loader', postcssLoader, 'less-loader' ] }, // @endif // @if sass @@ -162,7 +148,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in src/main.js, it's not loaded by style-loader. // It's for shared styles for shadow-dom only. issuer: /[/\\]src[/\\]main\.(js|ts)$/, - use: [ cssLoader, postcssLoader, sassLoader ] + use: [ 'css-loader', postcssLoader, sassLoader ] }, // @endif { @@ -170,7 +156,7 @@ module.exports = function(env, { /* @if jasmine || mocha*/runTest, /* @endif */a // For style loaded in other js/ts files, it's loaded by style-loader. // They are directly injected to HTML head. issuer: /(?