diff --git a/.gitignore b/.gitignore index c7368a40b8..9fa46f4c80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ build build-translations/* -hassio/build-es5/* node_modules/* npm-debug.log .DS_Store diff --git a/gulp/tasks/gen-icons.js b/gulp/tasks/gen-icons.js index bb99d4d9c8..71bbc0bebb 100644 --- a/gulp/tasks/gen-icons.js +++ b/gulp/tasks/gen-icons.js @@ -7,16 +7,30 @@ const ICON_PACKAGE_PATH = path.resolve(__dirname, '../../node_modules/@mdi/svg/' const META_PATH = path.resolve(ICON_PACKAGE_PATH, 'meta.json'); const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, 'svg'); const OUTPUT_DIR = path.resolve(__dirname, '../../build'); -const OUTPUT_PATH = path.resolve(OUTPUT_DIR, 'mdi.html'); +const MDI_OUTPUT_PATH = path.resolve(OUTPUT_DIR, 'mdi.html'); +const HASS_OUTPUT_PATH = path.resolve(OUTPUT_DIR, 'hass-icons.html'); -function iconPath(name) { - return path.resolve(ICON_PATH, `${name}.svg`); -} +const BUILT_IN_PANEL_ICONS = [ + 'settings', // Config + 'home-assistant', // Hass.io + 'poll-box', // History panel + 'format-list-bulleted-type', // Logbook + 'mailbox', // Mailbox + 'account-location', // Map + 'cart', // Shopping List +]; +// Given an icon name, load the SVG file function loadIcon(name) { - return fs.readFileSync(iconPath(name), 'utf-8'); + const iconPath = path.resolve(ICON_PATH, `${name}.svg`); + try { + return fs.readFileSync(iconPath, 'utf-8'); + } catch (err) { + return null; + } } +// Given an SVG file, convert it to an iron-iconset-svg definition function transformXMLtoPolymer(name, xml) { const start = xml.indexOf('>${path}`; } -function generateIconset(name, iconDefs) { - return ` - -${iconDefs} - - `; +// Given an iconset name and icon names, generate a polymer iconset +function generateIconset(name, iconNames) { + const iconDefs = iconNames.map(name => { + const iconDef = loadIcon(name); + if (!iconDef) { + throw new Error(`Unknown icon referenced: ${name}`); + } + return transformXMLtoPolymer(name, iconDef) + }).join(''); + return `${iconDefs}`; } -async function genIcons(es6) { +// Generate the full MDI iconset +function genMDIIcons() { const meta = JSON.parse(fs.readFileSync(path.resolve(ICON_PACKAGE_PATH, META_PATH), 'UTF-8')); - const iconDefs = meta.map(iconInfo => transformXMLtoPolymer(iconInfo.name, loadIcon(iconInfo.name))).join(''); + const iconNames = meta.map(iconInfo => iconInfo.name); fs.existsSync(OUTPUT_DIR) || fs.mkdirSync(OUTPUT_DIR); - fs.writeFileSync(OUTPUT_PATH, generateIconset('mdi', iconDefs)); + fs.writeFileSync(MDI_OUTPUT_PATH, generateIconset('mdi', iconNames)); } -gulp.task('gen-icons', () => genIcons()); +// Helper function to map recursively over files in a folder and it's subfolders +function mapFiles(startPath, filter, mapFunc) { + const files = fs.readdirSync(startPath); + for (let i = 0; i < files.length; i++) { + const filename = path.join(startPath, files[i]); + const stat = fs.lstatSync(filename); + if (stat.isDirectory()) { + mapFiles(filename, filter, mapFunc); + } else if (filename.indexOf(filter) >= 0) { + mapFunc(filename); + } + } +} + +// Find all icons used by the project. +function findIcons(path, iconsetName) { + const iconRegex = new RegExp(`${iconsetName}:[\\w-]+`, 'g'); + const icons = new Set(); + function processFile(filename) { + const content = fs.readFileSync(filename); + let match; + // eslint-disable-next-line + while (match = iconRegex.exec(content)) { + // strip off "hass:" and add to set + icons.add(match[0].substr(iconsetName.length + 1)); + } + } + mapFiles(path, '.js', processFile); + return Array.from(icons); +} + +function genHassIcons() { + const iconNames = findIcons('./src', 'hass').concat(BUILT_IN_PANEL_ICONS); + fs.existsSync(OUTPUT_DIR) || fs.mkdirSync(OUTPUT_DIR); + fs.writeFileSync(HASS_OUTPUT_PATH, generateIconset('hass', iconNames)); +} + +gulp.task('gen-icons-mdi', () => genMDIIcons()); +gulp.task('gen-icons-hass', () => genHassIcons()); +gulp.task('gen-icons-hassio', () => genHassIcons()); +gulp.task('gen-icons', ['gen-icons-hass', 'gen-icons-mdi'], () => {}); + +module.exports = { + findIcons, + generateIconset, +}; diff --git a/gulp/tasks/gen-index-html.js b/gulp/tasks/gen-index-html.js index 76c128f94d..756b76595a 100644 --- a/gulp/tasks/gen-index-html.js +++ b/gulp/tasks/gen-index-html.js @@ -18,8 +18,8 @@ function generateIndex(es6) { const toReplace = [ // Needs to look like a color during CSS minifiaction ['{{ theme_color }}', '#THEME'], - ['/frontend_latest/mdi.js', - `/frontend_latest/mdi-${md5(path.resolve(config.output, 'mdi.js'))}.js`], + ['/frontend_latest/hass-icons.js', + `/frontend_latest/hass-icons-${md5(path.resolve(config.output, 'hass-icons.js'))}.js`], ]; if (!es6) { diff --git a/hassio/.gitignore b/hassio/.gitignore new file mode 100644 index 0000000000..e996d33877 --- /dev/null +++ b/hassio/.gitignore @@ -0,0 +1,2 @@ +build-es5/* +hassio-icons.html diff --git a/hassio/index.html b/hassio/index.html index 6b88a23d21..abf2d78649 100644 --- a/hassio/index.html +++ b/hassio/index.html @@ -30,6 +30,5 @@ } - diff --git a/hassio/script/build_hassio b/hassio/script/build_hassio index eac3313364..8388b902ef 100755 --- a/hassio/script/build_hassio +++ b/hassio/script/build_hassio @@ -9,5 +9,6 @@ cd "$(dirname "$0")/.." OUTPUT_DIR_ES5=build-es5 rm -rf $OUTPUT_DIR_ES5 +node script/gen-icons.js NODE_ENV=production ../node_modules/.bin/webpack -p node script/gen-index-html.js diff --git a/hassio/script/develop b/hassio/script/develop index a74c1e178e..b2344bd7e7 100755 --- a/hassio/script/develop +++ b/hassio/script/develop @@ -9,4 +9,5 @@ OUTPUT_DIR_ES5=build-es5 rm -rf $OUTPUT_DIR_ES5 mkdir $OUTPUT_DIR_ES5 node script/gen-index-html.js +node script/gen-icons.js ../node_modules/.bin/webpack --watch --progress diff --git a/hassio/script/gen-icons.js b/hassio/script/gen-icons.js new file mode 100755 index 0000000000..21c6f3b9e4 --- /dev/null +++ b/hassio/script/gen-icons.js @@ -0,0 +1,13 @@ +#!/usr/bin/env node +const fs = require('fs'); +const { + findIcons, + generateIconset, +} = require('../../gulp/tasks/gen-icons.js'); + +function genHassIcons() { + const iconNames = findIcons('./src', 'hassio'); + fs.writeFileSync('./hassio-icons.html', generateIconset('hassio', iconNames)); +} + +genHassIcons(); diff --git a/hassio/src/addon-store/hassio-addon-repository.js b/hassio/src/addon-store/hassio-addon-repository.js index f35a655693..6498f8d71e 100644 --- a/hassio/src/addon-store/hassio-addon-repository.js +++ b/hassio/src/addon-store/hassio-addon-repository.js @@ -51,7 +51,7 @@ class HassioAddonRepository extends NavigateMixin(PolymerElement) { } computeIcon(addon) { - return addon.installed && addon.installed !== addon.version ? 'mdi:arrow-up-bold-circle' : 'mdi:puzzle'; + return addon.installed && addon.installed !== addon.version ? 'hassio:arrow-up-bold-circle' : 'hassio:puzzle'; } computeIconTitle(addon) { diff --git a/hassio/src/addon-store/hassio-repositories-editor.js b/hassio/src/addon-store/hassio-repositories-editor.js index 78edea7e34..3ecbc8917a 100644 --- a/hassio/src/addon-store/hassio-repositories-editor.js +++ b/hassio/src/addon-store/hassio-repositories-editor.js @@ -35,7 +35,7 @@ class HassioRepositoriesEditor extends PolymerElement {
- +
diff --git a/hassio/src/addon-view/hassio-addon-info.js b/hassio/src/addon-view/hassio-addon-info.js index 39113be4ac..50e73db38a 100644 --- a/hassio/src/addon-view/hassio-addon-info.js +++ b/hassio/src/addon-view/hassio-addon-info.js @@ -66,7 +66,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
- + `; } diff --git a/src/panels/config/script/ha-script-picker.js b/src/panels/config/script/ha-script-picker.js index 3e6cb898ee..6f82647e83 100644 --- a/src/panels/config/script/ha-script-picker.js +++ b/src/panels/config/script/ha-script-picker.js @@ -52,7 +52,7 @@ class HaScriptPicker extends LocalizeMixin(NavigateMixin(PolymerElement)) { - +
[[localize('ui.panel.config.script.caption')]]
@@ -76,13 +76,13 @@ class HaScriptPicker extends LocalizeMixin(NavigateMixin(PolymerElement)) {
[[computeName(script)]]
[[computeDescription(script)]]
- +
- + `; } diff --git a/src/panels/config/zwave/ha-config-zwave.js b/src/panels/config/zwave/ha-config-zwave.js index 6a1c0a5e55..4fc7126e98 100644 --- a/src/panels/config/zwave/ha-config-zwave.js +++ b/src/panels/config/zwave/ha-config-zwave.js @@ -83,7 +83,7 @@ class HaConfigZwave extends LocalizeMixin(PolymerElement) { - +
[[localize('ui.panel.config.zwave.caption')]]
@@ -94,7 +94,7 @@ class HaConfigZwave extends LocalizeMixin(PolymerElement) {
Z-Wave Node Management - +
diff --git a/src/panels/config/zwave/zwave-network.js b/src/panels/config/zwave/zwave-network.js index a4b25b14f8..c31860f5fb 100644 --- a/src/panels/config/zwave/zwave-network.js +++ b/src/panels/config/zwave/zwave-network.js @@ -45,7 +45,7 @@ class ZwaveNetwork extends PolymerElement {
Z-Wave Network Management - +
diff --git a/src/panels/dev-info/ha-panel-dev-info.js b/src/panels/dev-info/ha-panel-dev-info.js index da51b87185..74cb80ea1c 100644 --- a/src/panels/dev-info/ha-panel-dev-info.js +++ b/src/panels/dev-info/ha-panel-dev-info.js @@ -198,7 +198,7 @@ class HaPanelDevInfo extends PolymerElement {

Press the button to load the full Home Assistant log. - +

[[errorLog]]
diff --git a/src/panels/dev-state/ha-panel-dev-state.js b/src/panels/dev-state/ha-panel-dev-state.js index 347066e60b..a182603524 100644 --- a/src/panels/dev-state/ha-panel-dev-state.js +++ b/src/panels/dev-state/ha-panel-dev-state.js @@ -121,7 +121,7 @@ class HaPanelDevState extends EventsMixin(PolymerElement) { diff --git a/src/panels/logbook/ha-panel-logbook.js b/src/panels/logbook/ha-panel-logbook.js index c80e7547c5..8d85ddc9ef 100644 --- a/src/panels/logbook/ha-panel-logbook.js +++ b/src/panels/logbook/ha-panel-logbook.js @@ -61,7 +61,7 @@ class HaPanelLogbook extends LocalizeMixin(PolymerElement) {
[[localize('panel.logbook')]]
diff --git a/src/panels/mailbox/ha-panel-mailbox.js b/src/panels/mailbox/ha-panel-mailbox.js index f0fb1bfccb..028770317b 100644 --- a/src/panels/mailbox/ha-panel-mailbox.js +++ b/src/panels/mailbox/ha-panel-mailbox.js @@ -134,7 +134,7 @@ class HaPanelMailbox extends LocalizeMixin(PolymerElement) { [[localize('ui.panel.mailbox.playback_title')]]
diff --git a/src/panels/map/ha-entity-marker.js b/src/panels/map/ha-entity-marker.js index 110743af3f..3ff8b2e7ab 100644 --- a/src/panels/map/ha-entity-marker.js +++ b/src/panels/map/ha-entity-marker.js @@ -1,9 +1,7 @@ -import '@polymer/iron-icon/iron-icon.js'; import '@polymer/iron-image/iron-image.js'; import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js'; - import EventsMixin from '../../mixins/events-mixin.js'; /* diff --git a/src/panels/shopping-list/ha-panel-shopping-list.js b/src/panels/shopping-list/ha-panel-shopping-list.js index a755d29645..8ddeeac71b 100644 --- a/src/panels/shopping-list/ha-panel-shopping-list.js +++ b/src/panels/shopping-list/ha-panel-shopping-list.js @@ -79,7 +79,7 @@ class HaPanelShoppingList extends LocalizeMixin(PolymerElement) { vertical-offset="-5" > @@ -96,7 +96,7 @@ class HaPanelShoppingList extends LocalizeMixin(PolymerElement) { diff --git a/src/resources/hass-icons.js b/src/resources/hass-icons.js new file mode 100644 index 0000000000..ee234cf367 --- /dev/null +++ b/src/resources/hass-icons.js @@ -0,0 +1,6 @@ +import iconSetContent from '../../build/hass-icons.html'; + +const documentContainer = document.createElement('template'); +documentContainer.setAttribute('style', 'display: none;'); +documentContainer.innerHTML = iconSetContent; +document.head.appendChild(documentContainer.content); diff --git a/src/entrypoints/mdi.js b/src/resources/mdi-icons.js similarity index 100% rename from src/entrypoints/mdi.js rename to src/resources/mdi-icons.js diff --git a/webpack.config.js b/webpack.config.js index 5a1bc8f21f..5816e51240 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -64,7 +64,7 @@ function createConfig(isProdBuild, latestBuild) { copyPluginOpts.push('node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js') copyPluginOpts.push({ from: 'node_modules/leaflet/dist/leaflet.css', to: `images/leaflet/` }); copyPluginOpts.push({ from: 'node_modules/leaflet/dist/images', to: `images/leaflet/` }); - entry.mdi = './src/entrypoints/mdi.js'; + entry['hass-icons'] = './src/entrypoints/hass-icons.js'; } else { copyPluginOpts.push('node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js'); babelOptions.presets = [