Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ node_modules/*
npm-debug.log
.DS_Store
hass_frontend/*
hass_frontend_es5/*
.reify-cache
demo/hademo-icons.html

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions build-scripts/gulp/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const del = require("del");
const gulp = require("gulp");
const config = require("../paths");

gulp.task("clean", () => del([config.root, config.build_dir]));
29 changes: 29 additions & 0 deletions build-scripts/gulp/develop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Run HA develop mode
const gulp = require("gulp");

require("./clean.js");
require("./translations.js");
require("./gen-icons.js");
require("./gather-static.js");
require("./webpack.js");
require("./service-worker.js");
require("./entry-html.js");

gulp.task(
"develop",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean",
gulp.parallel(
"copy-static",
"gen-service-worker-dev",
"gen-icons",
"gen-pages-dev",
"gen-index-html-dev",
gulp.series("build-translations", "copy-translations")
),
"webpack-watch"
)
);
108 changes: 108 additions & 0 deletions build-scripts/gulp/entry-html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Tasks to generate entry HTML
/* eslint-disable import/no-dynamic-require */
/* eslint-disable global-require */
const gulp = require("gulp");
const fs = require("fs-extra");
const path = require("path");
const template = require("lodash.template");
const minify = require("html-minifier").minify;
const config = require("../paths.js");

const templatePath = (tpl) =>
path.resolve(config.polymer_dir, "src/html/", `${tpl}.html.template`);

const readFile = (pth) => fs.readFileSync(pth).toString();

const renderTemplate = (pth, data = {}) => {
const compiled = template(readFile(templatePath(pth)));
return compiled({ ...data, renderTemplate });
};

const minifyHtml = (content) =>
minify(content, {
collapseWhitespace: true,
minifyJS: true,
minifyCSS: true,
removeComments: true,
});

const PAGES = ["onboarding", "authorize"];

gulp.task("gen-pages-dev", (done) => {
for (const page of PAGES) {
const content = renderTemplate(page, {
latestPageJS: `/frontend_latest/${page}.js`,
latestHassIconsJS: "/frontend_latest/hass-icons.js",

es5Compatibility: "/frontend_es5/compatibility.js",
es5PageJS: `/frontend_es5/${page}.js`,
es5HassIconsJS: "/frontend_es5/hass-icons.js",
});

fs.outputFileSync(path.resolve(config.root, `${page}.html`), content);
}
done();
});

gulp.task("gen-pages-prod", (done) => {
const latestManifest = require(path.resolve(config.output, "manifest.json"));
const es5Manifest = require(path.resolve(config.output_es5, "manifest.json"));

for (const page of PAGES) {
const content = renderTemplate(page, {
latestPageJS: latestManifest[`${page}.js`],
latestHassIconsJS: latestManifest["hass-icons.js"],

es5Compatibility: es5Manifest["compatibility.js"],
es5PageJS: es5Manifest[`${page}.js`],
es5HassIconsJS: es5Manifest["hass-icons.js"],
});

fs.outputFileSync(
path.resolve(config.root, `${page}.html`),
minifyHtml(content)
);
}
done();
});

gulp.task("gen-index-html-dev", (done) => {
// In dev mode we don't mangle names, so we hardcode urls. That way we can
// run webpack as last in watch mode, which blocks output.
const content = renderTemplate("index", {
latestAppJS: "/frontend_latest/app.js",
latestCoreJS: "/frontend_latest/core.js",
latestCustomPanelJS: "/frontend_latest/custom-panel.js",
latestHassIconsJS: "/frontend_latest/hass-icons.js",

es5Compatibility: "/frontend_es5/compatibility.js",
es5AppJS: "/frontend_es5/app.js",
es5CoreJS: "/frontend_es5/core.js",
es5CustomPanelJS: "/frontend_es5/custom-panel.js",
es5HassIconsJS: "/frontend_es5/hass-icons.js",
});

fs.outputFileSync(path.resolve(config.root, "index.html"), content);
done();
});

gulp.task("gen-index-html-prod", (done) => {
const latestManifest = require(path.resolve(config.output, "manifest.json"));
const es5Manifest = require(path.resolve(config.output_es5, "manifest.json"));
const content = renderTemplate("index", {
latestAppJS: latestManifest["app.js"],
latestCoreJS: latestManifest["core.js"],
latestCustomPanelJS: latestManifest["custom-panel.js"],
latestHassIconsJS: latestManifest["hass-icons.js"],

es5Compatibility: es5Manifest["compatibility.js"],
es5AppJS: es5Manifest["app.js"],
es5CoreJS: es5Manifest["core.js"],
es5CustomPanelJS: es5Manifest["custom-panel.js"],
es5HassIconsJS: es5Manifest["hass-icons.js"],
});
const minified = minifyHtml(content).replace(/#THEMEC/g, "{{ theme_color }}");

fs.outputFileSync(path.resolve(config.root, "index.html"), minified);
done();
});
87 changes: 87 additions & 0 deletions build-scripts/gulp/gather-static.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Gulp task to gather all static files.

const gulp = require("gulp");
const path = require("path");
const fs = require("fs-extra");
const zopfli = require("gulp-zopfli-green");
const merge = require("merge-stream");
const config = require("../paths");

const npmPath = (...parts) =>
path.resolve(config.polymer_dir, "node_modules", ...parts);
const polyPath = (...parts) => path.resolve(config.polymer_dir, ...parts);
const staticPath = (...parts) => path.resolve(config.root, "static", ...parts);

const copyFileDir = (fromFile, toDir) =>
fs.copySync(fromFile, path.join(toDir, path.basename(fromFile)));

function copyTranslations() {
// Translation output
fs.copySync(
polyPath("build-translations/output"),
staticPath("translations")
);
}

function copyStatic() {
// Basic static files
fs.copySync(polyPath("public"), config.root);

// Web Component polyfills and adapters
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"),
staticPath("polyfills/")
);
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js"),
staticPath("polyfills/")
);
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js.map"),
staticPath("polyfills/")
);

// Local fonts
fs.copySync(npmPath("@polymer/font-roboto-local/fonts"), staticPath("fonts"));

// External dependency assets
copyFileDir(
npmPath("react-big-calendar/lib/css/react-big-calendar.css"),
staticPath("panels/calendar/")
);
copyFileDir(
npmPath("leaflet/dist/leaflet.css"),
staticPath("images/leaflet/")
);
fs.copySync(
npmPath("leaflet/dist/images"),
staticPath("images/leaflet/images/")
);
}

gulp.task("copy-static", (done) => {
copyStatic();
done();
});

gulp.task("compress-static", () => {
const fonts = gulp
.src(staticPath("fonts/**/*.ttf"))
.pipe(zopfli())
.pipe(gulp.dest(staticPath("fonts")));
const polyfills = gulp
.src(staticPath("polyfills/*.js"))
.pipe(zopfli())
.pipe(gulp.dest(staticPath("polyfills")));
const translations = gulp
.src(staticPath("translations/*.json"))
.pipe(zopfli())
.pipe(gulp.dest(staticPath("translations")));

return merge(fonts, polyfills, translations);
});

gulp.task("copy-translations", (done) => {
copyTranslations();
done();
});
19 changes: 10 additions & 9 deletions gulp/tasks/gen-icons.js → build-scripts/gulp/gen-icons.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const gulp = require("gulp");
const path = require("path");
const fs = require("fs");
const config = require("../config");

const ICON_PACKAGE_PATH = path.resolve(
__dirname,
Expand Down Expand Up @@ -38,12 +37,12 @@ function loadIcon(name) {
function transformXMLtoPolymer(name, xml) {
const start = xml.indexOf("><path") + 1;
const end = xml.length - start - 6;
const path = xml.substr(start, end);
return `<g id="${name}">${path}</g>`;
const pth = xml.substr(start, end);
return `<g id="${name}">${pth}</g>`;
}

// Given an iconset name and icon names, generate a polymer iconset
function generateIconset(name, iconNames) {
function generateIconset(iconsetName, iconNames) {
const iconDefs = Array.from(iconNames)
.map((name) => {
const iconDef = loadIcon(name);
Expand All @@ -53,7 +52,7 @@ function generateIconset(name, iconNames) {
return transformXMLtoPolymer(name, iconDef);
})
.join("");
return `<ha-iconset-svg name="${name}" size="24"><svg><defs>${iconDefs}</defs></svg></ha-iconset-svg>`;
return `<ha-iconset-svg name="${iconsetName}" size="24"><svg><defs>${iconDefs}</defs></svg></ha-iconset-svg>`;
}

// Generate the full MDI iconset
Expand All @@ -62,7 +61,9 @@ function genMDIIcons() {
fs.readFileSync(path.resolve(ICON_PACKAGE_PATH, META_PATH), "UTF-8")
);
const iconNames = meta.map((iconInfo) => iconInfo.name);
fs.existsSync(OUTPUT_DIR) || fs.mkdirSync(OUTPUT_DIR);
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR);
}
fs.writeFileSync(MDI_OUTPUT_PATH, generateIconset("mdi", iconNames));
}

Expand All @@ -81,7 +82,7 @@ function mapFiles(startPath, filter, mapFunc) {
}

// Find all icons used by the project.
function findIcons(path, iconsetName) {
function findIcons(searchPath, iconsetName) {
const iconRegex = new RegExp(`${iconsetName}:[\\w-]+`, "g");
const icons = new Set();
function processFile(filename) {
Expand All @@ -93,8 +94,8 @@ function findIcons(path, iconsetName) {
icons.add(match[0].substr(iconsetName.length + 1));
}
}
mapFiles(path, ".js", processFile);
mapFiles(path, ".ts", processFile);
mapFiles(searchPath, ".js", processFile);
mapFiles(searchPath, ".ts", processFile);
return icons;
}

Expand Down
31 changes: 31 additions & 0 deletions build-scripts/gulp/release.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Run HA develop mode
const gulp = require("gulp");

require("./clean.js");
require("./translations.js");
require("./gen-icons.js");
require("./gather-static.js");
require("./webpack.js");
require("./service-worker.js");
require("./entry-html.js");

gulp.task(
"build-release",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean",
gulp.parallel(
"copy-static",
"gen-icons",
gulp.series("build-translations", "copy-translations")
),
gulp.parallel("webpack-prod", "compress-static"),
gulp.parallel(
"gen-pages-prod",
"gen-index-html-prod",
"gen-service-worker-prod"
)
)
);
29 changes: 29 additions & 0 deletions build-scripts/gulp/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Generate service worker.
// Based on manifest, create a file with the content as service_worker.js
/* eslint-disable import/no-dynamic-require */
/* eslint-disable global-require */
const gulp = require("gulp");
const path = require("path");
const fs = require("fs-extra");
const config = require("../paths.js");

const swPath = path.resolve(config.root, "service_worker.js");

const writeSW = (content) => fs.outputFileSync(swPath, content.trim() + "\n");

gulp.task("gen-service-worker-dev", (done) => {
writeSW(
`
console.debug('Service worker disabled in development');
`
);
done();
});

gulp.task("gen-service-worker-prod", (done) => {
fs.copySync(
path.resolve(config.output, "service_worker.js"),
path.resolve(config.root, "service_worker.js")
);
done();
});
File renamed without changes.
Loading