diff --git a/.eslintrc.json b/.eslintrc.json index 553dba0c4a..78f9b4b623 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,7 +20,7 @@ "settings": { "import/resolver": { "webpack": { - "config": "./webpack.config.js" + "config": "./webpack.config.cjs" } } }, diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index a79cfb5249..224b1b49e0 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -43,7 +43,7 @@ jobs: LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }} - name: Bump version - run: script/version_bump.js nightly + run: script/version_bump.cjs nightly - name: Build nightly Python wheels run: | diff --git a/build-scripts/babel-plugins/inline-constants-plugin.js b/build-scripts/babel-plugins/inline-constants-plugin.cjs similarity index 100% rename from build-scripts/babel-plugins/inline-constants-plugin.js rename to build-scripts/babel-plugins/inline-constants-plugin.cjs diff --git a/build-scripts/bundle.js b/build-scripts/bundle.cjs similarity index 98% rename from build-scripts/bundle.js rename to build-scripts/bundle.cjs index fd4070ea59..801a766932 100644 --- a/build-scripts/bundle.js +++ b/build-scripts/bundle.cjs @@ -1,6 +1,6 @@ const path = require("path"); -const env = require("./env.js"); -const paths = require("./paths.js"); +const env = require("./env.cjs"); +const paths = require("./paths.cjs"); // GitHub base URL to use for production source maps // Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version @@ -99,7 +99,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({ [ path.resolve( paths.polymer_dir, - "build-scripts/babel-plugins/inline-constants-plugin.js" + "build-scripts/babel-plugins/inline-constants-plugin.cjs" ), { modules: ["@mdi/js"], diff --git a/build-scripts/env.js b/build-scripts/env.cjs similarity index 95% rename from build-scripts/env.js rename to build-scripts/env.cjs index 034e069181..bb0d6b3d00 100644 --- a/build-scripts/env.js +++ b/build-scripts/env.cjs @@ -1,6 +1,6 @@ const fs = require("fs"); const path = require("path"); -const paths = require("./paths.js"); +const paths = require("./paths.cjs"); module.exports = { useRollup() { diff --git a/build-scripts/gulp/app.js b/build-scripts/gulp/app.cjs similarity index 74% rename from build-scripts/gulp/app.js rename to build-scripts/gulp/app.cjs index f97a210930..0b6c49354c 100644 --- a/build-scripts/gulp/app.js +++ b/build-scripts/gulp/app.cjs @@ -1,18 +1,18 @@ // Run HA develop mode const gulp = require("gulp"); -const env = require("../env"); -require("./clean.js"); -require("./translations.js"); -require("./locale-data.js"); -require("./gen-icons-json.js"); -require("./gather-static.js"); -require("./compress.js"); -require("./webpack.js"); -require("./service-worker.js"); -require("./entry-html.js"); -require("./rollup.js"); -require("./wds.js"); +const env = require("../env.cjs"); +require("./clean.cjs"); +require("./translations.cjs"); +require("./locale-data.cjs"); +require("./gen-icons-json.cjs"); +require("./gather-static.cjs"); +require("./compress.cjs"); +require("./webpack.cjs"); +require("./service-worker.cjs"); +require("./entry-html.cjs"); +require("./rollup.cjs"); +require("./wds.cjs"); gulp.task( "develop-app", diff --git a/build-scripts/gulp/cast.js b/build-scripts/gulp/cast.cjs similarity index 77% rename from build-scripts/gulp/cast.js rename to build-scripts/gulp/cast.cjs index 3623cc9925..4dbc9b1eff 100644 --- a/build-scripts/gulp/cast.js +++ b/build-scripts/gulp/cast.cjs @@ -1,14 +1,13 @@ const gulp = require("gulp"); +const env = require("../env.cjs"); -const env = require("../env"); - -require("./clean.js"); -require("./translations.js"); -require("./gather-static.js"); -require("./webpack.js"); -require("./service-worker.js"); -require("./entry-html.js"); -require("./rollup.js"); +require("./clean.cjs"); +require("./translations.cjs"); +require("./gather-static.cjs"); +require("./webpack.cjs"); +require("./service-worker.cjs"); +require("./entry-html.cjs"); +require("./rollup.cjs"); gulp.task( "develop-cast", diff --git a/build-scripts/gulp/clean.js b/build-scripts/gulp/clean.cjs similarity index 92% rename from build-scripts/gulp/clean.js rename to build-scripts/gulp/clean.cjs index 726e932ced..1dbeca11a3 100644 --- a/build-scripts/gulp/clean.js +++ b/build-scripts/gulp/clean.cjs @@ -1,7 +1,7 @@ const del = import("del"); const gulp = require("gulp"); -const paths = require("../paths"); -require("./translations"); +const paths = require("../paths.cjs"); +require("./translations.cjs"); gulp.task( "clean", diff --git a/build-scripts/gulp/compress.js b/build-scripts/gulp/compress.cjs similarity index 97% rename from build-scripts/gulp/compress.js rename to build-scripts/gulp/compress.cjs index d247d0d1c9..73d4090de3 100644 --- a/build-scripts/gulp/compress.js +++ b/build-scripts/gulp/compress.cjs @@ -4,7 +4,7 @@ const gulp = require("gulp"); const zopfli = require("gulp-zopfli-green"); const merge = require("merge-stream"); const path = require("path"); -const paths = require("../paths"); +const paths = require("../paths.cjs"); const zopfliOptions = { threshold: 150 }; diff --git a/build-scripts/gulp/demo.js b/build-scripts/gulp/demo.cjs similarity index 77% rename from build-scripts/gulp/demo.js rename to build-scripts/gulp/demo.cjs index 25f1670d26..65d8035c66 100644 --- a/build-scripts/gulp/demo.js +++ b/build-scripts/gulp/demo.cjs @@ -1,16 +1,15 @@ // Run demo develop mode const gulp = require("gulp"); +const env = require("../env.cjs"); -const env = require("../env"); - -require("./clean.js"); -require("./translations.js"); -require("./gen-icons-json.js"); -require("./gather-static.js"); -require("./webpack.js"); -require("./service-worker.js"); -require("./entry-html.js"); -require("./rollup.js"); +require("./clean.cjs"); +require("./translations.cjs"); +require("./gen-icons-json.cjs"); +require("./gather-static.cjs"); +require("./webpack.cjs"); +require("./service-worker.cjs"); +require("./entry-html.cjs"); +require("./rollup.cjs"); gulp.task( "develop-demo", diff --git a/build-scripts/gulp/download_translations.js b/build-scripts/gulp/download_translations.cjs similarity index 100% rename from build-scripts/gulp/download_translations.js rename to build-scripts/gulp/download_translations.cjs diff --git a/build-scripts/gulp/entry-html.js b/build-scripts/gulp/entry-html.cjs similarity index 99% rename from build-scripts/gulp/entry-html.js rename to build-scripts/gulp/entry-html.cjs index 14ead700c9..ffb569f7ed 100644 --- a/build-scripts/gulp/entry-html.js +++ b/build-scripts/gulp/entry-html.cjs @@ -4,9 +4,9 @@ const fs = require("fs-extra"); const path = require("path"); const template = require("lodash.template"); const { minify } = require("html-minifier-terser"); -const paths = require("../paths.js"); -const env = require("../env.js"); -const { htmlMinifierOptions, terserOptions } = require("../bundle.js"); +const paths = require("../paths.cjs"); +const env = require("../env.cjs"); +const { htmlMinifierOptions, terserOptions } = require("../bundle.cjs"); const templatePath = (tpl) => path.resolve(paths.polymer_dir, "src/html/", `${tpl}.html.template`); diff --git a/build-scripts/gulp/fetch-nightly-translations.js b/build-scripts/gulp/fetch-nightly-translations.cjs similarity index 100% rename from build-scripts/gulp/fetch-nightly-translations.js rename to build-scripts/gulp/fetch-nightly-translations.cjs diff --git a/build-scripts/gulp/gallery.js b/build-scripts/gulp/gallery.cjs similarity index 92% rename from build-scripts/gulp/gallery.js rename to build-scripts/gulp/gallery.cjs index a1529ff7ec..25b53332ce 100644 --- a/build-scripts/gulp/gallery.js +++ b/build-scripts/gulp/gallery.cjs @@ -6,17 +6,17 @@ const { marked } = require("marked"); const glob = require("glob"); const yaml = require("js-yaml"); -const env = require("../env"); -const paths = require("../paths"); +const env = require("../env.cjs"); +const paths = require("../paths.cjs"); -require("./clean.js"); -require("./translations.js"); -require("./gen-icons-json.js"); -require("./gather-static.js"); -require("./webpack.js"); -require("./service-worker.js"); -require("./entry-html.js"); -require("./rollup.js"); +require("./clean.cjs"); +require("./translations.cjs"); +require("./gen-icons-json.cjs"); +require("./gather-static.cjs"); +require("./webpack.cjs"); +require("./service-worker.cjs"); +require("./entry-html.cjs"); +require("./rollup.cjs"); gulp.task("gather-gallery-pages", async function gatherPages() { const pageDir = path.resolve(paths.gallery_dir, "src/pages"); @@ -89,9 +89,7 @@ gulp.task("gather-gallery-pages", async function gatherPages() { // Generate sidebar const sidebarPath = path.resolve(paths.gallery_dir, "sidebar.js"); - // To make watch work during development - delete require.cache[sidebarPath]; - const sidebar = require(sidebarPath); + const sidebar = (await import(sidebarPath)).default; const pagesToProcess = {}; for (const key of processed) { diff --git a/build-scripts/gulp/gather-static.js b/build-scripts/gulp/gather-static.cjs similarity index 99% rename from build-scripts/gulp/gather-static.js rename to build-scripts/gulp/gather-static.cjs index 306ae3158a..fe1ed0e443 100644 --- a/build-scripts/gulp/gather-static.js +++ b/build-scripts/gulp/gather-static.cjs @@ -3,7 +3,7 @@ const gulp = require("gulp"); const path = require("path"); const fs = require("fs-extra"); -const paths = require("../paths"); +const paths = require("../paths.cjs"); const npmPath = (...parts) => path.resolve(paths.polymer_dir, "node_modules", ...parts); diff --git a/build-scripts/gulp/gen-icons-json.js b/build-scripts/gulp/gen-icons-json.cjs similarity index 97% rename from build-scripts/gulp/gen-icons-json.js rename to build-scripts/gulp/gen-icons-json.cjs index 8a69ba97af..44dafc3a7a 100644 --- a/build-scripts/gulp/gen-icons-json.js +++ b/build-scripts/gulp/gen-icons-json.cjs @@ -134,11 +134,11 @@ gulp.task("gen-icons-json", (done) => { }); const file = fs.readFileSync(PACKAGE_PATH, { encoding }); - const package = JSON.parse(file); + const packageMeta = JSON.parse(file); fs.writeFileSync( path.resolve(OUTPUT_DIR, "iconMetadata.json"), - JSON.stringify({ version: package.version, parts }) + JSON.stringify({ version: packageMeta.version, parts }) ); fs.writeFileSync( diff --git a/build-scripts/gulp/hassio.js b/build-scripts/gulp/hassio.cjs similarity index 78% rename from build-scripts/gulp/hassio.js rename to build-scripts/gulp/hassio.cjs index e1bfcb86e6..562ed3b646 100644 --- a/build-scripts/gulp/hassio.js +++ b/build-scripts/gulp/hassio.cjs @@ -1,13 +1,13 @@ const gulp = require("gulp"); -const env = require("../env"); -require("./clean.js"); -require("./gen-icons-json.js"); -require("./webpack.js"); -require("./compress.js"); -require("./rollup.js"); -require("./gather-static.js"); -require("./translations.js"); -require("./gen-icons-json.js"); +const env = require("../env.cjs"); +require("./clean.cjs"); +require("./compress.cjs"); +require("./entry-html.cjs"); +require("./gather-static.cjs"); +require("./gen-icons-json.cjs"); +require("./rollup.cjs"); +require("./translations.cjs"); +require("./webpack.cjs"); gulp.task( "develop-hassio", diff --git a/build-scripts/gulp/locale-data.js b/build-scripts/gulp/locale-data.cjs similarity index 98% rename from build-scripts/gulp/locale-data.js rename to build-scripts/gulp/locale-data.cjs index 328ddccf31..00bf705f43 100755 --- a/build-scripts/gulp/locale-data.js +++ b/build-scripts/gulp/locale-data.cjs @@ -2,7 +2,7 @@ const del = import("del"); const path = require("path"); const gulp = require("gulp"); const fs = require("fs"); -const paths = require("../paths"); +const paths = require("../paths.cjs"); const outDir = "build/locale-data"; diff --git a/build-scripts/gulp/rollup.js b/build-scripts/gulp/rollup.cjs similarity index 97% rename from build-scripts/gulp/rollup.js rename to build-scripts/gulp/rollup.cjs index fb16127eb0..8637ff8879 100644 --- a/build-scripts/gulp/rollup.js +++ b/build-scripts/gulp/rollup.cjs @@ -6,8 +6,8 @@ const handler = require("serve-handler"); const http = require("http"); const log = require("fancy-log"); const open = require("open"); -const rollupConfig = require("../rollup"); -const paths = require("../paths"); +const rollupConfig = require("../rollup.cjs"); +const paths = require("../paths.cjs"); const bothBuilds = (createConfigFunc, params) => gulp.series( @@ -46,7 +46,7 @@ function createServer(serveOptions) { ); } -function watchRollup(createConfig, extraWatchSrc = [], serveOptions) { +function watchRollup(createConfig, extraWatchSrc = [], serveOptions = null) { const { inputOptions, outputOptions } = createConfig({ isProdBuild: false, latestBuild: true, diff --git a/build-scripts/gulp/service-worker.js b/build-scripts/gulp/service-worker.cjs similarity index 98% rename from build-scripts/gulp/service-worker.js rename to build-scripts/gulp/service-worker.cjs index 05b4cd39aa..c32c4226c8 100644 --- a/build-scripts/gulp/service-worker.js +++ b/build-scripts/gulp/service-worker.cjs @@ -5,7 +5,7 @@ const path = require("path"); const fs = require("fs-extra"); const workboxBuild = require("workbox-build"); const sourceMapUrl = require("source-map-url"); -const paths = require("../paths.js"); +const paths = require("../paths.cjs"); const swDest = path.resolve(paths.app_output_root, "service_worker.js"); diff --git a/build-scripts/gulp/translations.js b/build-scripts/gulp/translations.cjs similarity index 98% rename from build-scripts/gulp/translations.js rename to build-scripts/gulp/translations.cjs index d3f9b7e1d2..bfa76891dc 100755 --- a/build-scripts/gulp/translations.js +++ b/build-scripts/gulp/translations.cjs @@ -9,11 +9,11 @@ const flatmap = require("gulp-flatmap"); const merge = require("gulp-merge-json"); const rename = require("gulp-rename"); const transform = require("gulp-json-transform"); -const { mapFiles } = require("../util"); -const env = require("../env"); -const paths = require("../paths"); +const { mapFiles } = require("../util.cjs"); +const env = require("../env.cjs"); +const paths = require("../paths.cjs"); -require("./fetch-nightly-translations"); +require("./fetch-nightly-translations.cjs"); const inFrontendDir = "translations/frontend"; const inBackendDir = "translations/backend"; diff --git a/build-scripts/gulp/wds.js b/build-scripts/gulp/wds.cjs similarity index 100% rename from build-scripts/gulp/wds.js rename to build-scripts/gulp/wds.cjs diff --git a/build-scripts/gulp/webpack.js b/build-scripts/gulp/webpack.cjs similarity index 97% rename from build-scripts/gulp/webpack.js rename to build-scripts/gulp/webpack.cjs index ed9fdb3ba6..a82dc29f04 100644 --- a/build-scripts/gulp/webpack.js +++ b/build-scripts/gulp/webpack.cjs @@ -5,15 +5,15 @@ const webpack = require("webpack"); const WebpackDevServer = require("webpack-dev-server"); const log = require("fancy-log"); const path = require("path"); -const env = require("../env"); -const paths = require("../paths"); +const env = require("../env.cjs"); +const paths = require("../paths.cjs"); const { createAppConfig, createDemoConfig, createCastConfig, createHassioConfig, createGalleryConfig, -} = require("../webpack"); +} = require("../webpack.cjs"); const bothBuilds = (createConfigFunc, params) => [ createConfigFunc({ ...params, latestBuild: true }), diff --git a/build-scripts/paths.js b/build-scripts/paths.cjs similarity index 100% rename from build-scripts/paths.js rename to build-scripts/paths.cjs diff --git a/build-scripts/rollup-plugins/dont-hash-plugin.js b/build-scripts/rollup-plugins/dont-hash-plugin.cjs similarity index 100% rename from build-scripts/rollup-plugins/dont-hash-plugin.js rename to build-scripts/rollup-plugins/dont-hash-plugin.cjs diff --git a/build-scripts/rollup-plugins/ignore-plugin.js b/build-scripts/rollup-plugins/ignore-plugin.cjs similarity index 100% rename from build-scripts/rollup-plugins/ignore-plugin.js rename to build-scripts/rollup-plugins/ignore-plugin.cjs diff --git a/build-scripts/rollup-plugins/manifest-plugin.js b/build-scripts/rollup-plugins/manifest-plugin.cjs similarity index 100% rename from build-scripts/rollup-plugins/manifest-plugin.js rename to build-scripts/rollup-plugins/manifest-plugin.cjs diff --git a/build-scripts/rollup-plugins/worker-plugin.js b/build-scripts/rollup-plugins/worker-plugin.cjs similarity index 98% rename from build-scripts/rollup-plugins/worker-plugin.js rename to build-scripts/rollup-plugins/worker-plugin.cjs index 5706475d24..007d5eadb8 100644 --- a/build-scripts/rollup-plugins/worker-plugin.js +++ b/build-scripts/rollup-plugins/worker-plugin.cjs @@ -103,7 +103,7 @@ module.exports = function (opts = {}) { } delete optionsObject.type; - if (!new RegExp("^.*/").test(workerFile)) { + if (!/^.*\//.test(workerFile)) { this.warn( `Paths passed to the Worker constructor must be relative or absolute, i.e. start with /, ./ or ../ (just like dynamic import!). Ignoring "${workerFile}".` ); diff --git a/build-scripts/rollup.js b/build-scripts/rollup.cjs similarity index 92% rename from build-scripts/rollup.js rename to build-scripts/rollup.cjs index dbc21dad9c..f321e9f33e 100644 --- a/build-scripts/rollup.js +++ b/build-scripts/rollup.cjs @@ -3,18 +3,18 @@ const path = require("path"); const commonjs = require("@rollup/plugin-commonjs"); const resolve = require("@rollup/plugin-node-resolve"); const json = require("@rollup/plugin-json"); -const babel = require("@rollup/plugin-babel").babel; +const { babel } = require("@rollup/plugin-babel"); const replace = require("@rollup/plugin-replace"); const visualizer = require("rollup-plugin-visualizer"); const { string } = require("rollup-plugin-string"); const { terser } = require("rollup-plugin-terser"); -const manifest = require("./rollup-plugins/manifest-plugin"); -const worker = require("./rollup-plugins/worker-plugin"); -const dontHashPlugin = require("./rollup-plugins/dont-hash-plugin"); -const ignore = require("./rollup-plugins/ignore-plugin"); +const manifest = require("./rollup-plugins/manifest-plugin.cjs"); +const worker = require("./rollup-plugins/worker-plugin.cjs"); +const dontHashPlugin = require("./rollup-plugins/dont-hash-plugin.cjs"); +const ignore = require("./rollup-plugins/ignore-plugin.cjs"); -const bundle = require("./bundle"); -const paths = require("./paths"); +const bundle = require("./bundle.cjs"); +const paths = require("./paths.cjs"); const extensions = [".js", ".ts"]; diff --git a/build-scripts/util.js b/build-scripts/util.cjs similarity index 100% rename from build-scripts/util.js rename to build-scripts/util.cjs diff --git a/build-scripts/webpack.js b/build-scripts/webpack.cjs similarity index 97% rename from build-scripts/webpack.js rename to build-scripts/webpack.cjs index bce6291b98..7a6e943a72 100644 --- a/build-scripts/webpack.js +++ b/build-scripts/webpack.cjs @@ -4,8 +4,8 @@ const TerserPlugin = require("terser-webpack-plugin"); const { WebpackManifestPlugin } = require("webpack-manifest-plugin"); const log = require("fancy-log"); const WebpackBar = require("webpackbar"); -const paths = require("./paths.js"); -const bundle = require("./bundle.js"); +const paths = require("./paths.cjs"); +const bundle = require("./bundle.cjs"); class LogStartCompilePlugin { ignoredFirst = false; @@ -64,6 +64,9 @@ const createWebpackConfig = ({ cacheCompression: false, }, }, + resolve: { + fullySpecified: false, + }, }, { test: /\.css$/, diff --git a/cast/rollup.config.js b/cast/rollup.config.js index 5460a82216..f598f1a4fa 100644 --- a/cast/rollup.config.js +++ b/cast/rollup.config.js @@ -1,5 +1,5 @@ -const rollup = require("../build-scripts/rollup.js"); -const env = require("../build-scripts/env.js"); +import rollup from "../build-scripts/rollup.cjs"; +import env from "../build-scripts/env.cjs"; const config = rollup.createCastConfig({ isProdBuild: env.isProdBuild(), @@ -7,4 +7,4 @@ const config = rollup.createCastConfig({ isStatsBuild: env.isStatsBuild(), }); -module.exports = { ...config.inputOptions, output: config.outputOptions }; +export default { ...config.inputOptions, output: config.outputOptions }; diff --git a/cast/webpack.config.js b/cast/webpack.config.js index e44575344d..b612b358ea 100644 --- a/cast/webpack.config.js +++ b/cast/webpack.config.js @@ -1,8 +1,8 @@ -const { createCastConfig } = require("../build-scripts/webpack.js"); -const { isProdBuild, isStatsBuild } = require("../build-scripts/env.js"); +import webpack from "../build-scripts/webpack.cjs"; +import env from "../build-scripts/env.cjs"; -module.exports = createCastConfig({ - isProdBuild: isProdBuild(), - isStatsBuild: isStatsBuild(), +export default webpack.createCastConfig({ + isProdBuild: env.isProdBuild(), + isStatsBuild: env.isStatsBuild(), latestBuild: true, }); diff --git a/demo/rollup.config.js b/demo/rollup.config.js index d236491002..90cff26a95 100644 --- a/demo/rollup.config.js +++ b/demo/rollup.config.js @@ -1,5 +1,5 @@ -const rollup = require("../build-scripts/rollup.js"); -const env = require("../build-scripts/env.js"); +import rollup from "../build-scripts/rollup.cjs"; +import env from "../build-scripts/env.cjs"; const config = rollup.createDemoConfig({ isProdBuild: env.isProdBuild(), @@ -7,4 +7,4 @@ const config = rollup.createDemoConfig({ isStatsBuild: env.isStatsBuild(), }); -module.exports = { ...config.inputOptions, output: config.outputOptions }; +export default { ...config.inputOptions, output: config.outputOptions }; diff --git a/demo/webpack.config.js b/demo/webpack.config.js index a297932311..52cfe8b83d 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -1,12 +1,11 @@ -const { createDemoConfig } = require("../build-scripts/webpack.js"); -const { isProdBuild, isStatsBuild } = require("../build-scripts/env.js"); +import webpack from "../build-scripts/webpack.cjs"; +import env from "../build-scripts/env.cjs"; // File just used for stats builds - const latestBuild = true; -module.exports = createDemoConfig({ - isProdBuild: isProdBuild(), - isStatsBuild: isStatsBuild(), +export default webpack.createDemoConfig({ + isProdBuild: env.isProdBuild(), + isStatsBuild: env.isStatsBuild(), latestBuild, }); diff --git a/gallery/rollup.config.js b/gallery/rollup.config.js index 787bf5a448..8504074822 100644 --- a/gallery/rollup.config.js +++ b/gallery/rollup.config.js @@ -1,5 +1,5 @@ -const rollup = require("../build-scripts/rollup.js"); -const env = require("../build-scripts/env.js"); +import rollup from "../build-scripts/rollup.cjs"; +import env from "../build-scripts/env.cjs"; const config = rollup.createGalleryConfig({ isProdBuild: env.isProdBuild(), @@ -7,4 +7,4 @@ const config = rollup.createGalleryConfig({ isStatsBuild: env.isStatsBuild(), }); -module.exports = { ...config.inputOptions, output: config.outputOptions }; +export default { ...config.inputOptions, output: config.outputOptions }; diff --git a/gallery/sidebar.js b/gallery/sidebar.js index 156d7c2969..767aecf64c 100644 --- a/gallery/sidebar.js +++ b/gallery/sidebar.js @@ -1,4 +1,4 @@ -module.exports = [ +export default [ { // This section has no header and so all page links are shown directly in the sidebar category: "concepts", diff --git a/gallery/webpack.config.js b/gallery/webpack.config.js index d7ecb07da6..76e83341cd 100644 --- a/gallery/webpack.config.js +++ b/gallery/webpack.config.js @@ -1,8 +1,8 @@ -const { createGalleryConfig } = require("../build-scripts/webpack.js"); -const { isProdBuild, isStatsBuild } = require("../build-scripts/env.js"); +import webpack from "../build-scripts/webpack.cjs"; +import env from "../build-scripts/env.cjs"; -module.exports = createGalleryConfig({ - isProdBuild: isProdBuild(), - isStatsBuild: isStatsBuild(), +export default webpack.createGalleryConfig({ + isProdBuild: env.isProdBuild(), + isStatsBuild: env.isStatsBuild(), latestBuild: true, }); diff --git a/gulpfile.js b/gulpfile.js index 78578bad7b..6178d2779d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,3 +1,13 @@ -var requireDir = require("require-dir"); +import { globIterate } from "glob"; -requireDir("./build-scripts/gulp/"); +const gulpImports = []; + +for await (const gulpModule of globIterate("build-scripts/gulp/*.?(c|m)js", { + dotRelative: true, +})) { + gulpImports.push(import(gulpModule)); +} + +// Since all tasks are currently registered with gulp.task(), this is enough +// If any are converted to named exports, need to loop and aggregate exports here +await Promise.all(gulpImports); diff --git a/hassio/config.js b/hassio/config.cjs similarity index 100% rename from hassio/config.js rename to hassio/config.cjs diff --git a/hassio/rollup.config.js b/hassio/rollup.config.js index 4beee60e48..41835a7fa8 100644 --- a/hassio/rollup.config.js +++ b/hassio/rollup.config.js @@ -1,5 +1,5 @@ -const rollup = require("../build-scripts/rollup.js"); -const env = require("../build-scripts/env.js"); +import rollup from "../build-scripts/rollup.cjs"; +import env from "../build-scripts/env.cjs"; const config = rollup.createHassioConfig({ isProdBuild: env.isProdBuild(), @@ -7,4 +7,4 @@ const config = rollup.createHassioConfig({ isStatsBuild: env.isStatsBuild(), }); -module.exports = { ...config.inputOptions, output: config.outputOptions }; +export default { ...config.inputOptions, output: config.outputOptions }; diff --git a/hassio/webpack.config.js b/hassio/webpack.config.js index 429c98e6b2..1121f1776c 100644 --- a/hassio/webpack.config.js +++ b/hassio/webpack.config.js @@ -1,8 +1,8 @@ -const { createHassioConfig } = require("../build-scripts/webpack.js"); -const { isProdBuild, isStatsBuild } = require("../build-scripts/env.js"); +import webpack from "../build-scripts/webpack.cjs"; +import env from "../build-scripts/env.cjs"; -module.exports = createHassioConfig({ - isProdBuild: isProdBuild(), - isStatsBuild: isStatsBuild(), +export default webpack.createHassioConfig({ + isProdBuild: env.isProdBuild(), + isStatsBuild: env.isStatsBuild(), latestBuild: true, }); diff --git a/lint-staged.config.js b/lint-staged.config.js index 1a5df4fdc1..be7d7f2094 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -1,5 +1,5 @@ -module.exports = { - "*.{js,ts}": ["prettier --write", "eslint --fix"], +export default { + "*.?(c|m){js,ts}": ["eslint --fix", "prettier --write"], "!(/translations)*.{json,css,md,html}": "prettier --write", "translations/*/*.json": (files) => 'printf "%s\n" "Translation files should not be added or modified here. Instead, make the necessary modifications in src/translations/en.json. Other languages are managed externally. Please see https://developers.home-assistant.io/docs/translations/ for details." ' + diff --git a/package.json b/package.json index 58513dbc1d..24efbc6e82 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,11 @@ "postinstall": "husky install", "prepack": "pinst --disable", "postpack": "pinst --enable", - "test": "instant-mocha --webpack-config ./test/webpack.config.js --require ./test/setup.js \"test/**/*.ts\"" + "test": "instant-mocha --webpack-config ./test/webpack.config.js --require ./test/setup.cjs \"test/**/*.ts\"" }, "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", + "type": "module", "dependencies": { "@braintree/sanitize-url": "6.0.2", "@codemirror/autocomplete": "6.4.2", @@ -227,13 +228,12 @@ "open": "8.4.2", "pinst": "3.0.0", "prettier": "2.8.7", - "require-dir": "1.2.0", "rollup": "2.79.1", "rollup-plugin-string": "3.0.0", "rollup-plugin-terser": "7.0.2", "rollup-plugin-visualizer": "5.9.0", "serve-handler": "6.1.5", - "sinon": "15.0.2", + "sinon": "15.0.3", "source-map-url": "0.4.1", "systemjs": "6.14.1", "tar": "6.1.13", @@ -254,7 +254,6 @@ "@polymer/polymer": "patch:@polymer/polymer@3.5.1#./.yarn/patches/@polymer/polymer/pr-5569.patch", "@material/mwc-button@^0.25.3": "^0.27.0" }, - "main": "src/home-assistant.js", "prettier": { "trailingComma": "es5", "arrowParens": "always" diff --git a/pyproject.toml b/pyproject.toml index 4bdd5d3728..cbb6b9d813 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20230329.0" +version = "20230330.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" diff --git a/rollup.config.js b/rollup.config.js index 2eb552dbfe..0b59a654d2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,5 +1,5 @@ -const rollup = require("./build-scripts/rollup.js"); -const env = require("./build-scripts/env.js"); +import rollup from "../build-scripts/rollup.cjs"; +import env from "../build-scripts/env.cjs"; const config = rollup.createAppConfig({ isProdBuild: env.isProdBuild(), @@ -7,4 +7,4 @@ const config = rollup.createAppConfig({ isStatsBuild: env.isStatsBuild(), }); -module.exports = { ...config.inputOptions, output: config.outputOptions }; +export default { ...config.inputOptions, output: config.outputOptions }; diff --git a/script/version_bump.js b/script/version_bump.cjs similarity index 100% rename from script/version_bump.js rename to script/version_bump.cjs diff --git a/src/components/chart/ha-chart-base.ts b/src/components/chart/ha-chart-base.ts index 0235fcdf88..3ffe16f64c 100644 --- a/src/components/chart/ha-chart-base.ts +++ b/src/components/chart/ha-chart-base.ts @@ -302,6 +302,7 @@ export default class HaChartBase extends LitElement { return css` :host { display: block; + position: relative; } .chartContainer { overflow: hidden; diff --git a/src/components/chart/state-history-chart-line.ts b/src/components/chart/state-history-chart-line.ts index c4b735d488..064a23d27a 100644 --- a/src/components/chart/state-history-chart-line.ts +++ b/src/components/chart/state-history-chart-line.ts @@ -61,6 +61,10 @@ class StateHistoryChartLine extends LitElement { this._chartOptions = { parsing: false, animation: false, + interaction: { + mode: "nearest", + axis: "x", + }, scales: { x: { type: "time", @@ -108,7 +112,6 @@ class StateHistoryChartLine extends LitElement { }, plugins: { tooltip: { - mode: "nearest", callbacks: { label: (context) => `${context.dataset.label}: ${formatNumber( @@ -127,16 +130,13 @@ class StateHistoryChartLine extends LitElement { }, }, }, - hover: { - mode: "nearest", - }, elements: { line: { tension: 0.1, borderWidth: 1.5, }, point: { - hitRadius: 5, + hitRadius: 50, }, }, // @ts-expect-error diff --git a/src/components/chart/statistics-chart.ts b/src/components/chart/statistics-chart.ts index 906b265143..1374d9dbf6 100644 --- a/src/components/chart/statistics-chart.ts +++ b/src/components/chart/statistics-chart.ts @@ -102,6 +102,7 @@ class StatisticsChart extends LitElement { if ( changedProps.has("statisticsData") || changedProps.has("statTypes") || + changedProps.has("chartType") || changedProps.has("hideLegend") ) { this._generateData(); @@ -149,6 +150,10 @@ class StatisticsChart extends LitElement { this._chartOptions = { parsing: false, animation: false, + interaction: { + mode: "nearest", + axis: "x", + }, scales: { x: { type: "time", @@ -186,7 +191,6 @@ class StatisticsChart extends LitElement { }, plugins: { tooltip: { - mode: "nearest", callbacks: { label: (context) => `${context.dataset.label}: ${formatNumber( @@ -208,9 +212,6 @@ class StatisticsChart extends LitElement { }, }, }, - hover: { - mode: "nearest", - }, elements: { line: { tension: 0.4, @@ -219,7 +220,7 @@ class StatisticsChart extends LitElement { }, bar: { borderWidth: 1.5, borderRadius: 4 }, point: { - hitRadius: 5, + hitRadius: 50, }, }, // @ts-expect-error @@ -316,6 +317,7 @@ class StatisticsChart extends LitElement { } statDataSets.forEach((d, i) => { if ( + this.chartType === "line" && prevEndTime && prevValues && prevEndTime.getTime() !== start.getTime() diff --git a/src/components/ha-dialog.ts b/src/components/ha-dialog.ts index b7aff993c0..d0c0ae8596 100644 --- a/src/components/ha-dialog.ts +++ b/src/components/ha-dialog.ts @@ -41,7 +41,9 @@ export class HaDialog extends DialogBase { SUPPRESS_DEFAULT_PRESS_SELECTOR, ].join(", "); this._updateScrolledAttribute(); - this.contentElement?.addEventListener("scroll", this._onScroll); + this.contentElement?.addEventListener("scroll", this._onScroll, { + passive: true, + }); } disconnectedCallback(): void { diff --git a/src/components/ha-file-upload.ts b/src/components/ha-file-upload.ts index 045cac2daa..af4524b060 100644 --- a/src/components/ha-file-upload.ts +++ b/src/components/ha-file-upload.ts @@ -191,6 +191,9 @@ export class HaFileUpload extends LitElement { inset-inline-end: initial !important; direction: var(--direction); } + .mdc-text-field__icon--trailing { + pointer-events: auto !important; + } .dragged:before { position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); diff --git a/src/components/ha-top-app-bar-fixed.ts b/src/components/ha-top-app-bar-fixed.ts index 39e223b537..49501ac01b 100644 --- a/src/components/ha-top-app-bar-fixed.ts +++ b/src/components/ha-top-app-bar-fixed.ts @@ -10,6 +10,7 @@ export class HaTopAppBarFixed extends TopAppBarFixedBase { css` .mdc-top-app-bar__row { height: var(--header-height); + border-bottom: var(--app-header-border-bottom); } .mdc-top-app-bar--fixed-adjust { padding-top: var(--header-height); @@ -21,7 +22,6 @@ export class HaTopAppBarFixed extends TopAppBarFixedBase { --app-header-background-color, var(--mdc-theme-primary) ); - border-bottom: var(--app-header-border-bottom); } `, ]; diff --git a/src/components/ha-top-app-bar.ts b/src/components/ha-top-app-bar.ts index 02330c8b56..40d27b40a8 100644 --- a/src/components/ha-top-app-bar.ts +++ b/src/components/ha-top-app-bar.ts @@ -10,6 +10,7 @@ export class HaTopAppBar extends TopAppBarBase { css` .mdc-top-app-bar__row { height: var(--header-height); + border-bottom: var(--app-header-border-bottom); } .mdc-top-app-bar--fixed-adjust { padding-top: var(--header-height); @@ -21,7 +22,6 @@ export class HaTopAppBar extends TopAppBarBase { --app-header-background-color, var(--mdc-theme-primary) ); - border-bottom: var(--app-header-border-bottom); } `, ]; diff --git a/src/data/cover.ts b/src/data/cover.ts index ee45ed5c81..8a47b1528c 100644 --- a/src/data/cover.ts +++ b/src/data/cover.ts @@ -3,7 +3,9 @@ import { HassEntityBase, } from "home-assistant-js-websocket"; import { supportsFeature } from "../common/entity/supports-feature"; +import { blankBeforePercent } from "../common/translations/blank_before_percent"; import { UNAVAILABLE } from "./entity"; +import { FrontendLocaleData } from "./translation"; export const enum CoverEntityFeature { OPEN = 1, @@ -106,3 +108,18 @@ interface CoverEntityAttributes extends HassEntityAttributeBase { export interface CoverEntity extends HassEntityBase { attributes: CoverEntityAttributes; } + +export function computeCoverPositionStateDisplay( + stateObj: CoverEntity, + locale: FrontendLocaleData, + position?: number +) { + const currentPosition = + position ?? + stateObj.attributes.current_position ?? + stateObj.attributes.current_tilt_position; + + return currentPosition && currentPosition !== 100 + ? `${Math.round(currentPosition)}${blankBeforePercent(locale)}%` + : ""; +} diff --git a/src/data/fan.ts b/src/data/fan.ts index ca8e9e5a63..9dbef3fbb4 100644 --- a/src/data/fan.ts +++ b/src/data/fan.ts @@ -9,6 +9,8 @@ import { HassEntityAttributeBase, HassEntityBase, } from "home-assistant-js-websocket"; +import { blankBeforePercent } from "../common/translations/blank_before_percent"; +import { FrontendLocaleData } from "./translation"; export const enum FanEntityFeature { SET_SPEED = 1, @@ -91,3 +93,15 @@ export function computeFanSpeedIcon( : [mdiFanSpeed1, mdiFanSpeed2, mdiFanSpeed3][index - 1]; } export const FAN_SPEED_COUNT_MAX_FOR_BUTTONS = 4; + +export function computeFanSpeedStateDisplay( + stateObj: FanEntity, + locale: FrontendLocaleData, + speed?: number +) { + const currentSpeed = speed ?? stateObj.attributes.percentage; + + return currentSpeed + ? `${Math.round(currentSpeed)}${blankBeforePercent(locale)}%` + : ""; +} diff --git a/src/dialogs/more-info/controls/more-info-cover.ts b/src/dialogs/more-info/controls/more-info-cover.ts index 659862a9b1..ef9b0f069d 100644 --- a/src/dialogs/more-info/controls/more-info-cover.ts +++ b/src/dialogs/more-info/controls/more-info-cover.ts @@ -10,9 +10,12 @@ import { import { customElement, property, state } from "lit/decorators"; import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import "../../../components/ha-attributes"; -import { CoverEntity, CoverEntityFeature } from "../../../data/cover"; +import { + computeCoverPositionStateDisplay, + CoverEntity, + CoverEntityFeature, +} from "../../../data/cover"; import type { HomeAssistant } from "../../../types"; import "../components/cover/ha-more-info-cover-buttons"; import "../components/cover/ha-more-info-cover-position"; @@ -27,7 +30,9 @@ class MoreInfoCover extends LitElement { @property({ attribute: false }) public stateObj?: CoverEntity; - @state() private _displayedPosition?: number; + @state() private _livePosition?: number; + + @state() private _liveTilt?: number; @state() private _mode?: "position" | "button"; @@ -35,20 +40,29 @@ class MoreInfoCover extends LitElement { this._mode = this._mode === "position" ? "button" : "position"; } - private _positionChanged(ev) { + private _positionSliderMoved(ev) { const value = (ev.detail as any).value; if (isNaN(value)) return; - this._displayedPosition = value; + this._livePosition = value; + } + + private _positionValueChanged() { + this._livePosition = undefined; + } + + private _tiltSliderMoved(ev) { + const value = (ev.detail as any).value; + if (isNaN(value)) return; + this._liveTilt = value; + } + + private _tiltValueChanged() { + this._liveTilt = undefined; } protected willUpdate(changedProps: PropertyValues): void { super.willUpdate(changedProps); if (changedProps.has("stateObj") && this.stateObj) { - if (supportsFeature(this.stateObj, CoverEntityFeature.SET_POSITION)) { - const currentPosition = this.stateObj?.attributes.current_position; - this._displayedPosition = - currentPosition != null ? Math.round(currentPosition) : undefined; - } if (!this._mode) { this._mode = supportsFeature(this.stateObj, CoverEntityFeature.SET_POSITION) || @@ -60,29 +74,29 @@ class MoreInfoCover extends LitElement { } private get _stateOverride() { - if (this._displayedPosition == null) return undefined; + const liveValue = this._livePosition ?? this._liveTilt; - const tempState = { - ...this.stateObj, - state: this._displayedPosition ? "open" : "closed", - attributes: { - ...this.stateObj!.attributes, - current_position: this._displayedPosition, - }, - } as CoverEntity; + const forcedState = + liveValue != null ? (liveValue ? "open" : "closed") : undefined; const stateDisplay = computeStateDisplay( this.hass.localize, - tempState!, + this.stateObj!, this.hass.locale, - this.hass.entities + this.hass.entities, + forcedState ); - return this._displayedPosition && this._displayedPosition !== 100 - ? `${stateDisplay} - ${Math.round( - this._displayedPosition - )}${blankBeforePercent(this.hass!.locale)}%` - : stateDisplay; + const positionStateDisplay = computeCoverPositionStateDisplay( + this.stateObj!, + this.hass.locale, + liveValue + ); + + if (positionStateDisplay) { + return `${stateDisplay} ⸱ ${positionStateDisplay}`; + } + return stateDisplay; } protected render() { @@ -133,7 +147,8 @@ class MoreInfoCover extends LitElement { ` : nothing} @@ -142,6 +157,8 @@ class MoreInfoCover extends LitElement { ` : nothing} diff --git a/src/dialogs/more-info/controls/more-info-fan.ts b/src/dialogs/more-info/controls/more-info-fan.ts index 701dff67a2..72b5db5b7f 100644 --- a/src/dialogs/more-info/controls/more-info-fan.ts +++ b/src/dialogs/more-info/controls/more-info-fan.ts @@ -22,11 +22,12 @@ import { computeAttributeNameDisplay, computeAttributeValueDisplay, } from "../../../common/entity/compute_attribute_display"; +import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import "../../../components/ha-attributes"; import { UNAVAILABLE } from "../../../data/entity"; import { + computeFanSpeedStateDisplay, computeFanSpeedCount, FanEntity, FanEntityFeature, @@ -49,12 +50,16 @@ class MoreInfoFan extends LitElement { @state() public _presetMode?: string; - @state() private _selectedPercentage?: number; + @state() private _liveSpeed?: number; - private _percentageChanged(ev) { + private _speedSliderMoved(ev) { const value = (ev.detail as any).value; if (isNaN(value)) return; - this._selectedPercentage = value; + this._liveSpeed = value; + } + + private _speedValueChanged() { + this._liveSpeed = undefined; } private _toggle = () => { @@ -107,12 +112,35 @@ class MoreInfoFan extends LitElement { protected updated(changedProps: PropertyValues): void { if (changedProps.has("stateObj")) { this._presetMode = this.stateObj?.attributes.preset_mode; - this._selectedPercentage = this.stateObj?.attributes.percentage - ? Math.round(this.stateObj.attributes.percentage) - : undefined; } } + private get _stateOverride() { + const liveValue = this._liveSpeed; + + const forcedState = + this._liveSpeed != null ? (this._liveSpeed ? "on" : "off") : undefined; + + const stateDisplay = computeStateDisplay( + this.hass.localize, + this.stateObj!, + this.hass.locale, + this.hass.entities, + forcedState + ); + + const positionStateDisplay = computeFanSpeedStateDisplay( + this.stateObj!, + this.hass.locale, + liveValue + ); + + if (positionStateDisplay) { + return positionStateDisplay; + } + return stateDisplay; + } + protected render() { if (!this.hass || !this.stateObj) { return nothing; @@ -140,17 +168,11 @@ class MoreInfoFan extends LitElement { supportsSpeed && computeFanSpeedCount(this.stateObj) > FAN_SPEED_COUNT_MAX_FOR_BUTTONS; - const stateOverride = this._selectedPercentage - ? `${Math.round(this._selectedPercentage)}${blankBeforePercent( - this.hass!.locale - )}%` - : undefined; - return html`
${ @@ -159,7 +181,8 @@ class MoreInfoFan extends LitElement { ` diff --git a/src/html/_style_base.html.template b/src/html/_style_base.html.template index 34de4456f5..0e06158ebb 100644 --- a/src/html/_style_base.html.template +++ b/src/html/_style_base.html.template @@ -1,8 +1,6 @@