diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 94% rename from .eslintrc.js rename to .eslintrc.cjs index e798383f20..c299bfbdd1 100644 --- a/.eslintrc.js +++ b/.eslintrc.cjs @@ -1,5 +1,6 @@ const pluginPresets = { 'array-func': `all`, + import: `recommended`, jsdoc: `recommended`, markdown: `recommended`, nuxt: `recommended`, @@ -77,6 +78,14 @@ const enabledRuleParameters = { 'spaced-comment': [`always`], 'template-curly-spacing': [], + // eslint-plugin-import + 'import/extensions': [`ignorePackages`], + 'import/no-commonjs': [{ allowConditionalRequire: false }], + 'import/no-dynamic-require': [], + 'import/no-unresolved': [{ + ignore: [`^fs/promises$`], + }], + // eslint-plugin-jsdoc 'jsdoc/check-alignment': [], 'jsdoc/check-indentation': [], @@ -225,6 +234,7 @@ const warnRules = new Set([ const disabledRules = [ `no-console`, + `import/no-duplicates`, `jsdoc/newline-after-description`, `jsdoc/no-undefined-types`, `jsdoc/require-description`, @@ -241,7 +251,6 @@ const disabledRules = [ `unicorn/no-array-reduce`, `unicorn/no-useless-undefined`, `unicorn/prefer-node-protocol`, - `unicorn/prefer-module`, `unicorn/prefer-spread`, `vue/multiline-html-element-content-newline`, `vue/singleline-html-element-content-newline`, @@ -308,6 +317,16 @@ module.exports = { 'jsdoc/require-jsdoc': `off`, }, }, + { + files: [`**/*.cjs`, `server/**.js`], + parserOptions: { + sourceType: `script`, + }, + rules: { + 'import/no-commonjs': `off`, + 'unicorn/prefer-module': `off`, + }, + }, { files: [`**/*.vue`], }, diff --git a/cli/build-plugin-data.js b/cli/build-plugin-data.js index 89819f7381..c3cc99224e 100755 --- a/cli/build-plugin-data.js +++ b/cli/build-plugin-data.js @@ -1,13 +1,10 @@ #!/usr/bin/env node -const path = require(`path`); -const { - readdir, - stat, - writeFile, -} = require(`fs/promises`); -const chalk = require(`chalk`); -const importJson = require(`../lib/import-json.js`); +import path from 'path'; +import { fileURLToPath } from 'url'; +import { readdir, writeFile } from 'fs/promises'; +import chalk from 'chalk'; +import importJson from '../lib/import-json.js'; const plugins = { importPlugins: [], @@ -17,10 +14,10 @@ const plugins = { const allPreviousVersions = {}; -const pluginDirectory = path.join(__dirname, `../plugins/`); +const pluginDirectoryUrl = new URL(`../plugins/`, import.meta.url); (async () => { - const directoryEntries = await readdir(pluginDirectory, { withFileTypes: true }); + const directoryEntries = await readdir(pluginDirectoryUrl, { withFileTypes: true }); const pluginKeys = directoryEntries.filter(entry => entry.isDirectory()).map(entry => entry.name); for (const pluginKey of pluginKeys) { @@ -46,11 +43,11 @@ const pluginDirectory = path.join(__dirname, `../plugins/`); Object.keys(plugins.data).sort().map(key => [key, plugins.data[key]]), ); - const filename = path.join(pluginDirectory, `plugins.json`); + const filePath = fileURLToPath(new URL(`plugins.json`, pluginDirectoryUrl)); try { - await writeFile(filename, `${JSON.stringify(plugins, null, 2)}\n`, `utf8`); - console.log(chalk.green(`[Success]`), `Updated plugin data file`, filename); + await writeFile(filePath, `${JSON.stringify(plugins, null, 2)}\n`, `utf8`); + console.log(chalk.green(`[Success]`), `Updated plugin data file`, filePath); process.exit(0); } catch (error) { @@ -66,7 +63,7 @@ const pluginDirectory = path.join(__dirname, `../plugins/`); */ async function readPluginJson(pluginKey) { try { - const pluginJson = await importJson(`${pluginKey}/plugin.json`, pluginDirectory); + const pluginJson = await importJson(`${pluginKey}/plugin.json`, pluginDirectoryUrl); plugins.data[pluginKey].name = pluginJson.name; if (pluginJson.previousVersions) { @@ -90,20 +87,18 @@ async function readPluginJson(pluginKey) { * @param {String} pluginKey The plugin key. */ async function readPluginImport(pluginKey) { - const importPath = path.join(pluginDirectory, pluginKey, `import.js`); try { - await stat(importPath); - const importPlugin = require(importPath); + const importPlugin = await import(new URL(`${pluginKey}/import.js`, pluginDirectoryUrl)); plugins.importPlugins.push(pluginKey); plugins.data[pluginKey].importPluginVersion = importPlugin.version; } catch (error) { - if (error.code === `ENOENT`) { + if (error.code === `ERR_MODULE_NOT_FOUND`) { // ignore non-existing file return; } - console.error(error.message); + console.error(`Import plugin ${pluginKey} could not be parsed:`, error.message); process.exit(1); } } @@ -113,21 +108,19 @@ async function readPluginImport(pluginKey) { * @param {String} pluginKey The plugin key. */ async function readPluginExport(pluginKey) { - const exportPath = path.join(pluginDirectory, pluginKey, `export.js`); try { - await stat(exportPath); - const exportPlugin = require(exportPath); + const exportPlugin = await import(new URL(`${pluginKey}/export.js`, pluginDirectoryUrl)); plugins.exportPlugins.push(pluginKey); plugins.data[pluginKey].exportPluginVersion = exportPlugin.version; plugins.data[pluginKey].exportTests = []; } catch (error) { - if (error.code === `ENOENT`) { + if (error.code === `ERR_MODULE_NOT_FOUND`) { // ignore non-existing file return; } - console.error(error.message); + console.error(`Export plugin ${pluginKey} could not be parsed:`, error.message); process.exit(1); } } @@ -137,9 +130,8 @@ async function readPluginExport(pluginKey) { * @param {String} pluginKey The plugin key. */ async function readPluginExportTests(pluginKey) { - const exportTestsPath = path.join(pluginDirectory, pluginKey, `exportTests`); try { - const exportTestFiles = await readdir(exportTestsPath); + const exportTestFiles = await readdir(new URL(`${pluginKey}/exportTests/`, pluginDirectoryUrl)); for (const test of exportTestFiles) { const testKey = path.basename(test, path.extname(test)); plugins.data[pluginKey].exportTests.push(testKey); @@ -151,7 +143,7 @@ async function readPluginExportTests(pluginKey) { return; } - console.error(error.message); + console.error(`Export tests for plugin ${pluginKey} could not be read:`, error.message); process.exit(1); } } diff --git a/cli/build-register.js b/cli/build-register.js index 0c80b1b66e..893164ee02 100755 --- a/cli/build-register.js +++ b/cli/build-register.js @@ -1,20 +1,21 @@ #!/usr/bin/env node -const { readdir, writeFile } = require(`fs/promises`); -const path = require(`path`); -const chalk = require(`chalk`); +import { fileURLToPath } from 'url'; +import { readdir, writeFile } from 'fs/promises'; +import path from 'path'; +import chalk from 'chalk'; -const { Register } = require(`../lib/register.js`); -const importJson = require(`../lib/import-json.js`); +import { Register } from '../lib/register.js'; +import importJson from '../lib/import-json.js'; let register; let manufacturers; -const fixturesPath = path.join(__dirname, `../fixtures/`); +const fixturesPath = fileURLToPath(new URL(`../fixtures/`, import.meta.url)); (async () => { try { - manufacturers = await importJson(`../fixtures/manufacturers.json`, __dirname); + manufacturers = await importJson(`../fixtures/manufacturers.json`, import.meta.url); register = new Register(manufacturers); await addFixturesToRegister(); diff --git a/cli/build-test-fixtures.js b/cli/build-test-fixtures.js index 6c7a9a7172..fe1bf42fd8 100755 --- a/cli/build-test-fixtures.js +++ b/cli/build-test-fixtures.js @@ -5,16 +5,17 @@ * keeping the set as small as possible) and updates tests/test-fixtures.json and tests/test-fixtures.md. */ -const { readdir, writeFile } = require(`fs/promises`); -const path = require(`path`); -const chalk = require(`chalk`); +import { fileURLToPath } from 'url'; +import { readdir, writeFile } from 'fs/promises'; +import path from 'path'; +import chalk from 'chalk'; -const { fixtureFromRepository } = require(`../lib/model.js`); -const importJson = require(`../lib/import-json.js`); +import { fixtureFromRepository } from '../lib/model.js'; +import importJson from '../lib/import-json.js'; -const fixtureFeaturesDirectory = path.join(__dirname, `../lib/fixture-features`); -const jsonFile = path.join(__dirname, `../tests/test-fixtures.json`); -const markdownFile = path.join(__dirname, `../tests/test-fixtures.md`); +const fixtureFeaturesDirectoryUrl = new URL(`../lib/fixture-features/`, import.meta.url); +const jsonPath = fileURLToPath(new URL(`../tests/test-fixtures.json`, import.meta.url)); +const markdownPath = fileURLToPath(new URL(`../tests/test-fixtures.md`, import.meta.url)); /** * @typedef {Object} FixtureFeature @@ -33,7 +34,7 @@ const markdownFile = path.join(__dirname, `../tests/test-fixtures.md`); */ (async () => { - const register = await importJson(`../fixtures/register.json`, __dirname); + const register = await importJson(`../fixtures/register.json`, import.meta.url); const fixtureFeatures = await getFixtureFeatures(); const featuresUsed = Object.fromEntries(fixtureFeatures.map(feature => [feature.id, 0]));// check which features each fixture supports @@ -99,11 +100,11 @@ const markdownFile = path.join(__dirname, `../tests/test-fixtures.md`); } try { - await writeFile(jsonFile, `${JSON.stringify(fixtures, null, 2)}\n`, `utf8`); - console.log(chalk.green(`[Success]`), `Updated ${jsonFile}`); + await writeFile(jsonPath, `${JSON.stringify(fixtures, null, 2)}\n`, `utf8`); + console.log(chalk.green(`[Success]`), `Updated ${jsonPath}`); - await writeFile(markdownFile, await getMarkdownCode(fixtures, fixtureFeatures), `utf8`); - console.log(chalk.green(`[Success]`), `Updated ${markdownFile}`); + await writeFile(markdownPath, await getMarkdownCode(fixtures, fixtureFeatures), `utf8`); + console.log(chalk.green(`[Success]`), `Updated ${markdownPath}`); } catch (error) { console.error(chalk.red(`[Fail]`), `Could not write test fixtures file:`, error); @@ -117,18 +118,19 @@ const markdownFile = path.join(__dirname, `../tests/test-fixtures.md`); async function getFixtureFeatures() { const fixtureFeatures = []; - for (const featureFile of await readdir(fixtureFeaturesDirectory)) { - if (path.extname(featureFile) !== `.js`) { + for (const fileName of await readdir(fixtureFeaturesDirectoryUrl)) { + if (path.extname(fileName) !== `.js`) { continue; } // module exports array of fix features - const fixtureFeatureFile = require(path.join(fixtureFeaturesDirectory, featureFile)); + const fixtureFeatureFileUrl = new URL(fileName, fixtureFeaturesDirectoryUrl); + const { default: fixtureFeatureFile } = await import(fixtureFeatureFileUrl); for (const [index, fixtureFeature] of fixtureFeatureFile.entries()) { // default id if (!(`id` in fixtureFeature)) { - fixtureFeature.id = path.basename(featureFile, `.js`); + fixtureFeature.id = path.basename(fileName, `.js`); if (fixtureFeatureFile.length > 1) { fixtureFeature.id += `-${index}`; } @@ -155,7 +157,7 @@ async function getFixtureFeatures() { * @returns {Promise.} A Promise that resolves to the markdown code to be used in a markdown file. */ async function getMarkdownCode(fixtures, fixtureFeatures) { - const manufacturers = await importJson(`../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../fixtures/manufacturers.json`, import.meta.url); const mdLines = [ `# Test fixtures`, diff --git a/cli/debug-env-variables.js b/cli/debug-env-variables.js index 645a4035f3..582c1e22d8 100755 --- a/cli/debug-env-variables.js +++ b/cli/debug-env-variables.js @@ -1,6 +1,6 @@ #!/usr/bin/env node -const chalk = require(`chalk`); +import chalk from 'chalk'; const usedVariables = [ `ALLOW_SEARCH_INDEXING`, @@ -23,10 +23,12 @@ console.log(`Process environment variables:`); printVariables(); console.log(); -require(`../lib/load-env-file`); - -console.log(`Environment variables after reading .env:`); -printVariables(); +import(`../lib/load-env-file.js`).then(() => { + console.log(`Environment variables after reading .env:`); + printVariables(); +}).catch(error => { + throw error; +}); /** * Prints all used environment variables and their values / unset diff --git a/cli/diff-plugin-outputs.js b/cli/diff-plugin-outputs.js index cdb94b14b4..8e7c46384a 100755 --- a/cli/diff-plugin-outputs.js +++ b/cli/diff-plugin-outputs.js @@ -1,15 +1,14 @@ #!/usr/bin/env node -const path = require(`path`); -const minimist = require(`minimist`); -const chalk = require(`chalk`); +import minimist from 'minimist'; +import chalk from 'chalk'; -const diffPluginOutputs = require(`../lib/diff-plugin-outputs.js`); -const importJson = require(`../lib/import-json.js`); +import diffPluginOutputs from '../lib/diff-plugin-outputs.js'; +import importJson from '../lib/import-json.js'; (async () => { - const plugins = await importJson(`../plugins/plugins.json`, __dirname); - const testFixtures = (await importJson(`../tests/test-fixtures.json`, __dirname)).map( + const plugins = await importJson(`../plugins/plugins.json`, import.meta.url); + const testFixtures = (await importJson(`../tests/test-fixtures.json`, import.meta.url)).map( fixture => `${fixture.man}/${fixture.key}`, ); @@ -23,11 +22,13 @@ const importJson = require(`../lib/import-json.js`); cliArguments.testFix = cliArguments[`test-fix`]; cliArguments.fixtures = cliArguments._; + const scriptName = import.meta.url.split(`/`).slice(-2).join(`/`); + const helpMessage = [ `This script exports the given fixtures with the current version of the given plugin and diffs the results`, `against the files exported with the comparePlugin at the state of the given Git reference.`, `Fixtures have to be declared with the path to its file in the fixtures/ directory.`, - `Usage: node ${path.relative(process.cwd(), __filename)} -p [-c ] [-r ] [ -t | [] ]`, + `Usage: node ${scriptName} -p [-c ] [-r ] [ -t | [] ]`, `Options:`, ` --plugin, -p: Which plugin should be used to output fixtures. Allowed values:`, ` ${plugins.exportPlugins.join(`, `)}`, diff --git a/cli/export-fixture.js b/cli/export-fixture.js index bde5b4adf7..9edc2d7931 100755 --- a/cli/export-fixture.js +++ b/cli/export-fixture.js @@ -1,11 +1,12 @@ #!/usr/bin/env node -const { mkdir, writeFile } = require(`fs/promises`); -const path = require(`path`); -const minimist = require(`minimist`); -const chalk = require(`chalk`); +import { fileURLToPath } from 'url'; +import { mkdir, writeFile } from 'fs/promises'; +import path from 'path'; +import minimist from 'minimist'; +import chalk from 'chalk'; -const { fixtureFromRepository } = require(`../lib/model.js`); -const importJson = require(`../lib/import-json.js`); +import { fixtureFromRepository } from '../lib/model.js'; +import importJson from '../lib/import-json.js'; (async () => { try { @@ -19,7 +20,7 @@ const importJson = require(`../lib/import-json.js`); let fixtures; if (cliArguments.a) { - const register = await importJson(`../fixtures/register.json`, __dirname); + const register = await importJson(`../fixtures/register.json`, import.meta.url); fixtures = Object.keys(register.filesystem).filter( fixtureKey => !(`redirectTo` in register.filesystem[fixtureKey]) || register.filesystem[fixtureKey].reason === `SameAsDifferentBrand`, ).map(fixtureKey => fixtureKey.split(`/`)); @@ -36,13 +37,13 @@ const importJson = require(`../lib/import-json.js`); const outDirectory = cliArguments.o ? path.resolve(process.cwd(), cliArguments.o) : null; - const plugin = require(`../plugins/${cliArguments.plugin}/export.js`); + const plugin = await import(`../plugins/${cliArguments.plugin}/export.js`); const files = await plugin.exportFixtures( await Promise.all(fixtures.map( ([manufacturer, fixture]) => fixtureFromRepository(manufacturer, fixture), )), { - baseDirectory: path.join(__dirname, `..`), + baseDirectory: fileURLToPath(new URL(`../`, import.meta.url)), date: new Date(), }, ); @@ -96,7 +97,7 @@ async function checkCliArguments(cliArguments) { process.exit(1); } - const plugins = await importJson(`../plugins/plugins.json`, __dirname); + const plugins = await importJson(`../plugins/plugins.json`, import.meta.url); if (!plugins.exportPlugins.includes(cliArguments.plugin)) { console.error(chalk.red(`[Error]`), `Plugin '${cliArguments.plugin}' does not exist or does not support exporting.\n\navailable plugins:`, Object.keys(plugins.exportPlugins).join(`, `)); diff --git a/cli/import-fixture.js b/cli/import-fixture.js index 5e1d394b01..43266ee0df 100755 --- a/cli/import-fixture.js +++ b/cli/import-fixture.js @@ -1,12 +1,12 @@ #!/usr/bin/env node -const minimist = require(`minimist`); -const { readFile } = require(`fs/promises`); +import minimist from 'minimist'; +import { readFile } from 'fs/promises'; -const { checkFixture } = require(`../tests/fixture-valid.js`); -const fixtureJsonStringify = require(`../lib/fixture-json-stringify.js`); -const createPullRequest = require(`../lib/create-github-pr.js`); -const importJson = require(`../lib/import-json.js`); +import { checkFixture } from '../tests/fixture-valid.js'; +import fixtureJsonStringify from '../lib/fixture-json-stringify.js'; +import createPullRequest from '../lib/create-github-pr.js'; +import importJson from '../lib/import-json.js'; /** @typedef {import('../lib/types.js').FixtureCreateResult} FixtureCreateResult */ @@ -28,7 +28,7 @@ const importJson = require(`../lib/import-json.js`); try { const buffer = await readFile(filename); - const plugin = require(`../plugins/${cliArguments.plugin}/import.js`); + const plugin = await import(`../plugins/${cliArguments.plugin}/import.js`); const { manufacturers, fixtures, warnings } = await plugin.importFixtures(buffer, filename, cliArguments[`author-name`]); /** @type {FixtureCreateResult} */ @@ -74,7 +74,7 @@ const importJson = require(`../lib/import-json.js`); * @param {Object.} cliArguments Command line interface arguments parsed by minimist. */ async function checkCliArguments(cliArguments) { - const plugins = await importJson(`../plugins/plugins.json`, __dirname); + const plugins = await importJson(`../plugins/plugins.json`, import.meta.url); if (cliArguments._.length !== 1 || !plugins.importPlugins.includes(cliArguments.plugin) || !cliArguments[`author-name`]) { console.error(`Usage: ${process.argv[1]} -p -a [--create-pull-request] \n\navailable plugins: ${plugins.importPlugins.join(`, `)}`); diff --git a/cli/run-export-test.js b/cli/run-export-test.js index ff47b36ad4..e5fbd43a1e 100755 --- a/cli/run-export-test.js +++ b/cli/run-export-test.js @@ -1,15 +1,16 @@ #!/usr/bin/env node -const path = require(`path`); -const minimist = require(`minimist`); -const chalk = require(`chalk`); +import path from 'path'; +import minimist from 'minimist'; +import chalk from 'chalk'; +import { fileURLToPath } from 'url'; -const { fixtureFromFile, fixtureFromRepository } = require(`../lib/model.js`); -const importJson = require(`../lib/import-json.js`); +import { fixtureFromFile, fixtureFromRepository } from '../lib/model.js'; +import importJson from '../lib/import-json.js'; (async () => { try { - const plugins = await importJson(`../plugins/plugins.json`, __dirname); - const testFixtures = await importJson(`../tests/test-fixtures.json`, __dirname); + const plugins = await importJson(`../plugins/plugins.json`, import.meta.url); + const testFixtures = await importJson(`../tests/test-fixtures.json`, import.meta.url); const cliArguments = minimist(process.argv.slice(2), { string: [`p`], @@ -17,10 +18,12 @@ const importJson = require(`../lib/import-json.js`); alias: { p: `plugin`, h: `help` }, }); + const scriptName = import.meta.url.split(`/`).pop(); + const helpMessage = [ `Run the plugin's export tests against the specified fixtures`, `(or the test fixtures, if no fixtures are specified).`, - `Usage: node ${path.relative(process.cwd(), __filename)} -p [ ]`, + `Usage: node ${scriptName} -p [ ]`, `Options:`, ` --plugin, -p: Key of the plugin whose export tests should be called`, ` --help, -h: Show this help message.`, @@ -52,18 +55,18 @@ const importJson = require(`../lib/import-json.js`); ? testFixtures.map(fixture => fixtureFromRepository(fixture.man, fixture.key)) : cliArguments._.map(relativePath => fixtureFromFile(path.join(process.cwd(), relativePath))); - const pluginExport = require(`../plugins/${cliArguments.plugin}/export.js`); + const exportPlugin = await import(`../plugins/${cliArguments.plugin}/export.js`); - const files = await pluginExport.exportFixtures( + const files = await exportPlugin.exportFixtures( await Promise.all(fixtures), { - baseDirectory: path.join(__dirname, `..`), + baseDirectory: fileURLToPath(new URL(`../`, import.meta.url)), date: new Date(), }, ); await Promise.all(pluginData.exportTests.map(async testKey => { - const exportTest = require(`../plugins/${cliArguments.plugin}/exportTests/${testKey}.js`); + const { default: exportTest } = await import(`../plugins/${cliArguments.plugin}/exportTests/${testKey}.js`); const outputPerFile = await Promise.all(files.map(async file => { try { diff --git a/docs/environment-variables.md b/docs/environment-variables.md index 200da1e02f..61ed5c1c3b 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -9,7 +9,7 @@ MY_ENV_VARIABLE=hello NODE_ENV=production ``` -Every script that uses environment variables must require [`lib/load-env-file.js`](../lib/load-env-file.js) first (usually placed right after all the other `require` calls). Note that `require(...)` takes a relative path beginning with `./` or `../`. +Every script that uses environment variables must import [`lib/load-env-file.js`](../lib/load-env-file.js) first (usually placed right after all the other `import` calls). Please update these docs and [`cli/debug-env-variables.js`](../cli/debug-env-variables.js) after introducing new variables. diff --git a/docs/fixture-features.md b/docs/fixture-features.md index 425531c1fe..336846ca76 100644 --- a/docs/fixture-features.md +++ b/docs/fixture-features.md @@ -10,7 +10,7 @@ We use fixture features for the following purposes: Fixture features are saved in the the [`lib/fixture-features/`](../lib/fixture-features/) directory as JS modules that export an array of features. It is advised to put similar features into one module. A sample module looks like this: ```js -module.exports = [{ +export default [{ // Optional, default is the filename (without '.js', succeeded by `-${i}` if // multiple features per module are provided). Must be unique! id: `fine-channel-alias`, diff --git a/docs/fixture-model.md b/docs/fixture-model.md index 9a05887a0c..a206f6ad02 100644 --- a/docs/fixture-model.md +++ b/docs/fixture-model.md @@ -11,7 +11,7 @@ All model classes are located in the [`lib/model/`](../lib/model) directory. Whe ```js -const { fixtureFromRepository } = require(`./lib/model.js`); +import { fixtureFromRepository } from './lib/model.js'; const myFixture = await fixtureFromRepository(`cameo`, `nanospot-120`); // instanceof Fixture @@ -23,7 +23,7 @@ if (panFine.coarseChannel.hasHighlightValue) { } ``` -If you want to use a model class directly, also import it via `model.js` (like this: ``const { Meta } = require(`./lib/model.js`);``) because ES modules (`import ... from ...`, `export ...`) and CommonJS modules (`require(...)`, `module.exports = ...`) don't work together nicely; `model.js` fixes this through a polyfill. +If you want to use a model class directly, also import it via `model.js` (like this: `import { Meta } from './lib/model.js';`). Model properties are always implemented using getters and setters. To store data, we use backing fields (an internal property prefixed with underscore, e.g. `_jsonObject`) to hold the data. The backing field should never be accessed directly, but only through its getter and setter functions (without underscore). diff --git a/docs/plugins.md b/docs/plugins.md index 776485691a..bf855786b1 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -35,17 +35,17 @@ If exporting is supported, create a `plugins//export.js` module that A very simple export plugin looks like this: ```js -module.exports.version = `0.1.0`; // semantic versioning of export plugin +export const version = `0.1.0`; // semantic versioning of export plugin /** * @param {Array.} fixtures An array of Fixture objects, see our fixture model * @param {Object} options Some global options, for example: * @param {String} options.baseDirectory Absolute path to OFL's root directory * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} All generated files (see file schema above) */ -module.exports.exportFixtures = async function exportPluginName(fixtures, options) { +export async function exportFixtures(fixtures, options) { const outfiles = []; for (const fixture of fixtures) { @@ -62,7 +62,7 @@ module.exports.exportFixtures = async function exportPluginName(fixtures, option } return outfiles; -}; +} ``` ## Importing @@ -92,7 +92,7 @@ If the file can not be parsed by the import plugin or contains errors, the retur Example: ```js -module.exports.version = `0.1.0`; // semantic versioning of import plugin +export const version = `0.1.0`; // semantic versioning of import plugin /** * @param {Buffer} buffer The imported file. @@ -100,7 +100,7 @@ module.exports.version = `0.1.0`; // semantic versioning of import plugin * @param {String} authorName The importer's name. * @returns {Promise.} A Promise that resolves to an out object (see above) or rejects with an error. */ -module.exports.importFixtures = async function importPluginName(buffer, fileName, authorName) { +export async function importFixtures(buffer, fileName, authorName) { const out = { manufacturers: {}, fixtures: {}, @@ -129,7 +129,7 @@ module.exports.importFixtures = async function importPluginName(buffer, fileName out.fixtures[`${manufacturerKey}/${fixtureKey}`] = fixtureObject; return out; -}; +} ``` ## Export tests @@ -141,7 +141,7 @@ A plugin's export test takes an exported file object as argument and evaluates i Each test module should be located at `plugins//exportTests/.js`. Here's a dummy test illustrating the structure: ```js -const xml2js = require(`xml2js`); +import xml2js from 'xml2js'; /** * @param {Object} exportFile The file returned by the plugins' export module. @@ -152,7 +152,7 @@ const xml2js = require(`xml2js`); * @param {String|null} exportFile.mode Mode's shortName if given file only describes a single mode. * @returns {Promise.|String>} Resolve when the test passes or reject with an array of errors or one error if the test fails. */ -module.exports = async function testValueCorrectness(exportFile) { +export default async function testValueCorrectness(exportFile) { const xml = await xml2js.parseStringPromise(exportFile.content); const errors = []; @@ -168,7 +168,7 @@ module.exports = async function testValueCorrectness(exportFile) { } // everything's ok -}; +} ``` You can execute an export test from the command line: diff --git a/lib/ajv-validator.js b/lib/ajv-validator.js index 2805abbc53..51eab39aea 100644 --- a/lib/ajv-validator.js +++ b/lib/ajv-validator.js @@ -1,9 +1,9 @@ -const Ajv = require(`ajv`); -const addFormats = require(`ajv-formats`); +import Ajv from 'ajv'; +import addFormats from 'ajv-formats'; /** @typedef {import('ajv').ValidateFunction} ValidateFunction */ -const importJson = require(`./import-json.js`); +import importJson from './import-json.js'; const ajv = new Ajv({ verbose: true, @@ -15,16 +15,16 @@ ajv.addKeyword(`version`); ajv.addFormat(`color-hex`, true); const loadSchemasPromise = Promise.all([ - importJson(`../schemas/capability.json`, __dirname), - importJson(`../schemas/channel.json`, __dirname), - importJson(`../schemas/definitions.json`, __dirname), - importJson(`../schemas/fixture-redirect.json`, __dirname), - importJson(`../schemas/fixture.json`, __dirname), - importJson(`../schemas/gobo.json`, __dirname), - importJson(`../schemas/manufacturers.json`, __dirname), - importJson(`../schemas/matrix.json`, __dirname), - importJson(`../schemas/plugin.json`, __dirname), - importJson(`../schemas/wheel-slot.json`, __dirname), + importJson(`../schemas/capability.json`, import.meta.url), + importJson(`../schemas/channel.json`, import.meta.url), + importJson(`../schemas/definitions.json`, import.meta.url), + importJson(`../schemas/fixture-redirect.json`, import.meta.url), + importJson(`../schemas/fixture.json`, import.meta.url), + importJson(`../schemas/gobo.json`, import.meta.url), + importJson(`../schemas/manufacturers.json`, import.meta.url), + importJson(`../schemas/matrix.json`, import.meta.url), + importJson(`../schemas/plugin.json`, import.meta.url), + importJson(`../schemas/wheel-slot.json`, import.meta.url), ]).then(schemas => { ajv.addSchema(schemas); }); @@ -34,7 +34,7 @@ const loadSchemasPromise = Promise.all([ * @param {String} schemaName The name of the schema to load. * @returns {ValidateFunction} The validate function for the specified schema. */ -module.exports = async function getAjvValidator(schemaName) { +export default async function getAjvValidator(schemaName) { await loadSchemasPromise; const schemaId = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/master/schemas/${schemaName}.json`; @@ -45,4 +45,4 @@ module.exports = async function getAjvValidator(schemaName) { } return validationFunction; -}; +} diff --git a/lib/create-github-issue.js b/lib/create-github-issue.js index 39d850d08f..0357bcc7a1 100644 --- a/lib/create-github-issue.js +++ b/lib/create-github-issue.js @@ -1,6 +1,6 @@ -require(`./load-env-file.js`); +import './load-env-file.js'; -const { Octokit } = require(`@octokit/rest`); +import { Octokit } from '@octokit/rest'; /** * @param {String} title The issue heading. @@ -8,7 +8,7 @@ const { Octokit } = require(`@octokit/rest`); * @param {Array.|null} [labels=[]] Array of label names the created issue should be tagged with. * @returns {Promise.} A promise that resolves to the issue URL, or rejects with an error. */ -module.exports = async function createIssue(title, body, labels = []) { +export default async function createIssue(title, body, labels = []) { const repository = process.env.NODE_ENV === `production` ? `open-fixture-library` : `ofl-test`; const userToken = process.env.GITHUB_USER_TOKEN; @@ -30,4 +30,4 @@ module.exports = async function createIssue(title, body, labels = []) { }); return result.data.html_url; -}; +} diff --git a/lib/create-github-pr.js b/lib/create-github-pr.js index 6bc496aebb..b748ffd3d5 100644 --- a/lib/create-github-pr.js +++ b/lib/create-github-pr.js @@ -1,9 +1,9 @@ -const fixtureJsonStringify = require(`./fixture-json-stringify.js`); -const { getObjectSortedByKeys } = require(`./register.js`); +import fixtureJsonStringify from './fixture-json-stringify.js'; +import { getObjectSortedByKeys } from './register.js'; -require(`./load-env-file.js`); +import './load-env-file.js'; -const { Octokit } = require(`@octokit/rest`); +import { Octokit } from '@octokit/rest'; /** @typedef {import('./types.js').FixtureCreateResult} FixtureCreateResult */ @@ -13,7 +13,7 @@ const { Octokit } = require(`@octokit/rest`); * @param {String|null} [githubComment=null] Additional comment for the pull request. * @returns {Promise.} A promise that resolves to the pull request URL, or rejects with an error. */ -module.exports = async function createPullRequest(fixtureCreateResult, githubUsername = null, githubComment = null) { +export default async function createPullRequest(fixtureCreateResult, githubUsername = null, githubComment = null) { const { manufacturers, fixtures, @@ -294,7 +294,7 @@ module.exports = async function createPullRequest(fixtureCreateResult, githubUse githubErrors.push(`Error (${action.toLowerCase()} ${displayName}): \`${error.message}\``); } } -}; +} /** diff --git a/lib/diff-plugin-outputs.js b/lib/diff-plugin-outputs.js index 35c432fc8f..c3df78c5b0 100644 --- a/lib/diff-plugin-outputs.js +++ b/lib/diff-plugin-outputs.js @@ -1,11 +1,12 @@ -const { mkdir, readFile, rm, writeFile } = require(`fs/promises`); -const path = require(`path`); -const childProcess = require(`child_process`); -const JSZip = require(`jszip`); -const chalk = require(`chalk`); -const disparity = require(`disparity`); -const directoryCompare = require(`dir-compare`); -const promisify = require(`util`).promisify; +import { mkdir, readFile, rm, writeFile } from 'fs/promises'; +import path from 'path'; +import childProcess from 'child_process'; +import JSZip from 'jszip'; +import chalk from 'chalk'; +import disparity from 'disparity'; +import directoryCompare from 'dir-compare'; +import { fileURLToPath } from 'url'; +import { promisify } from 'util'; /** * @typedef {Object} PluginDiffOutput @@ -23,7 +24,7 @@ const promisify = require(`util`).promisify; * @param {Array.} fixtures Paths to the compared fixtures, relative to the current working directory. * @returns {Promise.} Information what output files were removed, added or changed plus the diffs for changed files. */ -module.exports = async function diffPluginOutputs(currentPluginKey, comparePluginKey, ref, fixtures) { +export default async function diffPluginOutputs(currentPluginKey, comparePluginKey, ref, fixtures) { const date = new Date(); // get manufacturer and fixture data later used by export plugins @@ -42,25 +43,25 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi console.log(`# fixtures:`, fixtures.map(([manufacturer, fixture]) => `${manufacturer}/${fixture}`).join(`, `)); console.log(); - const temporaryDirectory = path.join(__dirname, `..`, `tmp`); - if (process.cwd().startsWith(temporaryDirectory)) { + const temporaryDirectoryUrl = new URL(`../tmp/`, import.meta.url); + if (process.cwd().startsWith(fileURLToPath(temporaryDirectoryUrl))) { console.error(chalk.red(`[Error]`), `This script can't be run from inside the tmp directory.`); process.exit(1); } - const currentOut = path.join(temporaryDirectory, `current_output`); - const compareOut = path.join(temporaryDirectory, `compare_output`); + const currentOutUrl = new URL(`current_output/`, temporaryDirectoryUrl); + const compareOutUrl = new URL(`compare_output/`, temporaryDirectoryUrl); // delete old temp folder (if it exists) and recreate it - await rm(temporaryDirectory, { + await rm(temporaryDirectoryUrl, { recursive: true, force: true, }); - await mkdir(temporaryDirectory, { recursive: true }); + await mkdir(temporaryDirectoryUrl, { recursive: true }); // export with current plugin script try { - await exportFixtures(currentOut, currentPluginKey, path.join(__dirname, `..`)); + await exportFixtures(currentOutUrl, currentPluginKey, new URL(`../`, import.meta.url)); } catch (error) { console.error(chalk.red(`[Error]`), `Exporting with current plugin script failed:`, error); @@ -68,12 +69,12 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi } // get compare script and fixture files as archive - const compareArchivePath = path.join(temporaryDirectory, `compare.zip`); - const unzipDirectory = path.join(temporaryDirectory, `compareFiles`); + const compareArchiveUrl = new URL(`compare.zip`, temporaryDirectoryUrl); + const unzipDirectoryUrl = new URL(`compareFiles/`, temporaryDirectoryUrl); try { - await promisify(childProcess.exec)(`git archive ${ref} -o ${compareArchivePath}`, { - cwd: path.join(__dirname, `..`), + await promisify(childProcess.exec)(`git archive ${ref} -o ${fileURLToPath(compareArchiveUrl)}`, { + cwd: fileURLToPath(new URL(`../`, import.meta.url)), encoding: `utf-8`, }); } @@ -83,8 +84,8 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi } // unzip compare archive - await mkdir(unzipDirectory, { recursive: true }); - const compareArchiveData = await readFile(compareArchivePath); + await mkdir(unzipDirectoryUrl, { recursive: true }); + const compareArchiveData = await readFile(compareArchiveUrl); const zip = await JSZip.loadAsync(compareArchiveData); await Promise.all(Object.values(zip.files).map(async file => { @@ -92,21 +93,21 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi return; } - const filePath = path.join(unzipDirectory, file.name); + const filePath = fileURLToPath(new URL(file.name, unzipDirectoryUrl)); await mkdir(path.dirname(filePath), { recursive: true }); const fileBuffer = await file.async(`nodebuffer`); await writeFile(filePath, fileBuffer); })); // delete compare archive - await rm(compareArchivePath, { + await rm(compareArchiveUrl, { recursive: true, force: true, }); // export with compare plugin script try { - await exportFixtures(compareOut, comparePluginKey, unzipDirectory); + await exportFixtures(compareOutUrl, comparePluginKey, unzipDirectoryUrl); } catch (error) { console.error(chalk.red(`[Error]`), `Exporting with compare plugin script failed:`, error); @@ -114,7 +115,7 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi } // find the differences - const outputData = await findDifferences(currentOut, compareOut); + const outputData = await findDifferences(fileURLToPath(currentOutUrl), fileURLToPath(compareOutUrl)); console.log(`Done.`); return outputData; @@ -122,14 +123,14 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi /** * - * @param {String} outputPath The path where to output the exported fixtures. + * @param {URL} outputUrl The path where to output the exported fixtures. * @param {String} pluginKey The plugin key. - * @param {String} baseDirectory The OFL root directory. + * @param {URL} baseDirectory The OFL root directory. * @returns {Promise.<*, Error>} A Promise that resolves when all exported fixtures are saved to the filesystem. */ - async function exportFixtures(outputPath, pluginKey, baseDirectory) { - const plugin = require(path.join(baseDirectory, `plugins/${pluginKey}/export.js`)); - const { fixtureFromRepository } = require(path.join(baseDirectory, `lib`, `model.js`)); + async function exportFixtures(outputUrl, pluginKey, baseDirectory) { + const plugin = await import(new URL(`plugins/${pluginKey}/export.js`, baseDirectory)); + const { fixtureFromRepository } = await import(new URL(`lib/model.js`, baseDirectory)); // support export plugins before https://github.com/OpenLightingProject/open-fixture-library/pull/1623/commits/391e6045c6f0fcc0009bec924801b91790d3472c const exportFunction = plugin.exportFixtures || plugin.export; @@ -146,12 +147,12 @@ module.exports = async function diffPluginOutputs(currentPluginKey, comparePlugi ); return Promise.all(outFiles.map(async outFile => { - const outFilePath = path.join(outputPath, outFile.name); + const outFilePath = fileURLToPath(new URL(outFile.name, outputUrl)); await mkdir(path.dirname(outFilePath), { recursive: true }); await writeFile(outFilePath, outFile.content); })); } -}; +} /** * @param {String} currentOut The output directory of the current version. diff --git a/lib/esm-shim.cjs b/lib/esm-shim.cjs new file mode 100644 index 0000000000..53e3966fdf --- /dev/null +++ b/lib/esm-shim.cjs @@ -0,0 +1,17 @@ +/** + * @fileoverview + * There are some JSON files that need to be imported synchronously, but we + * don't want to use the `--experimental-json-modules` command-line flag for + * every `node` command. Thus, we require them all here in this CommonJS module + * and re-export them for use in ECMAScript modules. + * + * @see https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_experimental_json_modules + */ + +module.exports.manufacturersSchema = require(`../schemas/manufacturers.json`); +module.exports.fixtureRedirectSchema = require(`../schemas/fixture-redirect.json`); +module.exports.fixtureSchema = require(`../schemas/fixture.json`); +module.exports.channelSchema = require(`../schemas/channel.json`); +module.exports.capabilitySchema = require(`../schemas/capability.json`); +module.exports.wheelSlotSchema = require(`../schemas/wheel-slot.json`); +module.exports.definitionsSchema = require(`../schemas/definitions.json`); diff --git a/lib/fixture-features/capability-types.js b/lib/fixture-features/capability-types.js index ca742a00cd..c723a86fb3 100644 --- a/lib/fixture-features/capability-types.js +++ b/lib/fixture-features/capability-types.js @@ -1,12 +1,9 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign - -const schemaProperties = require(`../../lib/schema-properties.js`).default; +import schemaProperties from '../../lib/schema-properties.js'; const capabilityTypes = Object.keys(schemaProperties.capabilityTypes); -module.exports = capabilityTypes.map(type => ({ +export default capabilityTypes.map(type => ({ id: `capability-type-${type}`, name: `Capability type ${type}`, description: `Whether the fixture has at least one capability of type '${type}'`, diff --git a/lib/fixture-features/duplicate-channel-names.js b/lib/fixture-features/duplicate-channel-names.js index 32fa95616e..0d77dcfc22 100644 --- a/lib/fixture-features/duplicate-channel-names.js +++ b/lib/fixture-features/duplicate-channel-names.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `Duplicate channel names`, /** diff --git a/lib/fixture-features/fine-channels.js b/lib/fixture-features/fine-channels.js index 5a7ce6889d..df60ae284d 100644 --- a/lib/fixture-features/fine-channels.js +++ b/lib/fixture-features/fine-channels.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [ +export default [ { id: `fine-channel-alias`, name: `Fine channels (16bit)`, diff --git a/lib/fixture-features/fine-positions.js b/lib/fixture-features/fine-positions.js index 4da6b3f775..055ecee818 100644 --- a/lib/fixture-features/fine-positions.js +++ b/lib/fixture-features/fine-positions.js @@ -1,7 +1,7 @@ -const { FineChannel } = require(`../model.js`); +import { FineChannel } from '../model.js'; /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [ +export default [ { name: `Fine before coarse`, description: `Fine channel used in a mode before its coarse channel`, diff --git a/lib/fixture-features/floating-point-physicals.js b/lib/fixture-features/floating-point-physicals.js index 6b41831cab..91c07e50e3 100644 --- a/lib/fixture-features/floating-point-physicals.js +++ b/lib/fixture-features/floating-point-physicals.js @@ -1,7 +1,7 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ /** @typedef {import('../model/Physical.js').default} Physical */ -module.exports = [ +const fixtureFeatures = [ { id: `floating-point-dimensions`, name: `Floating point dimensions`, @@ -35,13 +35,15 @@ module.exports = [ }, ]; -for (const fixtureFeature of module.exports) { +export default fixtureFeatures.map(fixtureFeature => ({ + ...fixtureFeature, + /** * @param {Fixture} fixture The Fixture instance * @returns {Boolean} true if the fixture uses the feature */ - fixtureFeature.hasFeature = fixture => isFloatInPhysical(fixture.physical, fixtureFeature.properties) || fixture.modes.some(mode => isFloatInPhysical(mode.physical, fixtureFeature.properties)); -} + hasFeature: fixture => isFloatInPhysical(fixture.physical, fixtureFeature.properties) || fixture.modes.some(mode => isFloatInPhysical(mode.physical, fixtureFeature.properties)), +})); /** * @param {Physical|null} physical The physical data to check diff --git a/lib/fixture-features/many-modes.js b/lib/fixture-features/many-modes.js index eb6374a1b1..eba0ba1d85 100644 --- a/lib/fixture-features/many-modes.js +++ b/lib/fixture-features/many-modes.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `Many modes`, description: `True if the fixture has more than 15 modes.`, diff --git a/lib/fixture-features/matrices.js b/lib/fixture-features/matrices.js index 908211408d..3c932f47f3 100644 --- a/lib/fixture-features/matrices.js +++ b/lib/fixture-features/matrices.js @@ -1,8 +1,7 @@ -const { FineChannel } = require(`../model.js`); +import { FineChannel, SwitchingChannel } from '../model.js'; /** @typedef {import('../model/Fixture.js').default} Fixture */ -const { SwitchingChannel } = require(`../model.js`); -module.exports = [ +export default [ { id: `matrix-pixelKeys`, name: `Uses pixelKeys`, diff --git a/lib/fixture-features/multiple-categories.js b/lib/fixture-features/multiple-categories.js index 2d55828656..bb112ea9ef 100644 --- a/lib/fixture-features/multiple-categories.js +++ b/lib/fixture-features/multiple-categories.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `Multiple categories`, /** diff --git a/lib/fixture-features/multiple-focuses.js b/lib/fixture-features/multiple-focuses.js index 863fa110b9..72d9329f58 100644 --- a/lib/fixture-features/multiple-focuses.js +++ b/lib/fixture-features/multiple-focuses.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `Multiple Focuses`, description: `True if multiple Pan / Tilt channels are used in some mode.`, diff --git a/lib/fixture-features/no-physical-data.js b/lib/fixture-features/no-physical-data.js index 25c91402c4..46438d1c0d 100644 --- a/lib/fixture-features/no-physical-data.js +++ b/lib/fixture-features/no-physical-data.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `No physical`, /** diff --git a/lib/fixture-features/null-channels.js b/lib/fixture-features/null-channels.js index 20d8de49ee..802dddf645 100644 --- a/lib/fixture-features/null-channels.js +++ b/lib/fixture-features/null-channels.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `\`null\` channels`, description: `Channel list of a mode contains null, so it has an unused channel`, diff --git a/lib/fixture-features/physical-override.js b/lib/fixture-features/physical-override.js index 7642a7e99e..d2418fd94a 100644 --- a/lib/fixture-features/physical-override.js +++ b/lib/fixture-features/physical-override.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `Physical override`, description: `Whether at least one mode uses the 'physical' property`, diff --git a/lib/fixture-features/rdm.js b/lib/fixture-features/rdm.js index 65bb08be15..23727fd2ba 100644 --- a/lib/fixture-features/rdm.js +++ b/lib/fixture-features/rdm.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `RDM`, description: `Whether an RDM model ID is set`, diff --git a/lib/fixture-features/redirect-reasons.js b/lib/fixture-features/redirect-reasons.js index 68e77ad2f8..3a830733f5 100644 --- a/lib/fixture-features/redirect-reasons.js +++ b/lib/fixture-features/redirect-reasons.js @@ -1,17 +1,14 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign +import importJson from '../import-json.js'; +import schemaProperties from '../../lib/schema-properties.js'; -const importJson = require(`../import-json.js`); -const schemaProperties = require(`../../lib/schema-properties.js`).default; - -const registerPromise = importJson(`../../fixtures/register.json`, __dirname); +const registerPromise = importJson(`../../fixtures/register.json`, import.meta.url); /** @type {Array.} */ const redirectReasons = schemaProperties.fixtureRedirect.reason.enum; -module.exports = redirectReasons.map(reason => ({ +export default redirectReasons.map(reason => ({ id: `redirect-reason-${reason}`, name: `Fixture redirect reason ${reason}`, description: `Whether the fixture is a fixture redirect with reason '${reason}'`, diff --git a/lib/fixture-features/reused-channels.js b/lib/fixture-features/reused-channels.js index 1bce0a65bd..524cb01325 100644 --- a/lib/fixture-features/reused-channels.js +++ b/lib/fixture-features/reused-channels.js @@ -1,6 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [{ +export default [{ name: `Reused channels`, description: `Whether there is at least one channel that is used in different modes`, diff --git a/lib/fixture-features/switching-channels.js b/lib/fixture-features/switching-channels.js index 295b10cb5d..680b3090a7 100644 --- a/lib/fixture-features/switching-channels.js +++ b/lib/fixture-features/switching-channels.js @@ -1,7 +1,7 @@ -const { FineChannel } = require(`../model.js`); +import { FineChannel } from '../model.js'; /** @typedef {import('../model/Fixture.js').default} Fixture */ -module.exports = [ +export default [ { id: `switching-channels`, name: `Switching channels`, diff --git a/lib/fixture-features/wheels.js b/lib/fixture-features/wheels.js index 38670faace..449394b5b6 100644 --- a/lib/fixture-features/wheels.js +++ b/lib/fixture-features/wheels.js @@ -1,9 +1,6 @@ /** @typedef {import('../model/Fixture.js').default} Fixture */ -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign - -const schemaProperties = require(`../../lib/schema-properties.js`).default; +import schemaProperties from '../../lib/schema-properties.js'; const wheelSlotTypes = Object.keys(schemaProperties.wheelSlotTypes); const wheelTypes = wheelSlotTypes.filter(type => !type.startsWith(`AnimationGobo`)).concat(`AnimationGobo`); @@ -53,4 +50,4 @@ const resourceFeature = { ), }; -module.exports = wheelTypeFeatures.concat(wheelSlotTypeFeatures, resourceFeature); +export default wheelTypeFeatures.concat(wheelSlotTypeFeatures, resourceFeature); diff --git a/lib/fixture-json-stringify.js b/lib/fixture-json-stringify.js index 8650efcf80..b905bfed75 100644 --- a/lib/fixture-json-stringify.js +++ b/lib/fixture-json-stringify.js @@ -4,7 +4,7 @@ * @param {Object} object JSON object. * @returns {String} String representing the given object. */ -module.exports = function fixtureJsonStringify(object) { +export default function fixtureJsonStringify(object) { let string = JSON.stringify(object, null, 2); // make number arrays fit in one line @@ -18,4 +18,4 @@ module.exports = function fixtureJsonStringify(object) { ); return `${string}\n`; -}; +} diff --git a/lib/get-ajv-error-messages.js b/lib/get-ajv-error-messages.js index e06e6d3859..0c8c2f4be7 100644 --- a/lib/get-ajv-error-messages.js +++ b/lib/get-ajv-error-messages.js @@ -41,7 +41,7 @@ const getDetailsPerAjvKeyword = { * @param {String} [rootName=`root`] The display name of the root object in the error data path. * @returns {String} A human-readable validation error message. */ -module.exports = function getAjvErrorMessages(ajvErrors, rootName = `root`) { +export default function getAjvErrorMessages(ajvErrors, rootName = `root`) { const errors = ajvErrors.filter(error => !(`propertyName` in error)); return errors.map(error => { @@ -50,7 +50,7 @@ module.exports = function getAjvErrorMessages(ajvErrors, rootName = `root`) { const errorMessage = `${rootName}${error.instancePath}${getDataDescription(error.data)} ${details}`; return errorMessage.replace(/\n/g, `\\n`); }); -}; +} /** * @param {*} data Any kind of data; not all types can be represented. diff --git a/lib/import-json.js b/lib/import-json.js index 3e6b0bbd2e..86ce30b9ff 100644 --- a/lib/import-json.js +++ b/lib/import-json.js @@ -1,12 +1,12 @@ -const { readFile } = require(`fs/promises`); -const path = require(`path`); +import { readFile } from 'fs/promises'; +import path from 'path'; /** * @param {String|URL} jsonPath The JSON file path. * @param {String|URL|undefined} basePath A path from which the JSON path is resolved relative to. * @returns {Promise.<*>} A Promise that resolves to the parsed JSON file content. */ -module.exports = async function importJson(jsonPath, basePath) { +export default async function importJson(jsonPath, basePath) { if (typeof basePath === `string` && !basePath.startsWith(`file:`)) { jsonPath = path.resolve(basePath, jsonPath); } @@ -15,4 +15,4 @@ module.exports = async function importJson(jsonPath, basePath) { } return JSON.parse(await readFile(jsonPath, `utf8`)); -}; +} diff --git a/lib/load-env-file.js b/lib/load-env-file.js index 427a549a48..c67d1a4f7d 100644 --- a/lib/load-env-file.js +++ b/lib/load-env-file.js @@ -1,5 +1,5 @@ -const path = require(`path`); -const env = require(`node-env-file`); +import env from 'node-env-file'; +import { fileURLToPath } from 'url'; -const envFile = path.join(__dirname, `../.env`); -env(envFile, { raise: false }); +const envFilePath = fileURLToPath(new URL(`../.env`, import.meta.url)); +env(envFilePath, { raise: false }); diff --git a/lib/model.js b/lib/model.js index 759f85dda5..38b441f8e9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1,28 +1,26 @@ -const path = require(`path`); -const { readFile } = require(`fs/promises`); - -const importJson = require(`./import-json.js`); - -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign - -const AbstractChannel = require(`./model/AbstractChannel.js`).default; -const Capability = require(`./model/Capability.js`).default; -const CoarseChannel = require(`./model/CoarseChannel.js`).default; -const Entity = require(`./model/Entity.js`).default; -const FineChannel = require(`./model/FineChannel.js`).default; -const Fixture = require(`./model/Fixture.js`).default; -const Manufacturer = require(`./model/Manufacturer.js`).default; -const Matrix = require(`./model/Matrix.js`).default; -const Meta = require(`./model/Meta.js`).default; -const Mode = require(`./model/Mode.js`).default; -const NullChannel = require(`./model/NullChannel.js`).default; -const Physical = require(`./model/Physical.js`).default; -const Range = require(`./model/Range.js`).default; -const SwitchingChannel = require(`./model/SwitchingChannel.js`).default; -const TemplateChannel = require(`./model/TemplateChannel.js`).default; -const Wheel = require(`./model/Wheel.js`).default; -const WheelSlot = require(`./model/WheelSlot.js`).default; +import path from 'path'; +import { readFile } from 'fs/promises'; +import { fileURLToPath } from 'url'; + +import importJson from './import-json.js'; + +import AbstractChannel from './model/AbstractChannel.js'; +import Capability from './model/Capability.js'; +import CoarseChannel from './model/CoarseChannel.js'; +import Entity from './model/Entity.js'; +import FineChannel from './model/FineChannel.js'; +import Fixture from './model/Fixture.js'; +import Manufacturer from './model/Manufacturer.js'; +import Matrix from './model/Matrix.js'; +import Meta from './model/Meta.js'; +import Mode from './model/Mode.js'; +import NullChannel from './model/NullChannel.js'; +import Physical from './model/Physical.js'; +import Range from './model/Range.js'; +import SwitchingChannel from './model/SwitchingChannel.js'; +import TemplateChannel from './model/TemplateChannel.js'; +import Wheel from './model/Wheel.js'; +import WheelSlot from './model/WheelSlot.js'; /** * Look up the fixture definition in the directory structure and create a Fixture instance. @@ -54,11 +52,11 @@ async function fixtureFromFile(absolutePath) { */ async function fixtureFromRepository(manufacturerKey, fixtureKey) { let fixturePath = `../fixtures/${manufacturerKey}/${fixtureKey}.json`; - let fixtureJson = await importJson(fixturePath, __dirname); + let fixtureJson = await importJson(fixturePath, import.meta.url); if (fixtureJson.$schema.endsWith(`/fixture-redirect.json`)) { fixturePath = `../fixtures/${fixtureJson.redirectTo}.json`; - fixtureJson = Object.assign({}, await importJson(fixturePath, __dirname), { name: fixtureJson.name }); + fixtureJson = Object.assign({}, await importJson(fixturePath, import.meta.url), { name: fixtureJson.name }); } const manufacturer = await manufacturerFromRepository(manufacturerKey); @@ -73,7 +71,7 @@ async function fixtureFromRepository(manufacturerKey, fixtureKey) { * @returns {Promise.} A Promise that resolves to the created Manufacturer instance. */ async function manufacturerFromRepository(manufacturerKey) { - const manufacturers = await importJson(`../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../fixtures/manufacturers.json`, import.meta.url); return new Manufacturer(manufacturerKey, manufacturers[manufacturerKey]); } @@ -99,24 +97,24 @@ async function embedResourcesIntoFixtureJson(fixtureJson) { async function getResourceFromString(resourceName) { const { type, key, alias } = await resolveResourceName(resourceName); - const resourceBasePath = path.join(__dirname, `../resources/${type}`); - const resourcePath = `${resourceBasePath}/${key}.json`; + const resourceBaseUrl = new URL(`../resources/${type}/`, import.meta.url); + const resourceUrl = new URL(`${key}.json`, resourceBaseUrl); let resourceData; try { - resourceData = await importJson(resourcePath); + resourceData = await importJson(resourceUrl); } catch (error) { throw error instanceof SyntaxError - ? new Error(`Resource file '${resourcePath}' could not be parsed as JSON.`) + ? new Error(`Resource file '${fileURLToPath(resourceUrl)}' could not be parsed as JSON.`) : new Error(`Resource '${resourceName}' not found.`); } resourceData.key = key; resourceData.type = type; resourceData.alias = alias; - resourceData.image = await getImageForResource(type, resourceBasePath, key); + resourceData.image = await getImageForResource(type, resourceBaseUrl, key); delete resourceData.$schema; @@ -144,7 +142,7 @@ async function resolveResourceName(resourceName) { let aliases; try { - aliases = await importJson(`../${aliasesFilePath}`, __dirname); + aliases = await importJson(`../${aliasesFilePath}`, import.meta.url); } catch { throw new Error(`Resource aliases file '${aliasesFilePath}' not found.`); @@ -189,14 +187,14 @@ const resourceFileFormats = [ /** * @param {String} type The resource type, i.e. name of the directory inside the resources directory. - * @param {String} basePath The path of the resource directory. + * @param {URL} baseUrl The path of the resource directory. * @param {String} key The resource key. * @returns {Promise.} A Promise that resolves to the resource image, or undefined if none could be found. */ -async function getImageForResource(type, basePath, key) { +async function getImageForResource(type, baseUrl, key) { for (const { extension, mimeType, encoding } of resourceFileFormats) { try { - let data = await readFile(`${basePath}/${key}.${extension}`, encoding); + let data = await readFile(new URL(`${key}.${extension}`, baseUrl), encoding); if (extension === `svg`) { // see https://cloudfour.com/thinks/simple-svg-placeholder/#how-it-works @@ -217,13 +215,13 @@ async function getImageForResource(type, basePath, key) { if (type === `gobos`) { const fileExtensions = resourceFileFormats.map(({ extension }) => extension); - throw new Error(`Expected gobo image for resource '${basePath}/${key}' not found (supported file extensions: ${fileExtensions.join(`, `)}).`); + throw new Error(`Expected gobo image for resource '${fileURLToPath(new URL(key, baseUrl))}' not found (supported file extensions: ${fileExtensions.join(`, `)}).`); } return undefined; } -module.exports = { +export { AbstractChannel, Capability, CoarseChannel, diff --git a/lib/model/.eslintrc.json b/lib/model/.eslintrc.json deleted file mode 100644 index bd14a19ef2..0000000000 --- a/lib/model/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "sourceType": "module" - } -} diff --git a/lib/register.js b/lib/register.js index 06ee4cfa1e..d01787ae0a 100644 --- a/lib/register.js +++ b/lib/register.js @@ -1,5 +1,5 @@ -const ColorHash = require(`color-hash`).default; -const colorHash = new ColorHash({ +import ColorHash from 'color-hash'; +const colorHash = new (ColorHash.default || ColorHash)({ lightness: [0.5, 0.6], saturation: [0.5, 0.6, 0.7], hash: string => Array.from(string).reduce((accumulator, char, index) => { @@ -11,7 +11,7 @@ const colorHash = new ColorHash({ /** * A data store for the fixture register. */ -class Register { +export class Register { /** * Create a new register instance. * @param {Object} manufacturers An object of all known manufacturers like specified by the manufacturer schema. @@ -250,7 +250,7 @@ class Register { * @param {ItemMapFunction|null} itemMapFunction A function to be invoked for every object value to process it (useful to sort array values). * @returns {Object} A new object with the same entries, sorted by keys. */ -function getObjectSortedByKeys(object, itemMapFunction) { +export function getObjectSortedByKeys(object, itemMapFunction) { const sortedObject = {}; const keys = Object.keys(object).sort(localeSort); @@ -296,8 +296,3 @@ function getFixtureLastAction(fixtureMeta) { lastActionDate: fixtureMeta.lastModifyDate, }; } - -module.exports = { - Register, - getObjectSortedByKeys, -}; diff --git a/lib/schema-properties.js b/lib/schema-properties.js index 3097d18cb8..8fff7dbe0b 100644 --- a/lib/schema-properties.js +++ b/lib/schema-properties.js @@ -1,10 +1,12 @@ -import manufacturersSchema from '../schemas/manufacturers.json'; -import fixtureRedirectSchema from '../schemas/fixture-redirect.json'; -import fixtureSchema from '../schemas/fixture.json'; -import channelSchema from '../schemas/channel.json'; -import capabilitySchema from '../schemas/capability.json'; -import wheelSlotSchema from '../schemas/wheel-slot.json'; -import definitionsSchema from '../schemas/definitions.json'; +import { + manufacturersSchema, + fixtureRedirectSchema, + fixtureSchema, + channelSchema, + capabilitySchema, + wheelSlotSchema, + definitionsSchema, +} from '../lib/esm-shim.cjs'; const fixtureProperties = fixtureSchema.properties; const physicalProperties = fixtureProperties.physical.properties; diff --git a/lib/server-response-helpers.js b/lib/server-response-helpers.js index fa6190084a..d928860704 100644 --- a/lib/server-response-helpers.js +++ b/lib/server-response-helpers.js @@ -5,7 +5,7 @@ * @param {ServerResponse} response The Node ServerResponse object. * @param {Object} jsonObject The JSON object to send. */ -function sendJson(response, jsonObject) { +export function sendJson(response, jsonObject) { response.setHeader(`Content-Type`, `application/json`); response.end(JSON.stringify(jsonObject)); } @@ -17,13 +17,8 @@ function sendJson(response, jsonObject) { * @param {String} file.mimetype The MIME type to set. * @param {String|Buffer} file.content The content of the file attachment. */ -function sendAttachment(response, { name, mimetype, content }) { +export function sendAttachment(response, { name, mimetype, content }) { response.setHeader(`Content-Type`, mimetype); response.setHeader(`Content-Disposition`, `attachment; filename="${name}"`); response.end(content); } - -module.exports = { - sendJson, - sendAttachment, -}; diff --git a/lib/site-crawler.js b/lib/site-crawler.js index 5bbfa4be4d..d14b535f64 100644 --- a/lib/site-crawler.js +++ b/lib/site-crawler.js @@ -1,8 +1,8 @@ -const childProcess = require(`child_process`); -const EventEmitter = require(`events`); -const { SiteChecker } = require(`broken-link-checker`); +import childProcess from 'child_process'; +import EventEmitter from 'events'; +import brokenLinkChecker from 'broken-link-checker'; -const importJson = require(`./import-json.js`); +import importJson from './import-json.js'; const BASE_URL = `http://localhost:${process.env.PORT || 3000}`; @@ -11,7 +11,7 @@ const BASE_URL = `http://localhost:${process.env.PORT || 3000}`; * @emits failingPage The URL of a failing (internal) page and an error string. * @emits externalLinkFound The URL of an external link. */ -class SiteCrawler extends EventEmitter { +export default class SiteCrawler extends EventEmitter { /** * Starts the production OFL server by creating a new child process. * Make sure that 'npm run build' has been called before this function is executed! @@ -49,10 +49,10 @@ class SiteCrawler extends EventEmitter { * @returns {Promise} Promise that resolves as soon as the crawling has finished. */ async crawl() { - const exportPluginKeys = (await importJson(`../plugins/plugins.json`, __dirname)).exportPlugins; + const exportPluginKeys = (await importJson(`../plugins/plugins.json`, import.meta.url)).exportPlugins; return new Promise((resolve, reject) => { - const siteChecker = new SiteChecker({ + const siteChecker = new brokenLinkChecker.SiteChecker({ excludeExternalLinks: true, filterLevel: 3, honorRobotExclusions: false, @@ -126,5 +126,3 @@ class SiteCrawler extends EventEmitter { return { stdout: this.serverStdout, stderr: this.serverStderr }; } } - -module.exports = SiteCrawler; diff --git a/lib/types.js b/lib/types.js index addad4cd7f..881d903694 100644 --- a/lib/types.js +++ b/lib/types.js @@ -1,5 +1,5 @@ // needed for VS Code to import typedefs from this file -module.exports = null; +export default null; /** * @typedef {Object} FixtureCreateResult diff --git a/nuxt.config.js b/nuxt.config.js index 78fbf84968..7e8b17340e 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -1,4 +1,4 @@ -import path from 'path'; +import { fileURLToPath } from 'url'; import plugins from './plugins/plugins.json'; import register from './fixtures/register.json'; @@ -71,7 +71,7 @@ export default { }, extend(config, context) { // exclude /assets/icons from url-loader - const iconsPath = path.resolve(__dirname, `ui/assets/icons`); + const iconsPath = fileURLToPath(new URL(`ui/assets/icons/`, import.meta.url)); const urlLoader = config.module.rules.find(rule => rule.test.toString().includes(`|svg|`)); urlLoader.exclude = iconsPath; diff --git a/package-lock.json b/package-lock.json index 6dcfff9cf7..e1be4b690b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2674,28 +2674,28 @@ } }, "@nuxt/telemetry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-1.3.3.tgz", - "integrity": "sha512-ElnoAJo1n/Ui0j9i3xqhXajoGJdEwmkEtsWftlZUpQNJxdfoz+623qnt9XHMYa0X5Nf1PXYdcUKa2u4AASXOjA==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-1.3.6.tgz", + "integrity": "sha512-sZpLf/rU3cvN8/alR1HpJIl3mHPA1GOg41GKdOOrtw7Gi/lCEVk4hK+lpXgYInZ2n6i1JyknpKhM9YzX2RU33w==", "requires": { "arg": "^5.0.0", - "chalk": "^4.1.0", - "ci-info": "^2.0.0", - "consola": "^2.15.0", + "chalk": "^4.1.1", + "ci-info": "^3.1.1", + "consola": "^2.15.3", "create-require": "^1.1.1", - "defu": "^3.2.2", + "defu": "^5.0.0", "destr": "^1.1.0", - "dotenv": "^8.2.0", + "dotenv": "^9.0.2", "fs-extra": "^8.1.0", - "git-url-parse": "^11.4.3", + "git-url-parse": "^11.4.4", "inquirer": "^7.3.3", - "is-docker": "^2.1.1", - "jiti": "^1.3.0", - "nanoid": "^3.1.20", + "is-docker": "^2.2.1", + "jiti": "^1.9.2", + "nanoid": "^3.1.23", "node-fetch": "^2.6.1", "parse-git-config": "^3.0.0", "rc9": "^1.2.0", - "std-env": "^2.2.1" + "std-env": "^2.3.0" }, "dependencies": { "arg": { @@ -2703,25 +2703,15 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.0.tgz", "integrity": "sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ==" }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, "consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, "defu": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/defu/-/defu-3.2.2.tgz", - "integrity": "sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==" - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/defu/-/defu-5.0.0.tgz", + "integrity": "sha512-VHg73EDeRXlu7oYWRmmrNp/nl7QkdXUxkQQKig0Zk8daNmm84AbGoC8Be6/VVLJEKxn12hR0UBmz8O+xQiAPKQ==" } } }, @@ -3391,6 +3381,12 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/mdast": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz", @@ -4058,6 +4054,27 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + }, + "dependencies": { + "is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true + } + } + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -4068,6 +4085,17 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -5187,12 +5215,12 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "catharsis": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", - "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.15" } }, "chalk": { @@ -7487,12 +7515,281 @@ } } }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-module-utils": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", + "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, "eslint-plugin-array-func": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/eslint-plugin-array-func/-/eslint-plugin-array-func-3.1.7.tgz", "integrity": "sha512-fB5TBICjHSTGToNTbCCgR8zsngpUkoCM31EMh/M/NEAyNg90i5rUuG0dnNNBML2n0BzM0nBE3sPvo2SEWf6jlA==", "dev": true }, + "eslint-plugin-import": { + "version": "2.23.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.3.tgz", + "integrity": "sha512-wDxdYbSB55F7T5CC7ucDjY641VvKmlRwT0Vxh7PkY1mI4rclVRFWYfsrjDgZvwYYDZ5ee0ZtfFKXowWjqvEoRQ==", + "dev": true, + "requires": { + "array-includes": "^3.1.3", + "array.prototype.flat": "^1.2.4", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.1", + "find-up": "^2.0.0", + "has": "^1.0.3", + "is-core-module": "^2.4.0", + "minimatch": "^3.0.4", + "object.values": "^1.1.3", + "pkg-up": "^2.0.0", + "read-pkg-up": "^3.0.0", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } + } + }, "eslint-plugin-jsdoc": { "version": "34.8.2", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-34.8.2.tgz", @@ -9519,9 +9816,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "hpkp": { @@ -10349,9 +10646,9 @@ "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" }, "is-ssh": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.2.tgz", - "integrity": "sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", + "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", "requires": { "protocols": "^1.1.0" } @@ -10460,12 +10757,6 @@ } } }, - "jgexml": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/jgexml/-/jgexml-0.4.3.tgz", - "integrity": "sha512-N4doRtHFobW+prTgh32GRIRIflJIQrzf/ll4ePsg1wnonyhiBb29zeyVQ5MkwZDYPUbLuEAyVSx5XikPECXU9g==", - "dev": true - }, "jiti": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.9.2.tgz", @@ -10500,25 +10791,25 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdoc": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.6.tgz", - "integrity": "sha512-znR99e1BHeyEkSvgDDpX0sTiTu+8aQyDl9DawrkOGZTTW8hv0deIFXx87114zJ7gRaDZKVQD/4tr1ifmJp9xhQ==", + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", + "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", "dev": true, "requires": { "@babel/parser": "^7.9.4", "bluebird": "^3.7.2", - "catharsis": "^0.8.11", + "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.1", "klaw": "^3.0.0", "markdown-it": "^10.0.0", "markdown-it-anchor": "^5.2.7", - "marked": "^0.8.2", + "marked": "^2.0.3", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", "strip-json-comments": "^3.1.0", "taffydb": "2.6.2", - "underscore": "~1.10.2" + "underscore": "~1.13.1" }, "dependencies": { "escape-string-regexp": { @@ -10528,9 +10819,9 @@ "dev": true }, "marked": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", - "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.5.tgz", + "integrity": "sha512-yfCEUXmKhBPLOzEC7c+tc4XZdIeTdGoRCZakFMkCxodr7wDXqoapIME4wjcpBPJLNyUnKJ3e8rb8wlAgnLnaDw==", "dev": true }, "strip-json-comments": { @@ -10542,18 +10833,18 @@ } }, "jsdoc-api": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.0.0.tgz", - "integrity": "sha512-efKegVRrpzqzsTf4eDfTXSj7lyBfpFdu2VPv6hyzbOcaWVErAl0ArVB2mFstqtNYjwIGPmajHx/Ive7UrtuZtQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.0.1.tgz", + "integrity": "sha512-SttT7mAvl/L9liIoOoa647ksFlD+fyNP2Vy80MBRi6akOmJQ4ryQjMBOPfg1veKfwVp/8f3My8Bb2JnVGL9wVg==", "dev": true, "requires": { "array-back": "^5.0.0", "cache-point": "^2.0.0", "collect-all": "^1.0.4", - "file-set": "^4.0.1", + "file-set": "^4.0.2", "fs-then-native": "^2.0.0", "jsdoc": "^3.6.6", - "object-to-spawn-args": "^2.0.0", + "object-to-spawn-args": "^2.0.1", "temp-path": "^1.0.0", "walk-back": "^5.0.0" } @@ -10604,9 +10895,9 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-pointer": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.0.tgz", - "integrity": "sha1-jlAFUKaqxUZKRzN32leqbMIoKNc=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.1.tgz", + "integrity": "sha512-3OvjqKdCBvH41DLpV4iSt6v2XhZXV1bPB4OROuknvUXI7ZQNofieCPkmE26stEJ9zdQuvIxDHCuYhfgxFAAs+Q==", "dev": true, "requires": { "foreach": "^2.0.4" @@ -10892,6 +11183,36 @@ "uc.micro": "^1.0.1" } }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "loader-runner": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", @@ -10924,9 +11245,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -12654,9 +12975,9 @@ } }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yargs": { @@ -13407,6 +13728,66 @@ "find-up": "^4.0.0" } }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, "pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -15623,9 +16004,9 @@ } }, "sass-loader": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.1.1.tgz", - "integrity": "sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.2.0.tgz", + "integrity": "sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw==", "requires": { "klona": "^2.0.4", "loader-utils": "^2.0.0", @@ -15634,6 +16015,17 @@ "semver": "^7.3.2" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -15645,9 +16037,9 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "^1.2.5" } @@ -15683,25 +16075,12 @@ "@types/json-schema": "^7.0.6", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - } } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "requires": { "lru-cache": "^6.0.0" } @@ -16633,6 +17012,12 @@ "ansi-regex": "^2.0.0" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -17391,9 +17776,9 @@ } }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yargs": { @@ -18040,6 +18425,18 @@ "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==" }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, "tslib": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", @@ -18155,9 +18552,9 @@ } }, "underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", "dev": true }, "unfetch": { @@ -18381,9 +18778,9 @@ } }, "urijs": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.5.tgz", - "integrity": "sha512-48z9VGWwdCV5KfizHsE05DWS5fhK6gFlx5MjO7xu0Krc5FGPWzjlXEVV0nPMrdVuP7xmMHiPZ2HoYZwKOFTZOg==", + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.6.tgz", + "integrity": "sha512-eSXsXZ2jLvGWeLYlQA3Gh36BcjF+0amo92+wHPyN1mdR8Nxf75fuEuYTd9c0a+m/vhCjRK0ESlE9YNLW+E1VEw==", "dev": true }, "urix": { @@ -19489,7 +19886,7 @@ "fast-safe-stringify": "^2.0.7", "highlightjs": "^9.12.0", "httpsnippet": "^1.19.0", - "jgexml": "^0.4.3", + "jgexml": "^0.4.4", "markdown-it": "^10.0.0", "markdown-it-emoji": "^1.4.0", "node-fetch": "^2.0.0", @@ -19501,6 +19898,14 @@ "urijs": "^1.19.0", "yaml": "^1.8.3", "yargs": "^12.0.5" + }, + "dependencies": { + "jgexml": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jgexml/-/jgexml-0.4.4.tgz", + "integrity": "sha512-j0AzSWT7LXy3s3i1cdv5NZxUtscocwiBxgOLiEBfitCehm8STdXVrcOlbAWsJFLCq1elZYpQlGqA9k8Z+n9iJA==", + "dev": true + } } }, "wide-align": { @@ -19707,9 +20112,9 @@ } }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { "version": "2.1.2", diff --git a/package.json b/package.json index 74ed113838..58aaf497e7 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "engines": { "node": "14.15.0" }, + "type": "module", "scripts": { "dev": "nuxt dev", "start": "nuxt start", @@ -61,7 +62,7 @@ "openapi-backend": "^3.9.2", "sanitize-filename": "^1.6.3", "sass": "^1.33.0", - "sass-loader": "^10.1.1", + "sass-loader": "^10.2.0", "scroll-into-view": "^1.15.0", "svg-inline-loader": "^0.8.2", "uuid": "^8.3.2", @@ -78,6 +79,7 @@ "disparity": "^3.2.0", "eslint": "~7.26.0", "eslint-plugin-array-func": "~3.1.7", + "eslint-plugin-import": "^2.23.3", "eslint-plugin-jsdoc": "~34.8.2", "eslint-plugin-jsonc": "~1.2.1", "eslint-plugin-markdown": "~2.1.0", diff --git a/plugins/aglight/export.js b/plugins/aglight/export.js index 7edd407843..859d9ef27a 100644 --- a/plugins/aglight/export.js +++ b/plugins/aglight/export.js @@ -1,30 +1,30 @@ /* Based on the ofl export plugin */ -const fixtureJsonStringify = require(`../../lib/fixture-json-stringify.js`); -const namedColors = require(`color-name-list`); +import fixtureJsonStringify from '../../lib/fixture-json-stringify.js'; +import namedColors from 'color-name-list/dist/colornames.esm.mjs'; -const { Entity, NullChannel } = require(`../../lib/model.js`); -const importJson = require(`../../lib/import-json.js`); +import { Entity, NullChannel } from '../../lib/model.js'; +import importJson from '../../lib/import-json.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ const units = new Set([`K`, `deg`, `%`, `ms`, `Hz`, `m^3/min`, `rpm`]); const excludeKeys = new Set([`comment`, `name`, `helpWanted`, `type`, `effectName`, `effectPreset`, `shutterEffect`, `wheel`, `isShaking`, `fogType`, `menuClick`]); -module.exports.version = `1.0.0`; +export const version = `1.0.0`; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportAGLight(fixtures, options) { - const displayedPluginVersion = options.displayedPluginVersion || module.exports.version; +export async function exportFixtures(fixtures, options) { + const displayedPluginVersion = options.displayedPluginVersion || version; - const manufacturers = await importJson(`../../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../../fixtures/manufacturers.json`, import.meta.url); const library = { version: displayedPluginVersion, @@ -51,7 +51,7 @@ module.exports.exportFixtures = async function exportAGLight(fixtures, options) mimetype: `application/aglight-fixture-library`, fixtures, }]; -}; +} /** * Resolves matrix channels in modes' channel lists. diff --git a/plugins/colorsource/export.js b/plugins/colorsource/export.js index 33f2852838..538b2a92db 100644 --- a/plugins/colorsource/export.js +++ b/plugins/colorsource/export.js @@ -1,16 +1,13 @@ -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign -const { v5: uuidv5 } = require(`uuid`); +import { v5 as uuidv5 } from 'uuid'; -const { +import { CoarseChannel, FineChannel, SwitchingChannel, -} = require(`../../lib/model.js`); -const { scaleDmxValue } = require(`../../lib/scale-dmx-values.js`); +} from '../../lib/model.js'; +import { scaleDmxValue } from '../../lib/scale-dmx-values.js'; -module.exports.name = `ColorSource`; -module.exports.version = `0.1.0`; +export const version = `0.1.0`; const EDITOR_VERSION = `1.1.1.9.0.4`; @@ -30,7 +27,7 @@ const UUID_NAMESPACE = `0de81b51-02b2-45e3-b53c-578f9eb31b77`; // seed for UUIDs * @param {Date|null} options.date The current time. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = function exportColorSource(fixtures, options) { +export async function exportFixtures(fixtures, options) { const exportJson = { date: options.date.toISOString().replace(/\.\d{3}Z$/, `Z`), editorVersion: EDITOR_VERSION, @@ -69,7 +66,7 @@ module.exports.exportFixtures = function exportColorSource(fixtures, options) { mimetype: `application/json`, fixtures, }]); -}; +} /** * @param {Array.} colorSourceChannels A ColorSource fixture's parameter property. diff --git a/plugins/d-light/export.js b/plugins/d-light/export.js index 1d36a30fa7..34c33b648d 100644 --- a/plugins/d-light/export.js +++ b/plugins/d-light/export.js @@ -1,25 +1,25 @@ -const xmlbuilder = require(`xmlbuilder`); -const sanitize = require(`sanitize-filename`); +import xmlbuilder from 'xmlbuilder'; +import sanitize from 'sanitize-filename'; /** @typedef {import('../../lib/model/AbstractChannel.js').default} AbstractChannel */ /** @typedef {import('../../lib/model/Capability.js').default} Capability */ -const { CoarseChannel } = require(`../../lib/model.js`); -const { FineChannel } = require(`../../lib/model.js`); +import { CoarseChannel } from '../../lib/model.js'; +import { FineChannel } from '../../lib/model.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ /** @typedef {import('../../lib/model/Mode.js').default} Mode */ -const { SwitchingChannel } = require(`../../lib/model.js`); +import { SwitchingChannel } from '../../lib/model.js'; -module.exports.version = `0.2.0`; +export const version = `0.2.0`; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportDLight(fixtures, options) { +export async function exportFixtures(fixtures, options) { const deviceFiles = []; for (const fixture of fixtures) { @@ -30,7 +30,7 @@ module.exports.exportFixtures = async function exportDLight(fixtures, options) { .element({ Device: { 'OFL_Export': { - '@id': options.displayedPluginVersion || module.exports.version, + '@id': options.displayedPluginVersion || version, '#text': fixture.url, }, frames: { @@ -63,7 +63,7 @@ module.exports.exportFixtures = async function exportDLight(fixtures, options) { } return deviceFiles; -}; +} /** * Channels are grouped in attributes in D::Light. diff --git a/plugins/d-light/exportTests/attributes-correctness.js b/plugins/d-light/exportTests/attributes-correctness.js index 967d895395..c8ab2bebf8 100644 --- a/plugins/d-light/exportTests/attributes-correctness.js +++ b/plugins/d-light/exportTests/attributes-correctness.js @@ -1,4 +1,4 @@ -const xml2js = require(`xml2js`); +import xml2js from 'xml2js'; /** * @typedef {Object} ExportFile @@ -14,7 +14,7 @@ const xml2js = require(`xml2js`); * @param {Array.} allExportFiles An array of all export files. * @returns {Promise.|String>} Resolve when the test passes or reject with an array of errors or one error if the test fails. */ -module.exports = async function testAttributesCorrectness(exportFile, allExportFiles) { +export default async function testAttributesCorrectness(exportFile, allExportFiles) { try { const xml = await xml2js.parseStringPromise(exportFile.content); const errors = []; @@ -42,4 +42,4 @@ module.exports = async function testAttributesCorrectness(exportFile, allExportF catch (parseError) { throw `Error parsing XML: ${parseError.toString()}`; } -}; +} diff --git a/plugins/dragonframe/export.js b/plugins/dragonframe/export.js index af0281696f..4ac07b347b 100644 --- a/plugins/dragonframe/export.js +++ b/plugins/dragonframe/export.js @@ -1,22 +1,22 @@ -const fixtureJsonStringify = require(`../../lib/fixture-json-stringify.js`); -const importJson = require(`../../lib/import-json.js`); +import fixtureJsonStringify from '../../lib/fixture-json-stringify.js'; +import importJson from '../../lib/import-json.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ // needed for export test -module.exports.supportedOflVersion = `12.2.1`; +export const supportedOflVersion = `12.2.1`; -module.exports.version = `1.0.0`; +export const version = `1.0.0`; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportDragonframe(fixtures, options) { +export async function exportFixtures(fixtures, options) { const usedManufacturers = new Set(); // one JSON file for each fixture @@ -25,7 +25,7 @@ module.exports.exportFixtures = async function exportDragonframe(fixtures, optio const jsonData = JSON.parse(JSON.stringify(fixture.jsonObject)); - jsonData.$schema = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${module.exports.supportedOflVersion}/schemas/fixture.json`; + jsonData.$schema = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${supportedOflVersion}/schemas/fixture.json`; jsonData.fixtureKey = fixture.key; jsonData.manufacturerKey = fixture.manufacturer.key; @@ -39,11 +39,11 @@ module.exports.exportFixtures = async function exportDragonframe(fixtures, optio }; }); - const manufacturers = await importJson(`../../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../../fixtures/manufacturers.json`, import.meta.url); // manufacturers.json file const usedManufacturerData = { - $schema: `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${module.exports.supportedOflVersion}/schemas/manufacturers.json`, + $schema: `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${supportedOflVersion}/schemas/manufacturers.json`, }; for (const manufacturer of Object.keys(manufacturers).sort()) { if (usedManufacturers.has(manufacturer)) { @@ -57,4 +57,4 @@ module.exports.exportFixtures = async function exportDragonframe(fixtures, optio }); return files; -}; +} diff --git a/plugins/dragonframe/exportTests/json-schema-conformity.js b/plugins/dragonframe/exportTests/json-schema-conformity.js index 6c724597f1..8b77c272ea 100644 --- a/plugins/dragonframe/exportTests/json-schema-conformity.js +++ b/plugins/dragonframe/exportTests/json-schema-conformity.js @@ -1,9 +1,9 @@ -const https = require(`https`); -const Ajv = require(`ajv`); -const addFormats = require(`ajv-formats`); -const getAjvErrorMessages = require(`../../../lib/get-ajv-error-messages.js`); +import https from 'https'; +import Ajv from 'ajv'; +import addFormats from 'ajv-formats'; +import getAjvErrorMessages from '../../../lib/get-ajv-error-messages.js'; -const SUPPORTED_OFL_VERSION = require(`../export.js`).supportedOflVersion; +import { supportedOflVersion as SUPPORTED_OFL_VERSION } from '../export.js'; const REPO_BASE_URL = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library`; const SCHEMA_BASE_URL = `${REPO_BASE_URL}/schema-${SUPPORTED_OFL_VERSION}/schemas/`; const SCHEMA_FILES = [ @@ -34,7 +34,7 @@ const schemaPromises = getSchemas(); * @param {Array.} allExportFiles An array of all export files. * @returns {Promise.|String>} Resolve when the test passes or reject with an array of errors or one error if the test fails. */ -module.exports = async function testJsonSchemaConformity(exportFile, allExportFiles) { +export default async function testJsonSchemaConformity(exportFile, allExportFiles) { const schemas = await schemaPromises; const ajv = new Ajv({ schemas, @@ -51,7 +51,7 @@ module.exports = async function testJsonSchemaConformity(exportFile, allExportFi if (!schemaValid) { throw getAjvErrorMessages(schemaValidate.errors, `fixture`); } -}; +} /** * @returns {Promise.>} Asynchronously downloaded and JSON parsed schemas. diff --git a/plugins/ecue/export.js b/plugins/ecue/export.js index 29015629f5..f97f992af4 100644 --- a/plugins/ecue/export.js +++ b/plugins/ecue/export.js @@ -1,24 +1,24 @@ -const xmlbuilder = require(`xmlbuilder`); +import xmlbuilder from 'xmlbuilder'; -const { CoarseChannel } = require(`../../lib/model.js`); -const { FineChannel } = require(`../../lib/model.js`); +import { CoarseChannel } from '../../lib/model.js'; +import { FineChannel } from '../../lib/model.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ /** @typedef {import('../../lib/model/Mode.js').default} Mode */ -const { NullChannel } = require(`../../lib/model.js`); -const { Physical } = require(`../../lib/model.js`); -const { SwitchingChannel } = require(`../../lib/model.js`); +import { NullChannel } from '../../lib/model.js'; +import { Physical } from '../../lib/model.js'; +import { SwitchingChannel } from '../../lib/model.js'; -module.exports.version = `0.3.0`; +export const version = `0.3.0`; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportECue(fixtures, options) { +export async function exportFixtures(fixtures, options) { const timestamp = dateToString(options.date); const manufacturers = {}; @@ -83,7 +83,7 @@ module.exports.exportFixtures = async function exportECue(fixtures, options) { mimetype: `application/xml`, fixtures, }]; -}; +} /** * @param {Object} xmlManufacturer The xmlbuilder object. diff --git a/plugins/ecue/import.js b/plugins/ecue/import.js index c1c01b9bac..e4b60aeb95 100644 --- a/plugins/ecue/import.js +++ b/plugins/ecue/import.js @@ -1,7 +1,7 @@ -const colorNameList = require(`color-name-list`); -const xml2js = require(`xml2js`); +import colorNameList from 'color-name-list/dist/colornames.esm.mjs'; +import xml2js from 'xml2js'; -module.exports.version = `0.3.1`; +export const version = `0.3.1`; const colors = {}; for (const color of colorNameList) { @@ -14,7 +14,7 @@ for (const color of colorNameList) { * @param {String} authorName The importer's name. * @returns {Promise.} A Promise resolving to an out object */ -module.exports.importFixtures = async function importECue(buffer, filename, authorName) { +export async function importFixtures(buffer, filename, authorName) { const timestamp = new Date().toISOString().replace(/T.*/, ``); const out = { @@ -124,7 +124,7 @@ module.exports.importFixtures = async function importECue(buffer, filename, auth out.fixtures[fixtureKey] = fixture; } -}; +} /** * @param {Object} ecueFixture The e:cue fixture object. diff --git a/plugins/gdtf/deprecated-gdtf-attributes.js b/plugins/gdtf/deprecated-gdtf-attributes.js index 117061b353..dbb0b33a33 100644 --- a/plugins/gdtf/deprecated-gdtf-attributes.js +++ b/plugins/gdtf/deprecated-gdtf-attributes.js @@ -1,4 +1,4 @@ -const { normalizeAngularSpeedDirection } = require(`./gdtf-helpers.js`); +import { normalizeAngularSpeedDirection } from './gdtf-helpers.js'; const deprecatedGdtfAttributes = { ActiveZone: undefined, // From https://gitlab.com/petrvanek/gdtf-libraries/blob/master/gdtf.xsd @@ -525,4 +525,4 @@ function guessColorComponentName(gdtfCapability, primaryColor, secondaryColor) { return primaryColor; } -module.exports = deprecatedGdtfAttributes; +export default deprecatedGdtfAttributes; diff --git a/plugins/gdtf/gdtf-attributes.js b/plugins/gdtf/gdtf-attributes.js index 44f18564f8..155772706a 100644 --- a/plugins/gdtf/gdtf-attributes.js +++ b/plugins/gdtf/gdtf-attributes.js @@ -1,12 +1,12 @@ -const { +import { followXmlNodeReference, getRgbColorFromGdtfColor, normalizeAngularSpeedDirection, -} = require(`./gdtf-helpers.js`); -const deprecatedGdtfAttributes = require(`./deprecated-gdtf-attributes.js`); +} from './gdtf-helpers.js'; +import deprecatedGdtfAttributes from './deprecated-gdtf-attributes.js'; // see https://gdtf-share.com/wiki/GDTF_File_Description#Attribute -const gdtfUnits = { +export const gdtfUnits = { None(value) { return value; }, @@ -1250,7 +1250,7 @@ function guessSpeedOrDuration(gdtfCapability) { return gdtfCapability._channelFunction._attribute.$.PhysicalUnit === `Time` ? `duration` : `speed`; } -module.exports = { - gdtfUnits, - gdtfAttributes: Object.assign({}, deprecatedGdtfAttributes, gdtfAttributes), +export default { + ...deprecatedGdtfAttributes, + ...gdtfAttributes, }; diff --git a/plugins/gdtf/gdtf-helpers.js b/plugins/gdtf/gdtf-helpers.js index 68615a8f06..817a16d0b1 100644 --- a/plugins/gdtf/gdtf-helpers.js +++ b/plugins/gdtf/gdtf-helpers.js @@ -3,7 +3,7 @@ * @param {String} nodeReference A string of the form "Name.Name.Name…", see https://gdtf-share.com/wiki/GDTF_File_Description#attrType-node * @returns {Object|null} The referenced XML node object, or null if it could not be found. */ -function followXmlNodeReference(startNode, nodeReference) { +export function followXmlNodeReference(startNode, nodeReference) { if (!startNode || !nodeReference) { return null; } @@ -45,7 +45,7 @@ function followXmlNodeReference(startNode, nodeReference) { * @param {String} gdtfColorString A string in the form "0.3127, 0.3290, 100.0", see https://gdtf-share.com/wiki/GDTF_File_Description#attrType-colorCIE * @returns {String} The RGB hex code string in the form "#rrggbb". */ -function getRgbColorFromGdtfColor(gdtfColorString) { +export function getRgbColorFromGdtfColor(gdtfColorString) { /* eslint-disable camelcase, space-in-parens, unicorn/no-zero-fractions */ // functions ported from https://github.com/njsmith/colorspacious @@ -119,7 +119,7 @@ function getRgbColorFromGdtfColor(gdtfColorString) { /** * @param {Object} gdtfCapability The enhanced XML object. */ -function normalizeAngularSpeedDirection(gdtfCapability) { +export function normalizeAngularSpeedDirection(gdtfCapability) { if (/CCW|counter[\s-]*clockwise/.test(gdtfCapability.$.Name)) { gdtfCapability._physicalFrom = -Math.abs(gdtfCapability._physicalFrom); gdtfCapability._physicalTo = -Math.abs(gdtfCapability._physicalTo); @@ -129,9 +129,3 @@ function normalizeAngularSpeedDirection(gdtfCapability) { gdtfCapability._physicalTo = Math.abs(gdtfCapability._physicalTo); } } - -module.exports = { - followXmlNodeReference, - getRgbColorFromGdtfColor, - normalizeAngularSpeedDirection, -}; diff --git a/plugins/gdtf/import.js b/plugins/gdtf/import.js index 8dfffd9f71..5387f6d0c1 100644 --- a/plugins/gdtf/import.js +++ b/plugins/gdtf/import.js @@ -1,16 +1,13 @@ -const xml2js = require(`xml2js`); -const JSZip = require(`jszip`); +import xml2js from 'xml2js'; +import JSZip from 'jszip'; -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign +import { CoarseChannel } from '../../lib/model.js'; +import { scaleDmxValue, scaleDmxRangeIndividually } from '../../lib/scale-dmx-values.js'; +import importJson from '../../lib/import-json.js'; +import gdtfAttributes, { gdtfUnits } from './gdtf-attributes.js'; +import { getRgbColorFromGdtfColor, followXmlNodeReference } from './gdtf-helpers.js'; -const { CoarseChannel } = require(`../../lib/model.js`); -const { scaleDmxValue, scaleDmxRangeIndividually } = require(`../../lib/scale-dmx-values.js`); -const importJson = require(`../../lib/import-json.js`); -const { gdtfAttributes, gdtfUnits } = require(`./gdtf-attributes.js`); -const { getRgbColorFromGdtfColor, followXmlNodeReference } = require(`./gdtf-helpers.js`); - -module.exports.version = `0.2.0`; +export const version = `0.2.0`; /** * @param {Buffer} buffer The imported file. @@ -18,7 +15,7 @@ module.exports.version = `0.2.0`; * @param {String} authorName The importer's name. * @returns {Promise.} A Promise resolving to an out object */ -module.exports.importFixtures = async function importGdtf(buffer, filename, authorName) { +export async function importFixtures(buffer, filename, authorName) { const fixture = { $schema: `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/master/schemas/fixture.json`, }; @@ -48,7 +45,7 @@ module.exports.importFixtures = async function importGdtf(buffer, filename, auth const manufacturerKey = slugify(gdtfFixture.$.Manufacturer); const fixtureKey = `${manufacturerKey}/${slugify(fixture.name)}`; - const manufacturers = await importJson(`../../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../../fixtures/manufacturers.json`, import.meta.url); let manufacturer; if (manufacturerKey in manufacturers) { @@ -1254,7 +1251,7 @@ module.exports.importFixtures = async function importGdtf(buffer, filename, auth return CoarseChannel.RESOLUTION_8BIT; } } -}; +} /** diff --git a/plugins/millumin/export.js b/plugins/millumin/export.js index e325b22da9..fb8f58da54 100644 --- a/plugins/millumin/export.js +++ b/plugins/millumin/export.js @@ -1,28 +1,28 @@ -const fixtureJsonStringify = require(`../../lib/fixture-json-stringify.js`); +import fixtureJsonStringify from '../../lib/fixture-json-stringify.js'; -const { CoarseChannel } = require(`../../lib/model.js`); +import { CoarseChannel } from '../../lib/model.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ -module.exports.version = `0.4.0`; +export const version = `0.4.0`; // needed for export test -module.exports.supportedOflVersion = `7.3.0`; +export const supportedOflVersion = `7.3.0`; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportMillumin(fixtures, options) { +export async function exportFixtures(fixtures, options) { // one JSON file for each fixture const outFiles = fixtures.map(fixture => { const oflJson = JSON.parse(JSON.stringify(fixture.jsonObject)); const milluminJson = {}; - milluminJson.$schema = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${module.exports.supportedOflVersion}/schemas/fixture.json`; + milluminJson.$schema = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${supportedOflVersion}/schemas/fixture.json`; milluminJson.name = oflJson.name; addIfValidData(milluminJson, `shortName`, oflJson.shortName); milluminJson.categories = getDowngradedCategories(oflJson.categories); @@ -67,7 +67,7 @@ module.exports.exportFixtures = async function exportMillumin(fixtures, options) }); return outFiles; -}; +} /** * Replaces the fixture's categories array with one that only includes categories diff --git a/plugins/millumin/exportTests/json-schema-conformity.js b/plugins/millumin/exportTests/json-schema-conformity.js index 4c7c25e50c..a82d184da0 100644 --- a/plugins/millumin/exportTests/json-schema-conformity.js +++ b/plugins/millumin/exportTests/json-schema-conformity.js @@ -1,9 +1,9 @@ -const https = require(`https`); -const Ajv = require(`ajv`); -const addFormats = require(`ajv-formats`); -const getAjvErrorMessages = require(`../../../lib/get-ajv-error-messages.js`); +import https from 'https'; +import Ajv from 'ajv'; +import addFormats from 'ajv-formats'; +import getAjvErrorMessages from '../../../lib/get-ajv-error-messages.js'; -const SUPPORTED_OFL_VERSION = require(`../export.js`).supportedOflVersion; +import { supportedOflVersion as SUPPORTED_OFL_VERSION } from '../export.js'; const SCHEMA_BASE_URL = `https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-${SUPPORTED_OFL_VERSION}/schemas/`; const SCHEMA_FILES = [`capability.json`, `channel.json`, `definitions.json`, `fixture.json`]; @@ -23,7 +23,7 @@ const schemaPromises = getSchemas(); * @param {Array.} allExportFiles An array of all export files. * @returns {Promise.|String>} Resolve when the test passes or reject with an array of errors or one error if the test fails. */ -module.exports = async function testSchemaConformity(exportFile, allExportFiles) { +export default async function testSchemaConformity(exportFile, allExportFiles) { const schemas = await schemaPromises; const ajv = new Ajv({ schemas, @@ -39,7 +39,7 @@ module.exports = async function testSchemaConformity(exportFile, allExportFiles) if (!schemaValid) { throw getAjvErrorMessages(schemaValidate.errors, `fixture`); } -}; +} /** * @returns {Promise.>} Asynchronously downloaded and JSON parsed schemas. Already tweaked to handle Millumin's deviations from the supported schema version. diff --git a/plugins/ofl/export.js b/plugins/ofl/export.js index 69d2a396fb..579c67f0ab 100644 --- a/plugins/ofl/export.js +++ b/plugins/ofl/export.js @@ -1,20 +1,21 @@ -const fixtureJsonStringify = require(`../../lib/fixture-json-stringify.js`); -const importJson = require(`../../lib/import-json.js`); +import fixtureJsonStringify from '../../lib/fixture-json-stringify.js'; +import importJson from '../../lib/import-json.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ -module.exports.version = require(`../../schemas/fixture.json`).version; +import { fixtureSchema } from '../../lib/esm-shim.cjs'; +export const version = fixtureSchema.version; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportOfl(fixtures, options) { - const displayedPluginVersion = options.displayedPluginVersion || module.exports.version; +export async function exportFixtures(fixtures, options) { + const displayedPluginVersion = options.displayedPluginVersion || version; const usedManufacturers = new Set(); @@ -38,7 +39,7 @@ module.exports.exportFixtures = async function exportOfl(fixtures, options) { }; }); - const manufacturers = await importJson(`../../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../../fixtures/manufacturers.json`, import.meta.url); // manufacturers.json file const usedManufacturerData = { @@ -56,4 +57,4 @@ module.exports.exportFixtures = async function exportOfl(fixtures, options) { }); return files; -}; +} diff --git a/plugins/op-z/export.js b/plugins/op-z/export.js index cc2e43bf71..9a78b2b556 100644 --- a/plugins/op-z/export.js +++ b/plugins/op-z/export.js @@ -1,11 +1,11 @@ /** @typedef {import('../../lib/model/AbstractChannel.js').default} AbstractChannel */ -const { CoarseChannel } = require(`../../lib/model.js`); -const { FineChannel } = require(`../../lib/model.js`); +import { CoarseChannel } from '../../lib/model.js'; +import { FineChannel } from '../../lib/model.js'; /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ -const { NullChannel } = require(`../../lib/model.js`); -const { SwitchingChannel } = require(`../../lib/model.js`); +import { NullChannel } from '../../lib/model.js'; +import { SwitchingChannel } from '../../lib/model.js'; -module.exports.version = `0.1.0`; +export const version = `0.1.0`; const MAX_KNOBS = 8; const MAX_OPZ_FIXTURES = 16; @@ -15,10 +15,10 @@ const MAX_OPZ_FIXTURES = 16; * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportOpZ(fixtures, options) { +export async function exportFixtures(fixtures, options) { const exportJson = { profiles: [], config: [], @@ -127,4 +127,4 @@ module.exports.exportFixtures = async function exportOpZ(fixtures, options) { return null; } } -}; +} diff --git a/plugins/qlcplus_4.12.2/export.js b/plugins/qlcplus_4.12.2/export.js index 1817c14ca5..4b7e6773ad 100644 --- a/plugins/qlcplus_4.12.2/export.js +++ b/plugins/qlcplus_4.12.2/export.js @@ -1,33 +1,33 @@ -const xmlbuilder = require(`xmlbuilder`); -const sanitize = require(`sanitize-filename`); +import xmlbuilder from 'xmlbuilder'; +import sanitize from 'sanitize-filename'; -const { +import { getChannelPreset, getFineChannelPreset, getCapabilityPreset, exportHelpers, -} = require(`./presets.js`); +} from './presets.js'; /** @typedef {import('../../lib/model/AbstractChannel.js').default} AbstractChannel */ -const { Capability } = require(`../../lib/model.js`); -const { CoarseChannel } = require(`../../lib/model.js`); +import { Capability } from '../../lib/model.js'; +import { CoarseChannel } from '../../lib/model.js'; /** @typedef {import('../../lib/model/FineChannel.js').default} FineChannel */ /** @typedef {import('../../lib/model/Fixture.js').default} Fixture */ /** @typedef {import('../../lib/model/Mode.js').default} Mode */ -const { Physical } = require(`../../lib/model.js`); -const { SwitchingChannel } = require(`../../lib/model.js`); +import { Physical } from '../../lib/model.js'; +import { SwitchingChannel } from '../../lib/model.js'; -module.exports.version = `1.3.0`; +export const version = `1.3.0`; /** * @param {Array.} fixtures An array of Fixture objects. * @param {Object} options Global options, including: * @param {String} options.baseDirectory Absolute path to OFL's root directory. * @param {Date} options.date The current time. - * @param {String|undefined} options.displayedPluginVersion Replacement for module.exports.version if the plugin version is used in export. + * @param {String|undefined} options.displayedPluginVersion Replacement for plugin version if the plugin version is used in export. * @returns {Promise., Error>} The generated files. */ -module.exports.exportFixtures = async function exportQlcPlus(fixtures, options) { +export async function exportFixtures(fixtures, options) { const customGobos = {}; const outFiles = await Promise.all(fixtures.map(async fixture => { @@ -38,7 +38,7 @@ module.exports.exportFixtures = async function exportQlcPlus(fixtures, options) '@xmlns': `http://www.qlcplus.org/FixtureDefinition`, Creator: { Name: `OFL – ${fixture.url}`, - Version: options.displayedPluginVersion || module.exports.version, + Version: options.displayedPluginVersion || version, Author: fixture.meta.authors.join(`, `), }, Manufacturer: fixture.manufacturer.name, @@ -99,7 +99,7 @@ module.exports.exportFixtures = async function exportQlcPlus(fixtures, options) } return outFiles; -}; +} /** * @param {Object} xml The xmlbuilder object. diff --git a/plugins/qlcplus_4.12.2/exportTests/fixture-tool-validation.js b/plugins/qlcplus_4.12.2/exportTests/fixture-tool-validation.js index b372a4a00c..e280e3c7a0 100644 --- a/plugins/qlcplus_4.12.2/exportTests/fixture-tool-validation.js +++ b/plugins/qlcplus_4.12.2/exportTests/fixture-tool-validation.js @@ -1,11 +1,12 @@ -const https = require(`https`); -const path = require(`path`); -const { mkdir, mkdtemp, writeFile } = require(`fs/promises`); -const os = require(`os`); -const execFile = require(`util`).promisify(require(`child_process`).execFile); - -const importJson = require(`../../../lib/import-json.js`); +import https from 'https'; +import path from 'path'; +import { mkdir, mkdtemp, writeFile } from 'fs/promises'; +import os from 'os'; +import { promisify } from 'util'; +import { execFile as execFileAsync } from 'child_process'; +import importJson from '../../../lib/import-json.js'; +const execFile = promisify(execFileAsync); const FIXTURE_TOOL_URL = `https://raw.githubusercontent.com/mcallegari/qlcplus/master/resources/fixtures/scripts/fixtures-tool.py`; const FIXTURE_TOOL_DIR_PREFIX = path.join(os.tmpdir(), `ofl-qlcplus5-fixture-tool-`); @@ -26,7 +27,7 @@ const EXPORTED_FIXTURE_PATH = `resources/fixtures/manufacturer/fixture.qxf`; * @param {Array.} allExportFiles An array of all export files. * @returns {Promise.|String>} Resolve when the test passes or reject with an array of errors or one error if the test fails. */ -module.exports = async function testFixtureToolValidation(exportFile, allExportFiles) { +export default async function testFixtureToolValidation(exportFile, allExportFiles) { if (exportFile.name.startsWith(`gobos/`)) { return; } @@ -43,7 +44,7 @@ module.exports = async function testFixtureToolValidation(exportFile, allExportF await writeFile(path.join(directory, EXPORTED_FIXTURE_PATH), exportFile.content); // store used gobos in the gobos/ directory - const qlcplusGoboAliases = await importJson(`../../../resources/gobos/aliases/qlcplus.json`, __dirname); + const qlcplusGoboAliases = await importJson(`../../../resources/gobos/aliases/qlcplus.json`, import.meta.url); const qlcplusGobos = [`gobos/Others/open.svg`, `gobos/Others/rainbow.png`].concat( Object.keys(qlcplusGoboAliases).map(gobo => `gobos/${gobo}`), allExportFiles.filter(file => file.name.startsWith(`gobos/`)).map(file => file.name), @@ -67,7 +68,7 @@ module.exports = async function testFixtureToolValidation(exportFile, allExportF if (lastLine !== `1 definitions processed. 0 errors detected`) { throw output.stdout; } -}; +} /** diff --git a/plugins/qlcplus_4.12.2/exportTests/xsd-schema-conformity.js b/plugins/qlcplus_4.12.2/exportTests/xsd-schema-conformity.js index 9b179f5efb..ef06cb0256 100644 --- a/plugins/qlcplus_4.12.2/exportTests/xsd-schema-conformity.js +++ b/plugins/qlcplus_4.12.2/exportTests/xsd-schema-conformity.js @@ -1,5 +1,5 @@ -const https = require(`https`); -const libxml = require(`libxmljs`); +import https from 'https'; +import libxml from 'libxmljs'; const SCHEMA_URL = `https://raw.githubusercontent.com/mcallegari/qlcplus/master/resources/schemas/fixture.xsd`; @@ -17,7 +17,7 @@ const SCHEMA_URL = `https://raw.githubusercontent.com/mcallegari/qlcplus/master/ * @param {Array.} allExportFiles An array of all export files. * @returns {Promise.|String>} Resolve when the test passes or reject with an array of errors or one error if the test fails. */ -module.exports = async function testSchemaConformity(exportFile, allExportFiles) { +export default async function testSchemaConformity(exportFile, allExportFiles) { if (exportFile.name.startsWith(`gobos/`)) { return; } @@ -42,4 +42,4 @@ module.exports = async function testSchemaConformity(exportFile, allExportFiles) } throw xmlDocument.validationErrors.map(error => error.message.trim()); -}; +} diff --git a/plugins/qlcplus_4.12.2/import.js b/plugins/qlcplus_4.12.2/import.js index 3f16f1978f..1a01ad134b 100644 --- a/plugins/qlcplus_4.12.2/import.js +++ b/plugins/qlcplus_4.12.2/import.js @@ -1,17 +1,17 @@ -const xml2js = require(`xml2js`); +import xml2js from 'xml2js'; -const importJson = require(`../../lib/import-json.js`); +import importJson from '../../lib/import-json.js'; -const qlcplusGoboAliasesPromise = importJson(`../../resources/gobos/aliases/qlcplus.json`, __dirname); +const qlcplusGoboAliasesPromise = importJson(`../../resources/gobos/aliases/qlcplus.json`, import.meta.url); -const { +import { getCapabilityFromChannelPreset, getCapabilityFromCapabilityPreset, capabilityPresets, importHelpers, -} = require(`./presets.js`); +} from './presets.js'; -module.exports.version = `1.1.0`; +export const version = `1.1.0`; /** * @param {Buffer} buffer The imported file. @@ -19,7 +19,7 @@ module.exports.version = `1.1.0`; * @param {String} authorName The importer's name. * @returns {Promise.} A Promise resolving to an out object */ -module.exports.importFixtures = async function importQlcPlus(buffer, filename, authorName) { +export async function importFixtures(buffer, filename, authorName) { const timestamp = new Date().toISOString().replace(/T.*/, ``); const warnings = []; @@ -36,7 +36,7 @@ module.exports.importFixtures = async function importQlcPlus(buffer, filename, a const manufacturerKey = slugify(qlcPlusFixture.Manufacturer[0]); const fixtureKey = `${manufacturerKey}/${slugify(fixture.name)}`; - const oflManufacturers = await importJson(`../../fixtures/manufacturers.json`, __dirname); + const oflManufacturers = await importJson(`../../fixtures/manufacturers.json`, import.meta.url); const manufacturers = {}; if (!(manufacturerKey in oflManufacturers)) { @@ -99,7 +99,7 @@ module.exports.importFixtures = async function importQlcPlus(buffer, filename, a [fixtureKey]: warnings, }, }; -}; +} /** * @param {Object} qlcPlusFixture The QLC+ fixture object. @@ -176,7 +176,7 @@ const slotTypeFunctions = { if (goboKey) { slot.resource = `gobos/${goboKey}`; - const resource = await importJson(`../../resources/gobos/${goboKey}.json`, __dirname); + const resource = await importJson(`../../resources/gobos/${goboKey}.json`, import.meta.url); if (resource.name === capability._) { useResourceName = true; diff --git a/plugins/qlcplus_4.12.2/presets.js b/plugins/qlcplus_4.12.2/presets.js index a471a9a22c..d631d2b729 100644 --- a/plugins/qlcplus_4.12.2/presets.js +++ b/plugins/qlcplus_4.12.2/presets.js @@ -2,14 +2,14 @@ * @fileoverview Channel and capability presets, together with functions to export or import them. */ -const importJson = require(`../../lib/import-json.js`); +import importJson from '../../lib/import-json.js'; -const qlcplusGoboAliasesPromise = importJson(`../../resources/gobos/aliases/qlcplus.json`, __dirname); +const qlcplusGoboAliasesPromise = importJson(`../../resources/gobos/aliases/qlcplus.json`, import.meta.url); // ########## Helper functions ########## -const exportHelpers = { +export const exportHelpers = { isIncreasingSpeed: capability => capability.speed !== null && Math.abs(capability.speed[0].number) < Math.abs(capability.speed[1].number), isDecreasingSpeed: capability => capability.speed !== null && Math.abs(capability.speed[0].number) > Math.abs(capability.speed[1].number), isStopped: capability => capability.speed !== null && capability.speed[0].number === 0 && capability.speed[1].number === 0, @@ -49,7 +49,7 @@ const exportHelpers = { }, }; -const importHelpers = { +export const importHelpers = { getColorIntensityCap: color => ({ type: `ColorIntensity`, color, @@ -215,7 +215,7 @@ const importHelpers = { // ########## Channel presets ########## -const channelPresets = { +export const channelPresets = { IntensityMasterDimmer: { isApplicable: capability => { const channel = capability._channel; @@ -539,7 +539,7 @@ const channelPresets = { * @param {CoarseChannel} channel The OFL channel object. * @returns {String|null} The QLC+ channel preset name or null, if there is no suitable one. */ -function getChannelPreset(channel) { +export function getChannelPreset(channel) { if (channel.capabilities.length > 1) { return null; } @@ -556,7 +556,7 @@ function getChannelPreset(channel) { * @param {Number} tiltMax The maximum tilt angle, or 0. * @returns {Object} The OFL capability object. */ -function getCapabilityFromChannelPreset(preset, channelName, panMax, tiltMax) { +export function getCapabilityFromChannelPreset(preset, channelName, panMax, tiltMax) { if (preset in channelPresets) { return channelPresets[preset].importCapability({ channelName, @@ -575,7 +575,7 @@ function getCapabilityFromChannelPreset(preset, channelName, panMax, tiltMax) { // ########## Fine channel presets ########## -const fineChannelPresets = { +export const fineChannelPresets = { IntensityMasterDimmerFine: { isApplicable: ({ coarseChannelPreset }) => coarseChannelPreset === `IntensityMasterDimmer`, }, @@ -668,7 +668,7 @@ const fineChannelPresets = { * @param {FineChannel} fineChannel The OFL fine channel object. * @returns {String|null} The QLC+ channel preset name or null, if there is no suitable one. */ -function getFineChannelPreset(fineChannel) { +export function getFineChannelPreset(fineChannel) { const coarseChannel = fineChannel.coarseChannel; const coarseChannelPreset = getChannelPreset(coarseChannel); @@ -684,7 +684,7 @@ function getFineChannelPreset(fineChannel) { // ########## Capability presets ########## -const capabilityPresets = { +export const capabilityPresets = { // shutter capabilities @@ -1033,7 +1033,7 @@ const capabilityPresets = { * @param {Capability} capability The OFL capability object. * @returns {Promise.} A Promise that resolves to the QLC+ capability preset or null, if there is no suitable one. */ -async function getCapabilityPreset(capability) { +export async function getCapabilityPreset(capability) { const foundPresetName = Object.keys(capabilityPresets).find( presetName => capabilityPresets[presetName].isApplicable(capability), ); @@ -1055,7 +1055,7 @@ async function getCapabilityPreset(capability) { * @param {Object} capabilityData Additional data about capability and channel. * @returns {Object} The OFL capability object. */ -function getCapabilityFromCapabilityPreset(preset, capabilityData) { +export function getCapabilityFromCapabilityPreset(preset, capabilityData) { if (preset in capabilityPresets) { const capability = capabilityPresets[preset].importCapability(capabilityData); @@ -1075,20 +1075,3 @@ function getCapabilityFromCapabilityPreset(preset, capabilityData) { helpWanted: `Unknown QLC+ capability preset ${preset}, Res1="${capabilityData.res1}", Res2="${capabilityData.res2}".`, }; } - - -module.exports = { - channelPresets, - getChannelPreset, - getCapabilityFromChannelPreset, - - fineChannelPresets, - getFineChannelPreset, - - capabilityPresets, - getCapabilityPreset, - getCapabilityFromCapabilityPreset, - - importHelpers, - exportHelpers, -}; diff --git a/tests/built-files-committed.js b/tests/built-files-committed.js index 732873a271..7d9f4d71bd 100755 --- a/tests/built-files-committed.js +++ b/tests/built-files-committed.js @@ -1,10 +1,10 @@ #!/usr/bin/env node -const path = require(`path`); -const chalk = require(`chalk`); -const childProcess = require(`child_process`); +import chalk from 'chalk'; +import childProcess from 'child_process'; +import { fileURLToPath } from 'url'; -const projectDirectory = path.join(__dirname, `..`); +const projectDirectory = fileURLToPath(new URL(`../`, import.meta.url)); try { childProcess.execSync(`npm run build`, { diff --git a/tests/dmx-value-scaling.js b/tests/dmx-value-scaling.js index c4abe40638..81a9472d04 100755 --- a/tests/dmx-value-scaling.js +++ b/tests/dmx-value-scaling.js @@ -1,13 +1,10 @@ #!/usr/bin/env node -const chalk = require(`chalk`); +import chalk from 'chalk'; -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign - -const { +import { scaleDmxValue, scaleDmxRange, -} = require(`../lib/scale-dmx-values.js`); +} from '../lib/scale-dmx-values.js'; let errorCount = 0; diff --git a/tests/external-links.js b/tests/external-links.js index 0afb928583..c2fd9aa970 100755 --- a/tests/external-links.js +++ b/tests/external-links.js @@ -1,18 +1,18 @@ #!/usr/bin/env node -const http = require(`http`); -const https = require(`https`); -const path = require(`path`); -const chalk = require(`chalk`); -const { Octokit } = require(`@octokit/rest`); +import http from 'http'; +import https from 'https'; +import chalk from 'chalk'; +import userAgent from 'default-user-agent'; +import { Octokit } from '@octokit/rest'; -require(`../lib/load-env-file.js`); +import '../lib/load-env-file.js'; -const USER_AGENT = require(`default-user-agent`)(); +const USER_AGENT = userAgent(); const GITHUB_COMMENT_HEADING = `## Broken links update`; const TIMEOUT = 30_000; -const SiteCrawler = require(`../lib/site-crawler.js`); +import SiteCrawler from '../lib/site-crawler.js'; const excludedUrls = [ `https://open-fixture-library.org`, // exclude canonical URLs @@ -368,8 +368,9 @@ async function updateGithubIssue(urlResults) { * @returns {String} The new issue body (in Markdown and HTML) from the given link data. */ function getBodyFromLinkData(linkData) { + const scriptName = import.meta.url.split(`/`).slice(-2).join(`/`); const lines = [ - `*Auto-generated content by \`${path.relative(path.join(__dirname, `..`), __filename)}\`.*`, + `*Auto-generated content by \`${scriptName}\`.*`, ``, `**Last updated:** ${new Date().toISOString()}`, ``, diff --git a/tests/fixture-valid.js b/tests/fixture-valid.js index a7c9b15611..7440fff9a3 100644 --- a/tests/fixture-valid.js +++ b/tests/fixture-valid.js @@ -1,25 +1,22 @@ -const { inspect } = require(`util`); +import { inspect } from 'util'; -// see https://github.com/standard-things/esm#getting-started -require = require(`esm`)(module); // eslint-disable-line no-global-assign - -const getAjvValidator = require(`../lib/ajv-validator.js`); -const schemaProperties = require(`../lib/schema-properties.js`).default; -const { manufacturerFromRepository, getResourceFromString } = require(`../lib/model.js`); -const getAjvErrorMessages = require(`../lib/get-ajv-error-messages.js`); -const importJson = require(`../lib/import-json.js`); +import getAjvValidator from '../lib/ajv-validator.js'; +import schemaProperties from '../lib/schema-properties.js'; +import { manufacturerFromRepository, getResourceFromString } from '../lib/model.js'; +import getAjvErrorMessages from '../lib/get-ajv-error-messages.js'; +import importJson from '../lib/import-json.js'; /** @typedef {import('../lib/model/AbstractChannel.js').default} AbstractChannel */ /** @typedef {import('../lib/model/Capability.js').default} Capability */ /** @typedef {import('../lib/model/CoarseChannel.js').default} CoarseChannel */ -const { FineChannel } = require(`../lib/model.js`); -const { Fixture } = require(`../lib/model.js`); +import { FineChannel } from '../lib/model.js'; +import { Fixture } from '../lib/model.js'; /** @typedef {import('../lib/model/Matrix.js').default} Matrix */ /** @typedef {import('../lib/model/Meta.js').default} Meta */ -const { NullChannel } = require(`../lib/model.js`); +import { NullChannel } from '../lib/model.js'; /** @typedef {import('../lib/model/Physical.js').default} Physical */ /** @typedef {import('../lib/model/TemplateChannel.js').default} TemplateChannel */ -const { SwitchingChannel } = require(`../lib/model.js`); +import { SwitchingChannel } from '../lib/model.js'; /** @typedef {import('../lib/model/Wheel.js').default} Wheel */ let initialized = false; @@ -34,10 +31,10 @@ let plugins; * @param {UniqueValues|null} [uniqueValues=null] Values that have to be unique are checked and all new occurrences are appended. * @returns {Promise.} A Promise that resolves to the result object containing errors and warnings, if any. */ -async function checkFixture(manufacturerKey, fixtureKey, fixtureJson, uniqueValues = null) { +export async function checkFixture(manufacturerKey, fixtureKey, fixtureJson, uniqueValues = null) { if (!initialized) { - register = await importJson(`../fixtures/register.json`, __dirname); - plugins = await importJson(`../plugins/plugins.json`, __dirname); + register = await importJson(`../fixtures/register.json`, import.meta.url); + plugins = await importJson(`../plugins/plugins.json`, import.meta.url); initialized = true; } @@ -1192,7 +1189,7 @@ async function checkFixture(manufacturerKey, fixtureKey, fixtureJson, uniqueValu * @param {ResultData} result The object to add the error message to (if any). * @param {String} messageIfNotUnique If the value is not unique, add this message to errors. */ -function checkUniqueness(set, value, result, messageIfNotUnique) { +export function checkUniqueness(set, value, result, messageIfNotUnique) { if (set.has(value.toLowerCase())) { result.errors.push(messageIfNotUnique); } @@ -1205,7 +1202,7 @@ function checkUniqueness(set, value, result, messageIfNotUnique) { * @param {*} error An error object to append to the message. * @returns {String} A string containing the message and a deep inspection of the given error object. */ -function getErrorString(description, error) { +export function getErrorString(description, error) { if (typeof error === `string`) { return `${description} ${error}`; } @@ -1229,10 +1226,3 @@ function arraysEqual(a, b) { return a.every((value, index) => value === b[index]); } - - -module.exports = { - checkFixture, - checkUniqueness, - getErrorString, -}; diff --git a/tests/fixtures-valid.js b/tests/fixtures-valid.js index 58d337a6a6..f6bbcbe6bf 100755 --- a/tests/fixtures-valid.js +++ b/tests/fixtures-valid.js @@ -1,14 +1,14 @@ #!/usr/bin/env node -const { readdir } = require(`fs/promises`); -const path = require(`path`); -const chalk = require(`chalk`); -const minimist = require(`minimist`); +import { readdir } from 'fs/promises'; +import path from 'path'; +import chalk from 'chalk'; +import minimist from 'minimist'; -const getAjvValidator = require(`../lib/ajv-validator.js`); -const getAjvErrorMessages = require(`../lib/get-ajv-error-messages.js`); -const { checkFixture, checkUniqueness } = require(`./fixture-valid.js`); -const importJson = require(`../lib/import-json.js`); +import getAjvValidator from '../lib/ajv-validator.js'; +import getAjvErrorMessages from '../lib/get-ajv-error-messages.js'; +import { checkFixture, checkUniqueness } from './fixture-valid.js'; +import importJson from '../lib/import-json.js'; const cliArguments = minimist(process.argv.slice(2), { @@ -16,10 +16,11 @@ const cliArguments = minimist(process.argv.slice(2), { alias: { h: `help`, a: `all-fixtures` }, }); +const scriptName = import.meta.url.split(`/`).pop(); const helpMessage = [ `Check validity of some/all fixtures`, - `Usage: node ${path.relative(process.cwd(), __filename)} -a | -h | fixtures [...]`, + `Usage: node ${scriptName} -a | -h | fixtures [...]`, `Options:`, ` fixtures: a list of fixtures contained in the fixtures/ directory.`, ` has to resolve to the form 'manufacturer/fixture'`, @@ -56,7 +57,7 @@ const uniqueValues = { fixShortNames: new Set(), }; -const fixtureDirectory = path.join(__dirname, `..`, `fixtures/`); +const fixtureDirectoryUrl = new URL(`../fixtures/`, import.meta.url); /** * @returns {Promise.>} A Promise that resolves to an array of result objects. @@ -65,13 +66,13 @@ async function runTests() { const promises = []; if (cliArguments.a) { - const directoryEntries = await readdir(fixtureDirectory, { withFileTypes: true }); + const directoryEntries = await readdir(fixtureDirectoryUrl, { withFileTypes: true }); const manufacturerKeys = directoryEntries.filter(entry => entry.isDirectory()).map(entry => entry.name); for (const manufacturerKey of manufacturerKeys) { - const manufacturersDirectory = path.join(fixtureDirectory, manufacturerKey); + const manufacturersDirectoryUrl = new URL(manufacturerKey, fixtureDirectoryUrl); - for (const file of await readdir(manufacturersDirectory)) { + for (const file of await readdir(manufacturersDirectoryUrl)) { if (path.extname(file) === `.json`) { const fixtureKey = path.basename(file, `.json`); promises.push(checkFixtureFile(manufacturerKey, fixtureKey)); @@ -117,7 +118,7 @@ async function checkFixtureFile(manufacturerKey, fixtureKey) { }; try { - const fixtureJson = await importJson(filename, fixtureDirectory); + const fixtureJson = await importJson(filename, fixtureDirectoryUrl); Object.assign(result, await checkFixture(manufacturerKey, fixtureKey, fixtureJson, uniqueValues)); } catch (error) { @@ -138,7 +139,7 @@ async function checkManufacturers() { }; try { - const manufacturers = await importJson(result.name, fixtureDirectory); + const manufacturers = await importJson(result.name, fixtureDirectoryUrl); const validate = await getAjvValidator(`manufacturers`); const valid = validate(manufacturers); if (!valid) { diff --git a/tests/github/export-diff.js b/tests/github/export-diff.js index 07cc3c4d91..731028b813 100755 --- a/tests/github/export-diff.js +++ b/tests/github/export-diff.js @@ -1,12 +1,10 @@ #!/usr/bin/env node -const path = require(`path`); +import diffPluginOutputs from '../../lib/diff-plugin-outputs.js'; +import importJson from '../../lib/import-json.js'; +import * as pullRequest from './pull-request.js'; -const diffPluginOutputs = require(`../../lib/diff-plugin-outputs.js`); -const importJson = require(`../../lib/import-json.js`); -const pullRequest = require(`./pull-request.js`); - -require(`../../lib/load-env-file.js`); +import '../../lib/load-env-file.js'; /** * @typedef {Object} Task @@ -26,7 +24,7 @@ require(`../../lib/load-env-file.js`); if (tasks.length === 0) { await pullRequest.updateComment({ - filename: path.relative(path.join(__dirname, `../../`), __filename), + fileUrl: new URL(import.meta.url), name: `Plugin export diff`, lines: [], }); @@ -55,7 +53,7 @@ require(`../../lib/load-env-file.js`); } await pullRequest.updateComment({ - filename: path.relative(path.join(__dirname, `../../`), __filename), + fileUrl: new URL(import.meta.url), name: `Plugin export diff`, lines, }); @@ -73,11 +71,11 @@ require(`../../lib/load-env-file.js`); * @returns {Promise.>} A Promise that resolves to an array of diff tasks to perform. */ async function getDiffTasks(changedComponents) { - const testFixtures = (await importJson(`../test-fixtures.json`, __dirname)).map( + const testFixtures = (await importJson(`../test-fixtures.json`, import.meta.url)).map( fixture => `${fixture.man}/${fixture.key}`, ); - const plugins = await importJson(`../../plugins/plugins.json`, __dirname); + const plugins = await importJson(`../../plugins/plugins.json`, import.meta.url); const usablePlugins = plugins.exportPlugins.filter( // don't diff new plugins and the ofl plugin (which essentially exports the source files) pluginKey => !changedComponents.added.exports.includes(pluginKey) && pluginKey !== `ofl`, @@ -153,7 +151,7 @@ async function getDiffTasks(changedComponents) { const addedPlugins = changedComponents.added.exports; const removedPlugins = changedComponents.removed.exports; for (const addedPlugin of addedPlugins) { - const pluginData = await importJson(`../../plugins/${addedPlugin}/plugin.json`, __dirname); + const pluginData = await importJson(`../../plugins/${addedPlugin}/plugin.json`, import.meta.url); if (pluginData.previousVersions) { const previousVersions = Object.keys(pluginData.previousVersions); diff --git a/tests/github/exports-valid.js b/tests/github/exports-valid.js index a8f98e6bf2..04f05ebe48 100644 --- a/tests/github/exports-valid.js +++ b/tests/github/exports-valid.js @@ -1,10 +1,10 @@ #!/usr/bin/env node -const path = require(`path`); +import { fileURLToPath } from 'url'; -const { fixtureFromRepository } = require(`../../lib/model.js`); -const importJson = require(`../../lib/import-json.js`); -const pullRequest = require(`./pull-request.js`); +import { fixtureFromRepository } from '../../lib/model.js'; +import importJson from '../../lib/import-json.js'; +import * as pullRequest from './pull-request.js'; let plugins; let exportTests; @@ -26,7 +26,7 @@ let testErrored = false; await pullRequest.init(); const changedComponents = await pullRequest.fetchChangedComponents(); - plugins = await importJson(`../../plugins/plugins.json`, __dirname); + plugins = await importJson(`../../plugins/plugins.json`, import.meta.url); exportTests = []; for (const exportPluginKey of plugins.exportPlugins) { @@ -37,7 +37,7 @@ let testErrored = false; )); } - testFixtures = (await importJson(`../test-fixtures.json`, __dirname)).map( + testFixtures = (await importJson(`../test-fixtures.json`, import.meta.url)).map( fixture => [fixture.man, fixture.key], ); @@ -79,7 +79,7 @@ let testErrored = false; if (tasks.length === 0) { await pullRequest.updateComment({ - filename: path.relative(path.join(__dirname, `../../`), __filename), + fileUrl: new URL(import.meta.url), name: `Export files validity`, lines: [], }); @@ -109,7 +109,7 @@ let testErrored = false; } await pullRequest.updateComment({ - filename: path.relative(path.join(__dirname, `../../`), __filename), + fileUrl: new URL(import.meta.url), name: `Export files validity`, lines, }); @@ -221,8 +221,9 @@ function getTasksForFixtures(changedComponents) { * @returns {Promise} A promise resolving with an array of message lines. */ async function getTaskPromise(task) { - const plugin = require(`../../plugins/${task.pluginKey}/export.js`); - const test = require(`../../plugins/${task.pluginKey}/exportTests/${task.testKey}.js`); + const plugin = await import(`../../plugins/${task.pluginKey}/export.js`); + const { default: test } = await import(`../../plugins/${task.pluginKey}/exportTests/${task.testKey}.js`); + let emoji = `:heavy_check_mark:`; const detailListItems = []; @@ -230,7 +231,7 @@ async function getTaskPromise(task) { const files = await plugin.exportFixtures( [await fixtureFromRepository(task.manufacturerKey, task.fixtureKey)], { - baseDirectory: path.join(__dirname, `../..`), + baseDirectory: fileURLToPath(new URL(`../../`, import.meta.url)), date: new Date(), }, ); diff --git a/tests/github/pull-request.js b/tests/github/pull-request.js index 4bf6325f18..1b902a60cb 100644 --- a/tests/github/pull-request.js +++ b/tests/github/pull-request.js @@ -1,7 +1,9 @@ -const chalk = require(`chalk`); -const { Octokit } = require(`@octokit/rest`); +import path from 'path'; +import chalk from 'chalk'; +import { Octokit } from '@octokit/rest'; +import { fileURLToPath } from 'url'; -require(`../../lib/load-env-file.js`); +import '../../lib/load-env-file.js'; const requiredEnvironmentVariables = [ `GITHUB_USER_TOKEN`, @@ -22,16 +24,20 @@ let prData; * Checks if the environment variables for GitHub operations are correct. * @returns {Promise} Rejects an error message if the environment is not correct. */ -module.exports.checkEnv = async function checkEnv() { +export async function checkEnv() { for (const environmentVariable of requiredEnvironmentVariables) { if (!(environmentVariable in process.env)) { throw `Environment variable ${environmentVariable} is required for this script. Please define it in your system or in the .env file.`; } } -}; +} -module.exports.init = async function init() { - await module.exports.checkEnv(); +/** + * Fetch data about the current pull request from the GitHub API. + * @returns {Promise} A Promise that resolves to the returned pull request data. + */ +export async function init() { + await checkEnv(); repoOwner = process.env.GITHUB_REPOSITORY.split(`/`)[0]; repoName = process.env.GITHUB_REPOSITORY.split(`/`)[1]; @@ -50,9 +56,12 @@ module.exports.init = async function init() { prData = pr.data; return pr.data; -}; +} -module.exports.fetchChangedComponents = async function fetchChangedComponents() { +/** + * @returns {Promise} A Promise that resolves to an object which describes the OFL components changed in this pull request. + */ +export async function fetchChangedComponents() { // fetch changed files in blocks of 100 const filePromises = []; for (let index = 0; index < prData.changed_files / 100; index++) { @@ -163,27 +172,30 @@ module.exports.fetchChangedComponents = async function fetchChangedComponents() ]); } } -}; +} /** * Creates a new comment in the PR if test.lines is not empty and if there is not already an exactly equal comment. - * Deletes old comments from the same test (determined by test.filename). + * Deletes old comments from the same test (determined by test.fileUrl). * @param {Object} test Information about the test script that wants to update the comment. - * @param {String} test.filename Relative path from OFL root dir to test file: 'tests/github/test-file-name.js' + * @param {URL} test.fileUrl URL of the test file. * @param {String} test.name Heading to be used in the comment * @param {Array.} test.lines The comment's lines of text * @returns {Promise} A Promise that is fulfilled as soon as all GitHub operations have finished */ -module.exports.updateComment = async function updateComment(test) { +export async function updateComment(test) { if (prData.head.repo.full_name !== prData.base.repo.full_name) { console.warn(chalk.yellow(`Warning:`), `This PR is created from a forked repository, so there is no write permission for the repo.`); return undefined; } + const oflRootPath = fileURLToPath(new URL(`../../`, import.meta.url)); + const relativeFilePath = path.relative(oflRootPath, fileURLToPath(test.fileUrl)); + const lines = [ - ``, + ``, `# ${test.name}`, - `(Output of test script \`${test.filename}\`.)`, + `(Output of test script \`${relativeFilePath}\`.)`, ``, ...test.lines, ]; @@ -240,12 +252,4 @@ module.exports.updateComment = async function updateComment(test) { } return Promise.all(promises); -}; - -module.exports.getTestFixturesMessage = function getTestFixturesMessage(fixtures) { - return [ - `Tested with the following minimal collection of [test fixtures](https://github.com/OpenLightingProject/open-fixture-library/blob/master/docs/fixture-features.md) that cover all fixture features:`, - ...fixtures.map(fixture => `- ${fixture}`), - ``, - ]; -}; +} diff --git a/tests/github/schema-version-reminder.js b/tests/github/schema-version-reminder.js index 7ad7be75f9..0549a5083e 100644 --- a/tests/github/schema-version-reminder.js +++ b/tests/github/schema-version-reminder.js @@ -1,10 +1,8 @@ #!/usr/bin/env node -const path = require(`path`); +import * as pullRequest from './pull-request.js'; -const pullRequest = require(`./pull-request.js`); - -require(`../../lib/load-env-file.js`); +import '../../lib/load-env-file.js'; (async () => { try { @@ -21,7 +19,7 @@ require(`../../lib/load-env-file.js`); } await pullRequest.updateComment({ - filename: path.relative(path.join(__dirname, `../../`), __filename), + fileUrl: new URL(import.meta.url), name: `Schema has changed`, lines, }); diff --git a/tests/http-status.js b/tests/http-status.js index 95c7d6089e..5e42779ded 100755 --- a/tests/http-status.js +++ b/tests/http-status.js @@ -1,10 +1,10 @@ #!/usr/bin/env node -const chalk = require(`chalk`); +import chalk from 'chalk'; -require(`../lib/load-env-file.js`); +import '../lib/load-env-file.js'; -const SiteCrawler = require(`../lib/site-crawler.js`); +import SiteCrawler from '../lib/site-crawler.js'; (async () => { const testStartTime = Date.now(); diff --git a/ui/api/download.js b/ui/api/download.js index 6f98af68f0..431a947c5a 100644 --- a/ui/api/download.js +++ b/ui/api/download.js @@ -1,16 +1,16 @@ -const express = require(`express`); -const JSZip = require(`jszip`); - -const { fixtureFromRepository, embedResourcesIntoFixtureJson } = require(`../../lib/model.js`); -const importJson = require(`../../lib/import-json.js`); -const Fixture = require(`../../lib/model/Fixture.js`).default; -const Manufacturer = require(`../../lib/model/Manufacturer.js`).default; -const { sendJson, sendAttachment } = require(`../../lib/server-response-helpers.js`); +import express from 'express'; +import JSZip from 'jszip'; +import { fileURLToPath } from 'url'; + +import { fixtureFromRepository, embedResourcesIntoFixtureJson } from '../../lib/model.js'; +import importJson from '../../lib/import-json.js'; +import Fixture from '../../lib/model/Fixture.js'; +import Manufacturer from '../../lib/model/Manufacturer.js'; +import { sendJson, sendAttachment } from '../../lib/server-response-helpers.js'; /** @typedef {import('http').ServerResponse} ServerResponse */ -const pluginsPromise = importJson(`../../plugins/plugins.json`, __dirname); -const registerPromise = importJson(`../../fixtures/register.json`, __dirname); - +const pluginsPromise = importJson(`../../plugins/plugins.json`, import.meta.url); +const registerPromise = importJson(`../../fixtures/register.json`, import.meta.url); /** * Instruct Express to initiate a download of one / multiple exported fixture files. @@ -22,11 +22,11 @@ const registerPromise = importJson(`../../fixtures/register.json`, __dirname); * @returns {Promise} A Promise that is resolved when the response is sent. */ async function downloadFixtures(response, pluginKey, fixtures, zipName, errorDesc) { - const plugin = require(`../../plugins/${pluginKey}/export.js`); + const plugin = await import(`../../plugins/${pluginKey}/export.js`); try { const files = await plugin.exportFixtures(fixtures, { - baseDirectory: __dirname, + baseDirectory: fileURLToPath(new URL(`../../`, import.meta.url)), date: new Date(), }); @@ -132,7 +132,7 @@ router.get(`/:manufacturerKey/:fixtureKey.:format([a-z0-9_.-]+)`, async (request if (format === `json`) { try { - const json = await importJson(`../../fixtures/${manufacturerKey}/${fixtureKey}.json`, __dirname); + const json = await importJson(`../../fixtures/${manufacturerKey}/${fixtureKey}.json`, import.meta.url); await embedResourcesIntoFixtureJson(json); sendJson(response, json); } @@ -157,4 +157,4 @@ router.get(`/:manufacturerKey/:fixtureKey.:format([a-z0-9_.-]+)`, async (request downloadFixtures(response, format, fixtures, zipName, errorDesc); }); -module.exports = router; +export default router; diff --git a/ui/api/index.js b/ui/api/index.js index 7a4b24c823..f662c5a2dd 100644 --- a/ui/api/index.js +++ b/ui/api/index.js @@ -1,11 +1,12 @@ -const express = require(`express`); -const chalk = require(`chalk`); -const cors = require(`cors`); -const OpenAPIBackend = require(`openapi-backend`).default; -const getAjvErrorMessages = require(`../../lib/get-ajv-error-messages.js`); -const { sendJson } = require(`../../lib/server-response-helpers.js`); +import express from 'express'; +import chalk from 'chalk'; +import cors from 'cors'; +import { fileURLToPath } from 'url'; +import { OpenAPIBackend } from 'openapi-backend'; +import getAjvErrorMessages from '../../lib/get-ajv-error-messages.js'; +import { sendJson } from '../../lib/server-response-helpers.js'; -const routeHandlers = require(`./routes.js`); +import * as routeHandlers from './routes.js'; /** * @typedef {Object} ApiResponse @@ -42,7 +43,7 @@ app.use(cors({ const base64Regex = /^(?:[\d+/A-Za-z]{4})*(?:[\d+/A-Za-z]{2}==|[\d+/A-Za-z]{3}=)?$/; const api = new OpenAPIBackend({ - definition: `${__dirname}/openapi.json`, + definition: fileURLToPath(new URL(`openapi.json`, import.meta.url)), strict: process.env.NODE_ENV !== `production`, ajvOpts: { formats: { @@ -122,4 +123,4 @@ app.use(async (request, response) => { sendJson(response, body); }); -module.exports = app; +export default app; diff --git a/ui/api/routes.js b/ui/api/routes.js index 8fa3add09d..6472785858 100644 --- a/ui/api/routes.js +++ b/ui/api/routes.js @@ -1,11 +1,9 @@ -module.exports = { - ...require(`./routes/get-search-results.js`), - ...require(`./routes/submit-feedback.js`), - ...require(`./routes/fixtures/from-editor.js`), - ...require(`./routes/fixtures/import.js`), - ...require(`./routes/fixtures/submit.js`), - ...require(`./routes/manufacturers/index.js`), - ...require(`./routes/manufacturers/_manufacturerKey.js`), - ...require(`./routes/plugins/index.js`), - ...require(`./routes/plugins/_pluginKey.js`), -}; +export { getSearchResults } from './routes/get-search-results.js'; +export { createFeedbackIssue } from './routes/submit-feedback.js'; +export { createFixtureFromEditor } from './routes/fixtures/from-editor.js'; +export { importFixtureFile } from './routes/fixtures/import.js'; +export { submitFixtures } from './routes/fixtures/submit.js'; +export { getManufacturers } from './routes/manufacturers/index.js'; +export { getManufacturerByKey } from './routes/manufacturers/_manufacturerKey.js'; +export { getPlugins } from './routes/plugins/index.js'; +export { getPluginByKey } from './routes/plugins/_pluginKey.js'; diff --git a/ui/api/routes/fixtures/from-editor.js b/ui/api/routes/fixtures/from-editor.js index 041b6771a1..3c4cf235cd 100644 --- a/ui/api/routes/fixtures/from-editor.js +++ b/ui/api/routes/fixtures/from-editor.js @@ -1,7 +1,7 @@ -const schemaProperties = require(`../../../../lib/schema-properties.js`).default; -const { checkFixture } = require(`../../../../tests/fixture-valid.js`); -const { CoarseChannel } = require(`../../../../lib/model.js`); -const importJson = require(`../../../../lib/import-json.js`); +import schemaProperties from '../../../../lib/schema-properties.js'; +import { checkFixture } from '../../../../tests/fixture-valid.js'; +import { CoarseChannel } from '../../../../lib/model.js'; +import importJson from '../../../../lib/import-json.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -12,7 +12,7 @@ const importJson = require(`../../../../lib/import-json.js`); * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {Promise.} The handled response. */ -async function createFixtureFromEditor({ request }) { +export async function createFixtureFromEditor({ request }) { try { const fixtureCreateResult = await getFixtureCreateResult(request.requestBody); return { @@ -43,7 +43,7 @@ async function getFixtureCreateResult(fixtures) { errors: {}, }; - const manufacturers = await importJson(`../../../../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../../../../fixtures/manufacturers.json`, import.meta.url); // { 'uuid 1': 'new channel key 1', ... } const channelKeyMapping = {}; @@ -433,5 +433,3 @@ function getComboboxInput(property, from) { function slugify(string) { return string.toLowerCase().replace(/[^\da-z-]+/g, ` `).trim().replace(/\s+/g, `-`); } - -module.exports = { createFixtureFromEditor }; diff --git a/ui/api/routes/fixtures/import.js b/ui/api/routes/fixtures/import.js index 22dd4e90cf..92b8eed3d6 100644 --- a/ui/api/routes/fixtures/import.js +++ b/ui/api/routes/fixtures/import.js @@ -1,5 +1,5 @@ -const importJson = require(`../../../../lib/import-json.js`); -const { checkFixture } = require(`../../../../tests/fixture-valid.js`); +import importJson from '../../../../lib/import-json.js'; +import { checkFixture } from '../../../../tests/fixture-valid.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -18,7 +18,7 @@ const { checkFixture } = require(`../../../../tests/fixture-valid.js`); * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {ApiResponse} The handled response. */ -async function importFixtureFile({ request }) { +export async function importFixtureFile({ request }) { try { const fixtureCreateResult = await importFixture(request.requestBody); return { @@ -42,13 +42,13 @@ async function importFixtureFile({ request }) { * @returns {FixtureCreateResult} The imported fixtures (and manufacturers) with warnings and errors. */ async function importFixture(body) { - const { importPlugins } = await importJson(`../../../../plugins/plugins.json`, __dirname); + const { importPlugins } = await importJson(`../../../../plugins/plugins.json`, import.meta.url); if (!body.plugin || !importPlugins.includes(body.plugin)) { throw new Error(`'${body.plugin}' is not a valid import plugin.`); } - const plugin = require(`../../../../plugins/${body.plugin}/import.js`); + const plugin = await import(`../../../../plugins/${body.plugin}/import.js`); const { manufacturers, fixtures, warnings } = await plugin.importFixtures( Buffer.from(body.fileContentBase64, `base64`), body.fileName, @@ -66,7 +66,7 @@ async function importFixture(body) { errors: {}, }; - const oflManufacturers = await importJson(`../../../../fixtures/manufacturers.json`, __dirname); + const oflManufacturers = await importJson(`../../../../fixtures/manufacturers.json`, import.meta.url); for (const [key, fixture] of Object.entries(result.fixtures)) { const [manufacturerKey, fixtureKey] = key.split(`/`); @@ -83,5 +83,3 @@ async function importFixture(body) { return result; } - -module.exports = { importFixtureFile }; diff --git a/ui/api/routes/fixtures/submit.js b/ui/api/routes/fixtures/submit.js index 4adea1ef55..17153215eb 100644 --- a/ui/api/routes/fixtures/submit.js +++ b/ui/api/routes/fixtures/submit.js @@ -1,4 +1,4 @@ -const createPullRequest = require(`../../../../lib/create-github-pr.js`); +import createPullRequest from '../../../../lib/create-github-pr.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -17,7 +17,7 @@ const createPullRequest = require(`../../../../lib/create-github-pr.js`); * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {ApiResponse} The handled response. */ -async function submitFixtures({ request }) { +export async function submitFixtures({ request }) { try { const pullRequestUrl = await createPullRequest( request.requestBody.fixtureCreateResult, @@ -40,5 +40,3 @@ async function submitFixtures({ request }) { }; } } - -module.exports = { submitFixtures }; diff --git a/ui/api/routes/get-search-results.js b/ui/api/routes/get-search-results.js index 3f025ebe3d..5fc0d7969a 100644 --- a/ui/api/routes/get-search-results.js +++ b/ui/api/routes/get-search-results.js @@ -1,4 +1,4 @@ -const importJson = require(`../../../lib/import-json.js`); +import importJson from '../../../lib/import-json.js'; let register; let manufacturers; @@ -11,11 +11,11 @@ let manufacturers; * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {Promise.} The handled response. */ -async function getSearchResults({ request }) { +export async function getSearchResults({ request }) { const { searchQuery, manufacturersQuery, categoriesQuery } = request.requestBody; - register = await importJson(`../../../fixtures/register.json`, __dirname); - manufacturers = await importJson(`../../../fixtures/manufacturers.json`, __dirname); + register = await importJson(`../../../fixtures/register.json`, import.meta.url); + manufacturers = await importJson(`../../../fixtures/manufacturers.json`, import.meta.url); const results = Object.keys(register.filesystem).filter( key => queryMatch(searchQuery, key) && manufacturerMatch(manufacturersQuery, key) && categoryMatch(categoriesQuery, key), @@ -65,5 +65,3 @@ function categoryMatch(categoriesQuery, fixtureKey) { cat => cat in register.categories && register.categories[cat].includes(fixtureKey), ); } - -module.exports = { getSearchResults }; diff --git a/ui/api/routes/manufacturers/_manufacturerKey.js b/ui/api/routes/manufacturers/_manufacturerKey.js index da5bad3eb4..69e2406758 100644 --- a/ui/api/routes/manufacturers/_manufacturerKey.js +++ b/ui/api/routes/manufacturers/_manufacturerKey.js @@ -1,4 +1,4 @@ -const importJson = require(`../../../../lib/import-json.js`); +import importJson from '../../../../lib/import-json.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -8,10 +8,10 @@ const importJson = require(`../../../../lib/import-json.js`); * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {Promise.} The handled response. */ -async function getManufacturerByKey({ request }) { +export async function getManufacturerByKey({ request }) { const { manufacturerKey } = request.params; - const manufacturers = await importJson(`../../../../fixtures/manufacturers.json`, __dirname); + const manufacturers = await importJson(`../../../../fixtures/manufacturers.json`, import.meta.url); if (!(manufacturerKey in manufacturers) || manufacturerKey === `$schema`) { return { statusCode: 404, @@ -21,7 +21,7 @@ async function getManufacturerByKey({ request }) { }; } - const register = await importJson(`../../../../fixtures/register.json`, __dirname); + const register = await importJson(`../../../../fixtures/register.json`, import.meta.url); const manufacturer = Object.assign({}, manufacturers[manufacturerKey], { key: manufacturerKey, color: register.colors[manufacturerKey], @@ -40,6 +40,3 @@ async function getManufacturerByKey({ request }) { body: manufacturer, }; } - - -module.exports = { getManufacturerByKey }; diff --git a/ui/api/routes/manufacturers/index.js b/ui/api/routes/manufacturers/index.js index f099b3c22b..2faf6da56a 100644 --- a/ui/api/routes/manufacturers/index.js +++ b/ui/api/routes/manufacturers/index.js @@ -1,4 +1,4 @@ -const importJson = require(`../../../../lib/import-json.js`); +import importJson from '../../../../lib/import-json.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -8,9 +8,9 @@ const importJson = require(`../../../../lib/import-json.js`); * @param {OpenApiBackendContext} context Passed from OpenAPI Backend. * @returns {Promise.} The handled response. */ -async function getManufacturers(context) { - const manufacturers = await importJson(`../../../../fixtures/manufacturers.json`, __dirname); - const register = await importJson(`../../../../fixtures/register.json`, __dirname); +export async function getManufacturers(context) { + const manufacturers = await importJson(`../../../../fixtures/manufacturers.json`, import.meta.url); + const register = await importJson(`../../../../fixtures/register.json`, import.meta.url); const manufacturerData = {}; @@ -28,6 +28,3 @@ async function getManufacturers(context) { body: manufacturerData, }; } - - -module.exports = { getManufacturers }; diff --git a/ui/api/routes/plugins/_pluginKey.js b/ui/api/routes/plugins/_pluginKey.js index 9996c5863d..9e80bf463d 100644 --- a/ui/api/routes/plugins/_pluginKey.js +++ b/ui/api/routes/plugins/_pluginKey.js @@ -1,4 +1,4 @@ -const importJson = require(`../../../../lib/import-json.js`); +import importJson from '../../../../lib/import-json.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -8,10 +8,10 @@ const importJson = require(`../../../../lib/import-json.js`); * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {Promise.} The handled response. */ -async function getPluginByKey({ request }) { +export async function getPluginByKey({ request }) { let { pluginKey } = request.params; - const plugins = await importJson(`../../../../plugins/plugins.json`, __dirname); + const plugins = await importJson(`../../../../plugins/plugins.json`, import.meta.url); if (!(pluginKey in plugins.data)) { return { @@ -26,7 +26,7 @@ async function getPluginByKey({ request }) { pluginKey = plugins.data[pluginKey].newPlugin; } - const pluginData = await importJson(`../../../../plugins/${pluginKey}/plugin.json`, __dirname); + const pluginData = await importJson(`../../../../plugins/${pluginKey}/plugin.json`, import.meta.url); return { body: { @@ -44,6 +44,3 @@ async function getPluginByKey({ request }) { }, }; } - - -module.exports = { getPluginByKey }; diff --git a/ui/api/routes/plugins/index.js b/ui/api/routes/plugins/index.js index 86465fef7e..f0e725f109 100644 --- a/ui/api/routes/plugins/index.js +++ b/ui/api/routes/plugins/index.js @@ -1,4 +1,4 @@ -const importJson = require(`../../../../lib/import-json.js`); +import importJson from '../../../../lib/import-json.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../../index.js').ApiResponse} ApiResponse */ @@ -8,13 +8,10 @@ const importJson = require(`../../../../lib/import-json.js`); * @param {OpenApiBackendContext} context Passed from OpenAPI Backend. * @returns {Promise.} The handled response. */ -async function getPlugins(context) { - const plugins = await importJson(`../../../../plugins/plugins.json`, __dirname); +export async function getPlugins(context) { + const plugins = await importJson(`../../../../plugins/plugins.json`, import.meta.url); return { body: plugins, }; } - - -module.exports = { getPlugins }; diff --git a/ui/api/routes/submit-feedback.js b/ui/api/routes/submit-feedback.js index dc6c604001..4682cd9e9f 100644 --- a/ui/api/routes/submit-feedback.js +++ b/ui/api/routes/submit-feedback.js @@ -1,5 +1,5 @@ -const createIssue = require(`../../../lib/create-github-issue.js`); -const { fixtureFromRepository } = require(`../../../lib/model.js`); +import createIssue from '../../../lib/create-github-issue.js'; +import { fixtureFromRepository } from '../../../lib/model.js'; /** @typedef {import('openapi-backend').Context} OpenApiBackendContext */ /** @typedef {import('../index.js').ApiResponse} ApiResponse */ @@ -9,7 +9,7 @@ const { fixtureFromRepository } = require(`../../../lib/model.js`); * @param {OpenApiBackendContext} ctx Passed from OpenAPI Backend. * @returns {ApiResponse} The handled response. */ -async function createFeedbackIssue({ request }) { +export async function createFeedbackIssue({ request }) { const { type, context, @@ -71,5 +71,3 @@ async function createFeedbackIssue({ request }) { }, }; } - -module.exports = { createFeedbackIssue }; diff --git a/ui/assets/icons/icons.js b/ui/assets/icons/icons.js index 680ab1e5e4..b8b33ea1ae 100644 --- a/ui/assets/icons/icons.js +++ b/ui/assets/icons/icons.js @@ -1,5 +1,6 @@ // read all SVG files in this directory (and subdirectories) into icons object // see https://webpack.js.org/guides/dependency-management/#requirecontext +// eslint-disable-next-line unicorn/prefer-module const resolve = require.context(`.`, true, /\.svg$/); const getIconPath = key => key.match(/^\.\/(.+)\.svg$/)[1]; diff --git a/ui/components/A11yDialog.vue b/ui/components/A11yDialog.vue index fc22d88644..90858fdc35 100644 --- a/ui/components/A11yDialog.vue +++ b/ui/components/A11yDialog.vue @@ -151,8 +151,8 @@ export default { watch: { shown: `update`, }, - mounted() { - const A11yDialog = require(`a11y-dialog`).default; + async mounted() { + const { default: A11yDialog } = await import(`a11y-dialog`); this.dialog = new A11yDialog(this.$el); diff --git a/ui/components/editor/EditorSubmitDialog.vue b/ui/components/editor/EditorSubmitDialog.vue index 5b88eb5943..f8229fc3e6 100644 --- a/ui/components/editor/EditorSubmitDialog.vue +++ b/ui/components/editor/EditorSubmitDialog.vue @@ -193,8 +193,8 @@