diff --git a/.gitignore b/.gitignore
index c5c2d9ded..c1f742825 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
/coverage/
/demos/*/package-lock.json
/demos/*/node_modules/
+/demos/rollup/dist/
/docs/.jekyll-cache/
/docs/_site/
/docs/Gemfile.lock
diff --git a/demos/rollup/Gruntfile.js b/demos/rollup/Gruntfile.js
new file mode 100644
index 000000000..afbd05d59
--- /dev/null
+++ b/demos/rollup/Gruntfile.js
@@ -0,0 +1,40 @@
+/* eslint-env node */
+module.exports = function (grunt) {
+ grunt.loadNpmTasks('grunt-contrib-connect');
+ grunt.loadNpmTasks('grunt-contrib-qunit');
+
+ grunt.initConfig({
+ connect: {
+ all: {
+ options: {
+ useAvailablePort: true,
+ base: '.'
+ }
+ }
+ },
+ qunit: {
+ options: {
+ },
+ all: ['test-*.html']
+ }
+ });
+
+ grunt.event.once('connect.all.listening', function(host, port) {
+ grunt.config('qunit.options.httpBase', `http://localhost:${port}`);
+ // console.log(grunt.config()); // DEBUG
+ });
+
+
+ let results = [];
+ grunt.event.on('qunit.on.testEnd', function (test) {
+ results.push(
+ `>> ${test.status} test "${test.fullName.join(' > ')}"`
+ );
+ });
+ grunt.event.on('qunit.on.runEnd', function () {
+ grunt.log.writeln(results.join('\n'));
+ results = [];
+ });
+
+ grunt.registerTask('test', ['connect', 'qunit']);
+};
diff --git a/demos/rollup/build.mjs b/demos/rollup/build.mjs
new file mode 100644
index 000000000..9c67e94a6
--- /dev/null
+++ b/demos/rollup/build.mjs
@@ -0,0 +1,103 @@
+import fs from 'node:fs';
+
+import { rollup } from 'rollup';
+import resolve from '@rollup/plugin-node-resolve';
+import commonjs from '@rollup/plugin-commonjs';
+
+const plugins = [ commonjs(), resolve() ];
+
+const inputs = [
+ {
+ input:'test/test-import-default-from-cjs.js',
+ plugins
+ },
+ {
+ input: 'test/test-import-from-cjs.js',
+ plugins
+ },
+ {
+ input: 'test/test-mixed.js',
+ plugins
+ },
+ {
+ input: 'test/test-require-from-cjs.js',
+ plugins,
+ // Ignore "output.name" warning for test-require-from-cjs.iife.js
+ onwarn: () => {}
+ }
+];
+const outputs = [
+ {
+ dir: 'dist/',
+ entryFileNames: '[name].[format].js',
+ format: 'es'
+ },
+ {
+ dir: 'dist/',
+ entryFileNames: '[name].[format].js',
+ format: 'cjs'
+ },
+ {
+ dir: 'dist/',
+ entryFileNames: '[name].[format].js',
+ format: 'iife'
+ },
+ {
+ dir: 'dist/',
+ entryFileNames: '[name].[format].js',
+ format: 'umd',
+ name: 'UNUSED'
+ }
+];
+const htmlTemplate = `
+
+
+
+{{title}}
+
+{{scriptTag}}
+
+
+
+
+
+`;
+const scriptTag = (src) => {
+ if (src.endsWith('.es.js')) {
+ return ;
+ } else {
+ }
+};
+
+(async function main() {
+ const entries = fs.readdirSync('.');
+ for (const entry of entries) {
+ if (entry.match(/^test-.*\.html$/)) {
+ fs.rmSync(entry);
+ }
+ }
+ for (const input of inputs) {
+ const bundle = await rollup(input);
+
+ for (const outputOptions of outputs) {
+ const { output } = await bundle.write(outputOptions);
+ const fileName = output[0].fileName;
+ console.log('... built ' + fileName );
+
+ if ( outputOptions.format !== 'cjs' ) {
+ const html = htmlTemplate
+ .replace('{{title}}', fileName)
+ .replace('{{scriptTag}}', (
+ fileName.endsWith('.es.js')
+ ? ``
+ : ``
+ ));
+
+ fs.writeFileSync(
+ fileName.replace('.js', '') + '.html',
+ html
+ );
+ }
+ }
+ }
+}());
diff --git a/demos/rollup/favicon.ico b/demos/rollup/favicon.ico
new file mode 100644
index 000000000..e69de29bb
diff --git a/demos/rollup/package.json b/demos/rollup/package.json
new file mode 100644
index 000000000..710d7c9b2
--- /dev/null
+++ b/demos/rollup/package.json
@@ -0,0 +1,16 @@
+{
+ "private": true,
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^26.0.1",
+ "@rollup/plugin-node-resolve": "^15.2.3",
+ "grunt": "1.6.1",
+ "grunt-contrib-connect": "^5.0.0",
+ "grunt-contrib-qunit": "10.1.1",
+ "qunit": "file:../..",
+ "rollup": "^4.18.0"
+ },
+ "scripts": {
+ "build": "node build.mjs",
+ "test": "grunt test"
+ }
+}
diff --git a/demos/rollup/test-import-default-from-cjs.es.html b/demos/rollup/test-import-default-from-cjs.es.html
new file mode 100644
index 000000000..b34e8a9eb
--- /dev/null
+++ b/demos/rollup/test-import-default-from-cjs.es.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-import-default-from-cjs.es.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-import-default-from-cjs.iife.html b/demos/rollup/test-import-default-from-cjs.iife.html
new file mode 100644
index 000000000..ae0700670
--- /dev/null
+++ b/demos/rollup/test-import-default-from-cjs.iife.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-import-default-from-cjs.iife.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-import-default-from-cjs.umd.html b/demos/rollup/test-import-default-from-cjs.umd.html
new file mode 100644
index 000000000..04eb36fe8
--- /dev/null
+++ b/demos/rollup/test-import-default-from-cjs.umd.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-import-default-from-cjs.umd.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-import-from-cjs.es.html b/demos/rollup/test-import-from-cjs.es.html
new file mode 100644
index 000000000..4ce33a9d1
--- /dev/null
+++ b/demos/rollup/test-import-from-cjs.es.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-import-from-cjs.es.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-import-from-cjs.iife.html b/demos/rollup/test-import-from-cjs.iife.html
new file mode 100644
index 000000000..e70b61347
--- /dev/null
+++ b/demos/rollup/test-import-from-cjs.iife.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-import-from-cjs.iife.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-import-from-cjs.umd.html b/demos/rollup/test-import-from-cjs.umd.html
new file mode 100644
index 000000000..04712aabf
--- /dev/null
+++ b/demos/rollup/test-import-from-cjs.umd.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-import-from-cjs.umd.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-mixed.es.html b/demos/rollup/test-mixed.es.html
new file mode 100644
index 000000000..64c3c827a
--- /dev/null
+++ b/demos/rollup/test-mixed.es.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-mixed.es.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-mixed.iife.html b/demos/rollup/test-mixed.iife.html
new file mode 100644
index 000000000..bbea520a0
--- /dev/null
+++ b/demos/rollup/test-mixed.iife.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-mixed.iife.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-mixed.umd.html b/demos/rollup/test-mixed.umd.html
new file mode 100644
index 000000000..92618233d
--- /dev/null
+++ b/demos/rollup/test-mixed.umd.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-mixed.umd.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-require-from-cjs.es.html b/demos/rollup/test-require-from-cjs.es.html
new file mode 100644
index 000000000..49c39dbb8
--- /dev/null
+++ b/demos/rollup/test-require-from-cjs.es.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-require-from-cjs.es.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-require-from-cjs.iife.html b/demos/rollup/test-require-from-cjs.iife.html
new file mode 100644
index 000000000..e2e73d040
--- /dev/null
+++ b/demos/rollup/test-require-from-cjs.iife.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-require-from-cjs.iife.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test-require-from-cjs.umd.html b/demos/rollup/test-require-from-cjs.umd.html
new file mode 100644
index 000000000..2c2cec72d
--- /dev/null
+++ b/demos/rollup/test-require-from-cjs.umd.html
@@ -0,0 +1,12 @@
+
+
+
+
+test-require-from-cjs.umd.js
+
+
+
+
+
+
+
diff --git a/demos/rollup/test/package.json b/demos/rollup/test/package.json
new file mode 100644
index 000000000..3dbc1ca59
--- /dev/null
+++ b/demos/rollup/test/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "module"
+}
diff --git a/demos/rollup/test/src.js b/demos/rollup/test/src.js
new file mode 100644
index 000000000..3b9c0b421
--- /dev/null
+++ b/demos/rollup/test/src.js
@@ -0,0 +1,3 @@
+export function add (a, b) {
+ return a + b;
+}
diff --git a/demos/rollup/test/test-import-default-from-cjs.js b/demos/rollup/test/test-import-default-from-cjs.js
new file mode 100644
index 000000000..36e0e0b07
--- /dev/null
+++ b/demos/rollup/test/test-import-default-from-cjs.js
@@ -0,0 +1,8 @@
+import QUnit from 'qunit';
+import { add } from './src.js';
+
+QUnit.module('import default from qunit.cjs', function () {
+ QUnit.test('example', function (assert) {
+ assert.equal(add(2, 3), 5);
+ });
+});
diff --git a/demos/rollup/test/test-import-from-cjs.js b/demos/rollup/test/test-import-from-cjs.js
new file mode 100644
index 000000000..fc3cd7db3
--- /dev/null
+++ b/demos/rollup/test/test-import-from-cjs.js
@@ -0,0 +1,8 @@
+import { module, test } from 'qunit';
+import { add } from './src.js';
+
+module('import { module,test } from qunit.cjs', function () {
+ test('example', function (assert) {
+ assert.equal(add(2, 3), 5);
+ });
+});
diff --git a/demos/rollup/test/test-mixed.js b/demos/rollup/test/test-mixed.js
new file mode 100644
index 000000000..e7c5a8bb1
--- /dev/null
+++ b/demos/rollup/test/test-mixed.js
@@ -0,0 +1,3 @@
+import './test-import-default-from-cjs.js';
+import './test-import-from-cjs.js';
+import './test-require-from-cjs.js';
diff --git a/demos/rollup/test/test-require-from-cjs.js b/demos/rollup/test/test-require-from-cjs.js
new file mode 100644
index 000000000..cc66fb9a7
--- /dev/null
+++ b/demos/rollup/test/test-require-from-cjs.js
@@ -0,0 +1,8 @@
+const QUnit = require('qunit');
+const { add } = require('./src.js');
+
+QUnit.module('require from qunit.cjs', function () {
+ QUnit.test('example', function (assert) {
+ assert.equal(add(2, 3), 5);
+ });
+});