diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 9a7f82536..000000000 --- a/.eslintignore +++ /dev/null @@ -1,11 +0,0 @@ -**/.greenwood/** -**/public/** -**/node_modules/** -!.eslintrc.cjs -!.mocharc.js -packages/**/test/cases/**/adapter-output/** -packages/init/src/template/** -packages/init/test/cases/**/output/** -packages/init/test/cases/**/my-app/** -packages/plugin-babel/test/cases/**/*main.js -TODO.md \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index dce41cebc..000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,240 +0,0 @@ -// need this custom parser configuration until ESLint natively supports import attributes -// https://github.com/eslint/eslint/discussions/15305#discussioncomment-2508948 -module.exports = { - parser: '@babel/eslint-parser', - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - requireConfigFile: false, - ecmaFeatures: { - jsx: true - }, - babelOptions: { - plugins: [ - '@babel/plugin-syntax-import-assertions' - ], - presets: ['@babel/preset-react'] - } - }, - plugins: [ - 'no-only-tests' - ], - // plugin does not seem to work well with custom parsers? - // https://github.com/eslint/eslint-plugin-markdown/discussions/221 - // extends: 'plugin:markdown/recommended-legacy', - env: { - browser: true, - node: false - }, - rules: { - 'comma-dangle': [2, 'never'], - 'no-cond-assign': 2, - 'no-console': 0, - 'no-constant-condition': 2, - 'no-control-regex': 0, - 'no-debugger': 0, - 'no-dupe-args': 0, - 'no-dupe-keys': 0, - 'no-duplicate-case': 2, - 'no-empty-character-class': 0, - 'no-empty': 2, - 'no-ex-assign': 2, - 'no-extra-boolean-cast': 2, - 'no-extra-parens': [2, 'all', { - 'conditionalAssign': false, - 'returnAssign': false, - 'nestedBinaryExpressions': false - }], - 'no-extra-semi': 2, - 'no-func-assign': 2, - 'no-inner-declarations': 2, - 'no-invalid-regexp': 0, - 'no-irregular-whitespace': 2, - 'no-negated-in-lhs': 2, - 'no-obj-calls': 0, - 'no-only-tests/no-only-tests': 2, - 'no-regex-spaces': 0, - 'no-sparse-arrays': 2, - 'no-unreachable': 2, - 'use-isnan': 2, - 'valid-jsdoc': 0, - 'valid-typeof': 0, - 'no-unexpected-multiline': 0, - 'accessor-pairs': 2, - 'block-scoped-var': 2, - 'complexity': 2, - 'consistent-return': 0, - 'curly': 2, - 'default-case': 2, - 'dot-notation': 2, - 'dot-location': 0, - 'eqeqeq': [2, 'allow-null'], - 'guard-for-in': 0, - 'no-alert': 0, - 'no-caller': 0, - 'no-div-regex': 0, - 'no-else-return': 0, - 'no-empty-label': 0, - 'no-eq-null': 0, - 'no-eval': 2, - 'no-extend-native': 0, - 'no-extra-bind': 2, - 'no-fallthrough': 2, - 'no-floating-decimal': 2, - 'no-implicit-coercion': [2, { - 'number': true, - 'string': true, - 'boolean': false - }], - 'no-implied-eval': 2, - 'no-invalid-this': 0, - 'no-iterator': 2, - 'no-labels': 0, - 'no-lone-blocks': 0, - 'no-loop-func': 2, - 'no-multi-spaces': 2, - 'no-multi-str': 0, - 'no-native-reassign': 0, - 'no-new-func': 0, - 'no-new-wrappers': 2, - 'no-new': 2, - 'no-octal-escape': 0, - 'no-octal': 0, - 'no-param-reassign': 0, - 'no-process-env': 0, - 'no-proto': 0, - 'no-redeclare': 2, - 'no-return-assign': 0, - 'no-script-url': 0, - 'no-self-compare': 0, - 'no-sequences': 0, - 'no-throw-literal': 2, - 'no-unused-expressions': 0, - 'no-useless-call': 0, - 'no-void': 0, - 'no-warning-comments': [1, { - 'terms': [ - 'todo', - ' fixme', - ' TODO', - ' FIXME' - ], - 'location': 'anywhere' - }], - 'no-with': 0, - 'radix': 2, - 'vars-on-top': 2, - 'wrap-iife': [2, 'inside'], - 'yoda': 0, - 'strict': [2, 'global'], - 'init-declarations': 0, - 'no-catch-shadow': 2, - 'no-delete-var': 2, - 'no-label-var': 0, - 'no-shadow-restricted-names': 0, - 'no-shadow': 0, - 'no-undef-init': 0, - 'no-undef': 0, - 'no-undefined': 0, - 'no-unused-vars': 2, - 'no-use-before-define': 0, - 'callback-return': 0, - 'handle-callback-err': 2, - 'no-mixed-requires': 0, - 'no-new-require': 0, - 'no-path-concat': 2, - 'no-process-exit': 2, - 'no-restricted-modules': 0, - 'no-sync': 0, - 'array-bracket-spacing': 2, - 'brace-style': [2, '1tbs', { - 'allowSingleLine': true - }], - 'camelcase': 2, - 'comma-spacing': 2, - 'comma-style': [2, 'last'], - 'computed-property-spacing': 0, - 'consistent-this': [0, 'self', 'that'], - 'eol-last': [2, 'never'], - 'func-names': 0, - 'func-style': 0, - 'id-length': 0, - 'indent': [2, 2, { - 'VariableDeclarator': 1, - 'SwitchCase': 1, - 'ignoredNodes': [ - 'TemplateLiteral' - ] - }], - 'key-spacing': [2, { - 'beforeColon': false, - 'afterColon': true - }], - 'lines-around-comment': 0, - 'linebreak-style': 0, - 'max-nested-callbacks': [2, { 'maximum': 8 }], - 'new-cap': 2, - 'new-parens': 2, - 'no-array-constructor': 2, - 'no-continue': 0, - 'no-inline-comments': 0, - 'no-lonely-if': 0, - 'no-mixed-spaces-and-tabs': [2, 'smart-tabs'], - 'no-multiple-empty-lines': [2, { 'max': 1 }], - 'no-nested-ternary': 0, - 'no-new-object': 2, - 'no-spaced-func': 2, - 'no-ternary': 0, - 'no-trailing-spaces': 2, - 'no-underscore-dangle': [2, { 'allowAfterThis': true }], - 'no-unneeded-ternary': 2, - 'object-curly-spacing': [2, 'always', {}], - 'one-var': 0, - 'operator-assignment': 0, - 'operator-linebreak': 0, - 'padded-blocks': [2, { 'switches': 'always' }], - 'quote-props': [2, 'consistent'], - 'quotes': [2, 'single', 'avoid-escape'], - 'id-match': 0, - 'semi-spacing': [2, { 'after': true }], - 'semi': [2, 'always'], - 'sort-vars': 0, - 'keyword-spacing': 2, - 'space-before-blocks': 2, - 'space-before-function-paren': 0, - 'space-in-parens': 2, - 'space-infix-ops': 2, - 'space-return-throw-case': 0, - 'space-unary-ops': 0, - 'spaced-comment': [2, 'always', { - 'line': { - 'markers': ['/'], - 'exceptions': ['-', '+'] - }, - 'block': { - 'markers': ['!'], - 'exceptions': ['*'] - } - }], - 'wrap-regex': 2, - 'arrow-parens': 0, - 'arrow-spacing': 0, - 'constructor-super': 0, - 'generator-star-spacing': 0, - 'no-class-assign': 0, - 'no-const-assign': 0, - 'no-this-before-super': 0, - 'no-var': 0, - 'object-shorthand': 0, - 'prefer-const': 0, - 'prefer-spread': 0, - 'prefer-reflect': 0, - 'require-yield': 0, - 'max-depth': [2, 4], - 'max-len': [2, 200, 1, { 'ignorePattern': 'true' }], - 'max-params': 0, - 'max-statements': 0, - 'no-bitwise': [2, { 'allow': ['~'] }], - 'no-plusplus': 2 - } -}; \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96cea8048..166df8d09 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -133,12 +133,15 @@ Test cases that exercise custom loaders (like TypeScript, JSX plugins) for SSR a 1. Prefix the test case directory and spec file with _loaders-_ 1. Make sure to pass `true` as the second param to `Runner` ```js + import { Runner } from 'gallinago'; + let runner; + before(function() { - this.context = { - publicDir: path.join(outputPath, 'public') - }; + // pass true as the second param here runner = new Runner(false, true); }); + + runner.runCommand(/* ... */); ``` 1. Use the `yarn test:loaders` npm script diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..737438351 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,70 @@ +import babelParser from '@babel/eslint-parser'; +import markdown from '@eslint/markdown'; +import json from '@eslint/json'; +import js from '@eslint/js'; +import globals from 'globals'; +import noOnlyTests from 'eslint-plugin-no-only-tests'; + +export default [ + { + // https://github.com/eslint/eslint/discussions/18304#discussioncomment-9069706 + ignores: [ + '.greenwood/*', + 'node_modules/*', + 'public/*', + 'reports/*', + 'coverage/*', + // 'packages/plugin-graphql/README.md', + 'www/**' + ], + }, + { + languageOptions: { + parser: babelParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + requireConfigFile: false, + babelOptions: { + plugins: ['@babel/plugin-syntax-import-assertions', '@babel/plugin-syntax-jsx'], + }, + }, + globals: { + ...globals.browser, + ...globals.mocha, + ...globals.chai, + ...globals.node, + }, + }, + rules: { + ...js.configs.recommended.rules, + // turn this off for Prettier + 'no-irregular-whitespace': 'off', + 'no-only-tests/no-only-tests': 'error', + }, + plugins: { + 'no-only-tests': noOnlyTests, + }, + }, + { + // https://github.com/eslint/json#recommended-configuration + files: ['**/*.json'], + ignores: ['package-lock.json'], + language: 'json/json', + rules: json.configs.recommended.rules, + plugins: { + json, + }, + }, + { + // note: we can only lint code fences, _or_ the markdown files themselves + // so for now we will just lint the code fences + // https://github.com/eslint/markdown/blob/main/docs/processors/markdown.md#using-the-markdown-processor + files: ['**/*.md'], + processor: 'markdown/markdown', + plugins: { + markdown, + }, + language: 'markdown/gfm', + }, +]; \ No newline at end of file diff --git a/package.json b/package.json index 4444e172a..f778d621e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "scripts": { "lerna": "lerna", - "clean": "rimraf ./**/.greenwood/** && rimraf ./**/public/** && rimraf ./coverage", + "clean": "rimraf --glob ./**/.greenwood/** ./**/public/** ./coverage", "clean:deps": "rimraf **/node_modules/**", "build": "cross-env __GWD_ROLLUP_MODE__=strict node . build", "serve": "node . serve", @@ -24,32 +24,28 @@ "test:loaders": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 node --loader $(pwd)/test/test-loader.js ./node_modules/mocha/bin/mocha \"./packages/**/**/*.spec.js\"", "test:loaders:win": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=true __GWD_ROLLUP_MODE__=strict NODE_NO_WARNINGS=1 node --loader file:\\\\%cd%\\test\\test-loader.js ./node_modules/mocha/bin/mocha --exclude \"./packages/init/test/cases/**\" \"./packages/**/**/*.spec.js\"", "test:tdd": "yarn test --watch", - "lint:js": "eslint \"*.js\" \"./packages/**/**/*.js\" \"./test/*.js\" \"./www/**/**/*.js\"", - "lint:ts": "eslint \"./packages/**/**/*.ts\"", - "lint:css": "stylelint \"./www/**/*.js\", \"./www/**/*.css\"", - "lint": "ls-lint && yarn lint:js && yarn lint:css" + "lint": "ls-lint && eslint" }, "devDependencies": { "@babel/core": "^7.24.4", - "@babel/eslint-parser": "^7.24.1", - "@babel/plugin-syntax-import-assertions": "^7.24.1", - "@babel/preset-react": "^7.24.1", + "@babel/eslint-parser": "^7.25.7", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@eslint/js": "^9.11.1", + "@eslint/json": "^0.5.0", + "@eslint/markdown": "^6.2.0", "@ls-lint/ls-lint": "^1.10.0", - "babel-eslint": "^10.1.0", "c8": "^7.10.0", "chai": "^4.2.0", "cross-env": "^7.0.3", - "eslint": "^8.51.0", - "eslint-plugin-markdown": "^3.0.0", + "eslint": "^9.11.1", "eslint-plugin-no-only-tests": "^2.6.0", "gallinago": "^0.8.2", "glob-promise": "^3.4.0", + "globals": "^15.10.0", "jsdom": "^16.5.0", "lerna": "^3.16.4", "mocha": "^9.1.3", - "rimraf": "^2.6.3", - "stylelint": "^13.8.0", - "stylelint-a11y": "^1.2.3", - "stylelint-config-standard": "^20.0.0" + "rimraf": "^5.0.10" } } diff --git a/packages/cli/src/commands/build.js b/packages/cli/src/commands/build.js index 56fdeb952..47a653d20 100644 --- a/packages/cli/src/commands/build.js +++ b/packages/cli/src/commands/build.js @@ -8,6 +8,7 @@ import { ServerInterface } from '../lib/server-interface.js'; const runProductionBuild = async (compilation) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { diff --git a/packages/cli/src/commands/develop.js b/packages/cli/src/commands/develop.js index 3c28226c0..de2729b1e 100644 --- a/packages/cli/src/commands/develop.js +++ b/packages/cli/src/commands/develop.js @@ -3,6 +3,7 @@ import { getDevServer } from '../lifecycles/serve.js'; const runDevServer = async (compilation) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { diff --git a/packages/cli/src/commands/eject.js b/packages/cli/src/commands/eject.js index 9786331c0..7195a0566 100644 --- a/packages/cli/src/commands/eject.js +++ b/packages/cli/src/commands/eject.js @@ -1,6 +1,7 @@ import fs from 'fs/promises'; const ejectConfiguration = async (compilation) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { const configFileDirUrl = new URL('../config/', import.meta.url); diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index d40983ad1..ab0c0ce0b 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -3,6 +3,7 @@ import { checkResourceExists } from '../lib/resource-utils.js'; const runProdServer = async (compilation) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { diff --git a/packages/cli/src/config/rollup.config.js b/packages/cli/src/config/rollup.config.js index 585f7de53..998819249 100644 --- a/packages/cli/src/config/rollup.config.js +++ b/packages/cli/src/config/rollup.config.js @@ -1,4 +1,3 @@ -/* eslint-disable complexity, max-depth */ import fs from 'fs'; import path from 'path'; import { checkResourceExists, normalizePathnameForWindows } from '../lib/resource-utils.js'; @@ -16,7 +15,7 @@ function cleanRollupId(id) { const externalizedResources = ['css', 'json']; function greenwoodResourceLoader (compilation, browser = false) { - const { importAttributes } = compilation.config?.polyfills; + const { importAttributes } = compilation.config.polyfills ?? {}; const resourcePlugins = compilation.config.plugins.filter((plugin) => { return plugin.type === 'resource'; }).map((plugin) => { @@ -612,7 +611,7 @@ const getRollupConfigForBrowserScripts = async (compilation) => { break; case 'UNRESOLVED_IMPORT': // this could be a legit warning for users, but... - if (process.env.__GWD_ROLLUP_MODE__ === 'strict') { // eslint-disable-line no-underscore-dangle + if (process.env.__GWD_ROLLUP_MODE__ === 'strict') { // if we see it happening in our tests / website build // treat it as an error for us since it usually is... // https://github.com/ProjectEvergreen/greenwood/issues/620 diff --git a/packages/cli/src/data/client.js b/packages/cli/src/data/client.js index 50cc34dc1..eb510ec85 100644 --- a/packages/cli/src/data/client.js +++ b/packages/cli/src/data/client.js @@ -1,9 +1,9 @@ import { filterContentByCollection, filterContentByRoute } from '@greenwood/cli/src/lib/content-utils.js'; -const CONTENT_STATE = globalThis.__CONTENT_AS_DATA_STATE__ ?? false; // eslint-disable-line no-underscore-dangle -const PRERENDER = globalThis.__CONTENT_OPTIONS__?.PRERENDER === 'true'; // eslint-disable-line no-underscore-dangle -const PORT = globalThis?.__CONTENT_OPTIONS__?.PORT ?? 1984; // eslint-disable-line no-underscore-dangle -const BASE_PATH = globalThis?.__GWD_BASE_PATH__ ?? ''; // eslint-disable-line no-underscore-dangle +const CONTENT_STATE = globalThis.__CONTENT_AS_DATA_STATE__ ?? false; +const PRERENDER = globalThis.__CONTENT_OPTIONS__?.PRERENDER === 'true'; +const PORT = globalThis?.__CONTENT_OPTIONS__?.PORT ?? 1984; +const BASE_PATH = globalThis?.__GWD_BASE_PATH__ ?? ''; async function getContentAsData(key = '') { if (CONTENT_STATE && PRERENDER) { diff --git a/packages/cli/src/index.js b/packages/cli/src/index.js index a928d6a4d..2947b00ca 100755 --- a/packages/cli/src/index.js +++ b/packages/cli/src/index.js @@ -1,6 +1,5 @@ #!/usr/bin/env node -/* eslint-disable no-underscore-dangle */ import { generateCompilation } from './lifecycles/compile.js'; import fs from 'fs/promises'; import program from 'commander'; @@ -88,10 +87,10 @@ const run = async() => { break; } - process.exit(0); // eslint-disable-line no-process-exit + process.exit(0); } catch (err) { console.error(err); - process.exit(1); // eslint-disable-line no-process-exit + process.exit(1); } }; diff --git a/packages/cli/src/lib/api-route-worker.js b/packages/cli/src/lib/api-route-worker.js index 4af5fabc5..417134251 100644 --- a/packages/cli/src/lib/api-route-worker.js +++ b/packages/cli/src/lib/api-route-worker.js @@ -4,7 +4,7 @@ import { transformKoaRequestIntoStandardRequest } from './resource-utils.js'; // based on https://stackoverflow.com/questions/57447685/how-can-i-convert-a-request-object-into-a-stringifiable-object-in-javascript async function responseAsObject (response) { - if (!response instanceof Response) { + if (!(response instanceof Response)) { throw Object.assign( new Error(), { name: 'TypeError', message: 'Argument must be a Response object' } diff --git a/packages/cli/src/lib/hashing-utils.js b/packages/cli/src/lib/hashing-utils.js index e758e5ba9..21e2c1991 100644 --- a/packages/cli/src/lib/hashing-utils.js +++ b/packages/cli/src/lib/hashing-utils.js @@ -3,7 +3,7 @@ function hashString(inputString) { let h = 0; for (let i = 0; i < inputString.length; i += 1) { - h = Math.imul(31, h) + inputString.charCodeAt(i) | 0; // eslint-disable-line no-bitwise + h = Math.imul(31, h) + inputString.charCodeAt(i) | 0; } return Math.abs(h).toString(); diff --git a/packages/cli/src/lib/layout-utils.js b/packages/cli/src/lib/layout-utils.js index 530bdd557..c5a31c0e9 100644 --- a/packages/cli/src/lib/layout-utils.js +++ b/packages/cli/src/lib/layout-utils.js @@ -1,4 +1,3 @@ -/* eslint-disable complexity */ import fs from 'fs/promises'; import htmlparser from 'node-html-parser'; import { checkResourceExists } from './resource-utils.js'; @@ -74,6 +73,7 @@ async function getPageLayout(pageHref = '', compilation, layout) { const routeModuleLocationUrl = new URL(`./${layout}.js`, userLayoutsDir); const routeWorkerUrl = compilation.config.plugins.find(plugin => plugin.type === 'renderer').provider().executeModuleUrl; + // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('./ssr-route-worker.js', import.meta.url)); @@ -107,7 +107,6 @@ async function getPageLayout(pageHref = '', compilation, layout) { return contents; } -/* eslint-disable-next-line complexity */ async function getAppLayout(pageLayoutContents, compilation, customImports = [], matchingRoute) { const activeFrontmatterTitleKey = '${globalThis.page.title}'; const enableHud = compilation.config.devServer.hud; @@ -122,6 +121,7 @@ async function getAppLayout(pageLayoutContents, compilation, customImports = [], if (userHasDynamicAppLayout) { const routeWorkerUrl = compilation.config.plugins.find(plugin => plugin.type === 'renderer').provider().executeModuleUrl; + // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('./ssr-route-worker.js', import.meta.url)); diff --git a/packages/cli/src/lib/resource-utils.js b/packages/cli/src/lib/resource-utils.js index 7c8e1984e..c916775e4 100644 --- a/packages/cli/src/lib/resource-utils.js +++ b/packages/cli/src/lib/resource-utils.js @@ -81,7 +81,7 @@ async function checkResourceExists(url) { try { await fs.access(url); return true; - } catch (e) { + } catch { return false; } } @@ -212,7 +212,7 @@ function transformKoaRequestIntoStandardRequest(url, request) { // https://stackoverflow.com/questions/57447685/how-can-i-convert-a-request-object-into-a-stringifiable-object-in-javascript async function requestAsObject (_request) { - if (!_request instanceof Request) { + if (!(_request instanceof Request)) { throw Object.assign( new Error(), { name: 'TypeError', message: 'Argument must be a Request object' } diff --git a/packages/cli/src/lib/router.js b/packages/cli/src/lib/router.js index ba792a728..cff88d569 100644 --- a/packages/cli/src/lib/router.js +++ b/packages/cli/src/lib/router.js @@ -1,5 +1,3 @@ -/* eslint-disable no-underscore-dangle */ - document.addEventListener('click', async function(e) { const currentUrl = window.location; // https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath diff --git a/packages/cli/src/lib/walker-package-ranger.js b/packages/cli/src/lib/walker-package-ranger.js index 1abad09a8..be977fa03 100644 --- a/packages/cli/src/lib/walker-package-ranger.js +++ b/packages/cli/src/lib/walker-package-ranger.js @@ -1,6 +1,5 @@ import fs from 'fs'; -/* eslint-disable max-depth,complexity */ // priority if from L -> R const SUPPORTED_EXPORT_CONDITIONS = ['import', 'module-sync', 'default']; const IMPORT_MAP_RESOLVED_PREFIX = '/~'; diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js index 0ed305af8..76fc63a87 100644 --- a/packages/cli/src/lifecycles/bundle.js +++ b/packages/cli/src/lifecycles/bundle.js @@ -1,4 +1,3 @@ -/* eslint-disable max-depth, max-len */ import fs from 'fs/promises'; import { getRollupConfigForApiRoutes, getRollupConfigForBrowserScripts, getRollupConfigForSsrPages } from '../config/rollup.config.js'; import { getAppLayout, getPageLayout, getUserScripts } from '../lib/layout-utils.js'; @@ -318,6 +317,7 @@ async function bundleSsrPages(compilation, optimizePlugins) { } // better way to write out this inline code? + /* eslint-disable no-useless-escape */ await fs.writeFile(entryFileOutputUrl, ` import { executeRouteModule } from '${normalizePathnameForWindows(executeModuleUrl)}'; @@ -340,6 +340,7 @@ async function bundleSsrPages(compilation, optimizePlugins) { }); } `); + /* eslint-enable no-useless-escape */ input.push({ id, @@ -372,6 +373,7 @@ async function bundleScriptResources(compilation) { const bundleCompilation = async (compilation) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { const optimizeResourcePlugins = compilation.config.plugins.filter((plugin) => { diff --git a/packages/cli/src/lifecycles/compile.js b/packages/cli/src/lifecycles/compile.js index 68ce2d0dc..229fd8dc0 100644 --- a/packages/cli/src/lifecycles/compile.js +++ b/packages/cli/src/lifecycles/compile.js @@ -5,6 +5,7 @@ import { readAndMergeConfig } from './config.js'; import fs from 'fs/promises'; const generateCompilation = () => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { @@ -32,7 +33,7 @@ const generateCompilation = () => { await fs.mkdir(scratchDir); } - if (process.env.__GWD_COMMAND__ === 'serve') { // eslint-disable-line no-underscore-dangle + if (process.env.__GWD_COMMAND__ === 'serve') { console.info('Loading graph from build output...'); if (!await checkResourceExists(new URL('./graph.json', outputDir))) { diff --git a/packages/cli/src/lifecycles/config.js b/packages/cli/src/lifecycles/config.js index 37b0621a8..e77cee37a 100644 --- a/packages/cli/src/lifecycles/config.js +++ b/packages/cli/src/lifecycles/config.js @@ -60,7 +60,7 @@ const defaultConfig = { }; const readAndMergeConfig = async() => { - // eslint-disable-next-line complexity + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { // deep clone of default config @@ -81,7 +81,6 @@ const readAndMergeConfig = async() => { if (hasConfigFile) { const userCfgFile = (await import(configUrl)).default; - // eslint-disable-next-line max-len const { workspace, devServer, markdown, optimization, plugins, port, prerender, basePath, staticRouter, pagesDirectory, layoutsDirectory, activeContent, isolation, polyfills } = userCfgFile; // workspace validation @@ -151,7 +150,7 @@ const readAndMergeConfig = async() => { if (devServer && Object.keys(devServer).length > 0) { - if (devServer.hasOwnProperty('hud')) { + if (Object.prototype.hasOwnProperty.call(devServer, "hud")) { if (typeof devServer.hud === 'boolean') { customConfig.devServer.hud = devServer.hud; } else { @@ -160,7 +159,6 @@ const readAndMergeConfig = async() => { } if (devServer.port) { - // eslint-disable-next-line max-depth if (!Number.isInteger(devServer.port)) { reject(`Error: greenwood.config.js devServer port must be an integer. Passed value was: ${devServer.port}`); } else { @@ -187,7 +185,6 @@ const readAndMergeConfig = async() => { } if (port) { - // eslint-disable-next-line max-depth if (!Number.isInteger(port)) { reject(`Error: greenwood.config.js port must be an integer. Passed value was: ${port}`); } else { @@ -196,7 +193,6 @@ const readAndMergeConfig = async() => { } if (basePath) { - // eslint-disable-next-line max-depth if (typeof basePath !== 'string') { reject(`Error: greenwood.config.js basePath must be a string. Passed value was: ${basePath}`); } else { diff --git a/packages/cli/src/lifecycles/context.js b/packages/cli/src/lifecycles/context.js index e4f45b564..311a446bf 100644 --- a/packages/cli/src/lifecycles/context.js +++ b/packages/cli/src/lifecycles/context.js @@ -3,6 +3,7 @@ import { checkResourceExists } from '../lib/resource-utils.js'; const initContext = async({ config }) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { const { workspace, pagesDirectory, layoutsDirectory } = config; diff --git a/packages/cli/src/lifecycles/graph.js b/packages/cli/src/lifecycles/graph.js index b791501df..6ad2896a0 100644 --- a/packages/cli/src/lifecycles/graph.js +++ b/packages/cli/src/lifecycles/graph.js @@ -1,4 +1,3 @@ -/* eslint-disable complexity, max-depth */ import fs from 'fs/promises'; import fm from 'front-matter'; import { checkResourceExists, requestAsObject } from '../lib/resource-utils.js'; @@ -32,6 +31,7 @@ function getIdFromRelativePathPath(relativePathPath, extension) { const generateGraph = async (compilation) => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { const { context, config } = compilation; @@ -163,6 +163,7 @@ const generateGraph = async (compilation) => { const routeWorkerUrl = compilation.config.plugins.filter(plugin => plugin.type === 'renderer')[0].provider(compilation).executeModuleUrl; let ssrFrontmatter; + // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('../lib/ssr-route-worker.js', import.meta.url)); const request = await requestAsObject(new Request(filenameUrl)); diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index 8a1ba11df..978d6004a 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -166,7 +166,7 @@ async function getDevServer(compilation) { // don't interfere with external requests or API calls, only files // and only run in development - if (process.env.__GWD_COMMAND__ === 'develop' && url.protocol === 'file:') { // eslint-disable-line no-underscore-dangle + if (process.env.__GWD_COMMAND__ === 'develop' && url.protocol === 'file:') { // there's probably a better way to do this with tee-ing streams but this works for now const { header, status, message } = ctx.response; const response = new Response(ctx.body, { @@ -188,7 +188,6 @@ async function getDevServer(compilation) { ctx.set('Cache-Control', 'no-cache'); } else if (!inm || inm !== etagHash) { ctx.body = Readable.from(response.body); - ctx.status = ctx.status; ctx.set('Etag', etagHash); ctx.message = response.statusText; response.headers.forEach((value, key) => { @@ -334,6 +333,7 @@ async function getHybridServer(compilation) { let html; if (matchingRoute.isolation || isolationMode) { + // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('../lib/ssr-route-worker-isolation-mode.js', import.meta.url)); // "faux" new Request here, a better way? @@ -373,6 +373,7 @@ async function getHybridServer(compilation) { let body, status, headers, statusText; if (apiRoute.isolation || isolationMode) { + // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('../lib/api-route-worker.js', import.meta.url)); // "faux" new Request here, a better way? diff --git a/packages/cli/src/plugins/resource/plugin-active-content.js b/packages/cli/src/plugins/resource/plugin-active-content.js index f1e8767d6..008370543 100644 --- a/packages/cli/src/plugins/resource/plugin-active-content.js +++ b/packages/cli/src/plugins/resource/plugin-active-content.js @@ -44,7 +44,7 @@ class ContentAsDataResource extends ResourceInterface { body = filterContentByRoute(graph, keyPieces[1]); } - if (process.env.__GWD_COMMAND__ === 'build') { // eslint-disable-line no-underscore-dangle + if (process.env.__GWD_COMMAND__ === 'build') { const fileKey = `./data-${contentKey.replace(/\//g, '_')}.json`; if (!await checkResourceExists(new URL(fileKey, this.compilation.context.outputDir))) { @@ -73,7 +73,7 @@ class ContentAsDataResource extends ResourceInterface { const body = await response.text(); let newBody = body; - if (process.env.__GWD_COMMAND__ === 'develop') { // eslint-disable-line no-underscore-dangle + if (process.env.__GWD_COMMAND__ === 'develop') { newBody = mergeImportMap(body, importMap, polyfills.importMaps); } diff --git a/packages/cli/src/plugins/resource/plugin-api-routes.js b/packages/cli/src/plugins/resource/plugin-api-routes.js index 6db1656cd..bcf554245 100644 --- a/packages/cli/src/plugins/resource/plugin-api-routes.js +++ b/packages/cli/src/plugins/resource/plugin-api-routes.js @@ -23,10 +23,11 @@ class ApiRoutesResource extends ResourceInterface { const apiUrl = new URL(api.pageHref); const href = apiUrl.href; - if (process.env.__GWD_COMMAND__ === 'develop') { // eslint-disable-line no-underscore-dangle + if (process.env.__GWD_COMMAND__ === 'develop') { const workerUrl = new URL('../../lib/api-route-worker.js', import.meta.url); const req = await requestAsObject(request); + // eslint-disable-next-line no-async-promise-executor const response = await new Promise(async (resolve, reject) => { const worker = new Worker(workerUrl); diff --git a/packages/cli/src/plugins/resource/plugin-node-modules.js b/packages/cli/src/plugins/resource/plugin-node-modules.js index ff22e43e4..1af45b5d9 100644 --- a/packages/cli/src/plugins/resource/plugin-node-modules.js +++ b/packages/cli/src/plugins/resource/plugin-node-modules.js @@ -64,12 +64,12 @@ class NodeModulesResource extends ResourceInterface { const { importMaps } = config.polyfills; const importMapShimScript = importMaps ? '' : ''; let body = await response.text(); - const hasHead = body.match(/\
(.*)<\/head>/s); + const hasHead = body.match(/(.*)<\/head>/s); if (importMaps && hasHead && hasHead.length > 0) { const contents = hasHead[0].replace(/type="module"/g, 'type="module-shim"'); - body = body.replace(/\(.*)<\/head>/s, contents.replace(/\$/g, '$$$')); // https://github.com/ProjectEvergreen/greenwood/issues/656); + body = body.replace(/(.*)<\/head>/s, contents.replace(/\$/g, '$$$')); // https://github.com/ProjectEvergreen/greenwood/issues/656); } const userPackageJson = await getPackageJsonForProject(context); diff --git a/packages/cli/src/plugins/resource/plugin-standard-css.js b/packages/cli/src/plugins/resource/plugin-standard-css.js index 332586de7..57234244a 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-css.js +++ b/packages/cli/src/plugins/resource/plugin-standard-css.js @@ -23,7 +23,7 @@ function bundleCss(body, sourceUrl, compilation, workingUrl) { let optimizedCss = ''; walk(ast, { - enter: function (node, item) { // eslint-disable-line complexity + enter: function (node, item) { const { type, name, value, children } = node; if ((type === 'String' || type === 'Url') && this.atrulePrelude && this.atrule.name === 'import') { @@ -82,7 +82,7 @@ function bundleCss(body, sourceUrl, compilation, workingUrl) { : new URL(`${urlPrefix}${value}`, sourceUrl); if (fs.existsSync(resolvedUrl)) { - const isDev = process.env.__GWD_COMMAND__ === 'develop'; // eslint-disable-line no-underscore-dangle + const isDev = process.env.__GWD_COMMAND__ === 'develop'; let finalValue = ''; if (resolvedUrl.href.startsWith(userWorkspace.href)) { @@ -179,8 +179,6 @@ function bundleCss(body, sourceUrl, compilation, workingUrl) { optimizedCss += ` (${name}:`; } else if (type === 'Parentheses' || type === 'SupportsDeclaration') { optimizedCss += '('; - } else if (type === 'PseudoElementSelector') { - optimizedCss += `::${name}`; } else if (type === 'MediaQuery') { // https://github.com/csstree/csstree/issues/285#issuecomment-2350230333 const { mediaType, modifier } = node; @@ -219,9 +217,7 @@ function bundleCss(body, sourceUrl, compilation, workingUrl) { } } else if (type === 'Declaration') { optimizedCss += `${node.property}:`; - } else if (type === 'Url' && this.atrule?.name !== 'import') { - optimizedCss += `url('${node.value}')`; - } else if (type === 'Identifier' || type === 'Hash' || type === 'Dimension' || type === 'Number' || (type === 'String' && (this.atrule?.type !== 'import')) || type === 'Operator' || type === 'Raw' || type === 'Percentage') { // eslint-disable-line max-len + } else if (type === 'Identifier' || type === 'Hash' || type === 'Dimension' || type === 'Number' || (type === 'String' && (this.atrule?.type !== 'import')) || type === 'Operator' || type === 'Raw' || type === 'Percentage') { if (item && item.prev && type !== 'Operator' && item.prev.data.type !== 'Operator') { optimizedCss += ' '; } @@ -258,7 +254,7 @@ function bundleCss(body, sourceUrl, compilation, workingUrl) { } } }, - leave: function(node, item) { // eslint-disable-line complexity + leave: function(node, item) { switch (node.type) { case 'Atrule': diff --git a/packages/cli/src/plugins/resource/plugin-standard-html.js b/packages/cli/src/plugins/resource/plugin-standard-html.js index 1639ba971..737db1255 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-html.js +++ b/packages/cli/src/plugins/resource/plugin-standard-html.js @@ -1,4 +1,3 @@ -/* eslint-disable complexity, max-depth */ /* * * Manages web standard resource related operations for HTML and markdown. @@ -86,6 +85,7 @@ class StandardHtmlResource extends ResourceInterface { const routeModuleLocationUrl = new URL(pageHref); const routeWorkerUrl = this.compilation.config.plugins.find(plugin => plugin.type === 'renderer').provider().executeModuleUrl; + // eslint-disable-next-line no-async-promise-executor await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('../../lib/ssr-route-worker.js', import.meta.url)); @@ -142,11 +142,11 @@ class StandardHtmlResource extends ResourceInterface { } // https://github.com/ProjectEvergreen/greenwood/issues/1126 - body = body.replace(/\