Fix Hass.io build script (#405)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-syntax": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
const {
|
||||
Analyzer,
|
||||
FSUrlLoader
|
||||
} = require('polymer-analyzer');
|
||||
|
||||
const Bundler = require('polymer-bundler').Bundler;
|
||||
const parse5 = require('parse5');
|
||||
|
||||
const { streamFromString } = require('./stream');
|
||||
|
||||
// Bundle an HTML file and convert it to a stream
|
||||
async function bundledStreamFromHTML(path, bundlerOptions = {}) {
|
||||
const bundler = new Bundler(bundlerOptions);
|
||||
const manifest = await bundler.generateManifest([path]);
|
||||
const result = await bundler.bundle(manifest);
|
||||
return streamFromString(
|
||||
path, parse5.serialize(result.documents.get(path).ast));
|
||||
}
|
||||
|
||||
async function analyze(root, paths) {
|
||||
const analyzer = new Analyzer({
|
||||
urlLoader: new FSUrlLoader(root),
|
||||
});
|
||||
return analyzer.analyze(paths);
|
||||
}
|
||||
|
||||
async function findDependencies(root, element) {
|
||||
const deps = new Set();
|
||||
|
||||
async function resolve(files) {
|
||||
const analysis = await analyze(root, files);
|
||||
const toResolve = [];
|
||||
|
||||
for (const file of files) {
|
||||
const doc = analysis.getDocument(file);
|
||||
|
||||
for (const importEl of doc.getFeatures({ kind: 'import' })) {
|
||||
const url = importEl.url;
|
||||
if (!deps.has(url)) {
|
||||
deps.add(url);
|
||||
toResolve.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toResolve.length > 0) {
|
||||
return resolve(toResolve);
|
||||
}
|
||||
}
|
||||
|
||||
await resolve([element]);
|
||||
return deps;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bundledStreamFromHTML,
|
||||
findDependencies,
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Polymer build strategy to strip imports, even if explictely imported
|
||||
*/
|
||||
module.exports.stripImportsStrategy = function (urls) {
|
||||
return (bundles) => {
|
||||
for (const bundle of bundles) {
|
||||
for (const url of urls) {
|
||||
bundle.stripImports.add(url);
|
||||
}
|
||||
}
|
||||
return bundles;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Polymer build strategy to strip everything but the entrypoints
|
||||
* for bundles that match a specific entry point.
|
||||
*/
|
||||
module.exports.stripAllButEntrypointStrategy = function (entryPoint) {
|
||||
return (bundles) => {
|
||||
for (const bundle of bundles) {
|
||||
if (bundle.entrypoints.size === 1 &&
|
||||
bundle.entrypoints.has(entryPoint)) {
|
||||
for (const file of bundle.files) {
|
||||
if (!bundle.entrypoints.has(file)) {
|
||||
bundle.stripImports.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bundles;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
const stream = require('stream');
|
||||
|
||||
const gutil = require('gulp-util');
|
||||
|
||||
function streamFromString(filename, string) {
|
||||
var src = stream.Readable({ objectMode: true });
|
||||
src._read = function () {
|
||||
this.push(new gutil.File({
|
||||
cwd: '',
|
||||
base: '',
|
||||
path: filename,
|
||||
contents: new Buffer(string)
|
||||
}));
|
||||
this.push(null);
|
||||
};
|
||||
return src;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
streamFromString,
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
const gulpif = require('gulp-if');
|
||||
|
||||
const babel = require('gulp-babel');
|
||||
const uglify = require('gulp-uglify');
|
||||
const { gulp: cssSlam } = require('css-slam');
|
||||
const htmlMinifier = require('gulp-html-minifier');
|
||||
const { HtmlSplitter } = require('polymer-build');
|
||||
|
||||
module.exports.minifyStream = function (stream) {
|
||||
const sourcesHtmlSplitter = new HtmlSplitter();
|
||||
return stream
|
||||
.pipe(sourcesHtmlSplitter.split())
|
||||
.pipe(gulpif(/[^app]\.js$/, babel({
|
||||
sourceType: 'script',
|
||||
presets: [
|
||||
['es2015', { modules: false }]
|
||||
]
|
||||
})))
|
||||
.pipe(gulpif(/\.js$/, uglify({ sourceMap: false })))
|
||||
.pipe(gulpif(/\.css$/, cssSlam()))
|
||||
.pipe(gulpif(/\.html$/, cssSlam()))
|
||||
.pipe(gulpif(/\.html$/, htmlMinifier({
|
||||
collapseWhitespace: true,
|
||||
removeComments: true
|
||||
})))
|
||||
.pipe(sourcesHtmlSplitter.rejoin());
|
||||
};
|
||||
+8
-62
@@ -1,11 +1,6 @@
|
||||
const babel = require('gulp-babel');
|
||||
const uglify = require('gulp-uglify');
|
||||
const { gulp: cssSlam } = require('css-slam');
|
||||
const gulp = require('gulp');
|
||||
const filter = require('gulp-filter');
|
||||
const htmlMinifier = require('gulp-html-minifier');
|
||||
const gulpif = require('gulp-if');
|
||||
const { PolymerProject, HtmlSplitter } = require('polymer-build');
|
||||
const { PolymerProject, } = require('polymer-build');
|
||||
const {
|
||||
composeStrategies,
|
||||
generateShellMergeStrategy,
|
||||
@@ -15,25 +10,11 @@ const rename = require('gulp-rename');
|
||||
|
||||
const polymerConfig = require('../../polymer');
|
||||
|
||||
function minifyStream(stream) {
|
||||
const sourcesHtmlSplitter = new HtmlSplitter();
|
||||
return stream
|
||||
.pipe(sourcesHtmlSplitter.split())
|
||||
.pipe(gulpif(/[^app]\.js$/, babel({
|
||||
sourceType: 'script',
|
||||
presets: [
|
||||
['es2015', { modules: false }]
|
||||
]
|
||||
})))
|
||||
.pipe(gulpif(/\.js$/, uglify({ sourceMap: false })))
|
||||
.pipe(gulpif(/\.css$/, cssSlam()))
|
||||
.pipe(gulpif(/\.html$/, cssSlam()))
|
||||
.pipe(gulpif(/\.html$/, htmlMinifier({
|
||||
collapseWhitespace: true,
|
||||
removeComments: true
|
||||
})))
|
||||
.pipe(sourcesHtmlSplitter.rejoin());
|
||||
}
|
||||
const minifyStream = require('../common/transform').minifyStream;
|
||||
const {
|
||||
stripImportsStrategy,
|
||||
stripAllButEntrypointStrategy
|
||||
} = require('../common/strategy');
|
||||
|
||||
function renamePanel(path) {
|
||||
// Rename panels to be panels/* and not their subdir
|
||||
@@ -49,49 +30,14 @@ function renamePanel(path) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polymer build strategy to strip imports, even if explictely imported
|
||||
*/
|
||||
function generateStripStrategy(urls) {
|
||||
return (bundles) => {
|
||||
for (const bundle of bundles) {
|
||||
for (const url of urls) {
|
||||
bundle.stripImports.add(url);
|
||||
}
|
||||
}
|
||||
return bundles;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Polymer build strategy to strip everything but the entrypoints
|
||||
* for bundles that match a specific entry point.
|
||||
*/
|
||||
function stripAllButEntrypoint(entryPoint) {
|
||||
return (bundles) => {
|
||||
for (const bundle of bundles) {
|
||||
if (bundle.entrypoints.size === 1 &&
|
||||
bundle.entrypoints.has(entryPoint)) {
|
||||
for (const file of bundle.files) {
|
||||
if (!bundle.entrypoints.has(file)) {
|
||||
bundle.stripImports.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bundles;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
gulp.task('build', ['ru_all'], () => {
|
||||
const strategy = composeStrategies([
|
||||
generateShellMergeStrategy(polymerConfig.shell),
|
||||
generateStripStrategy([
|
||||
stripImportsStrategy([
|
||||
'bower_components/font-roboto/roboto.html',
|
||||
'bower_components/paper-styles/color.html',
|
||||
]),
|
||||
stripAllButEntrypoint('panels/hassio/ha-panel-hassio.html')
|
||||
stripAllButEntrypointStrategy('panels/hassio/ha-panel-hassio.html')
|
||||
]);
|
||||
const project = new PolymerProject(polymerConfig);
|
||||
|
||||
|
||||
+34
-65
@@ -1,78 +1,47 @@
|
||||
/*
|
||||
TODO:
|
||||
- Use gulp streams
|
||||
- Use polymer bundler to vulcanize
|
||||
*/
|
||||
var gulp = require('gulp');
|
||||
var Vulcanize = require('vulcanize');
|
||||
var minify = require('html-minifier');
|
||||
var fs = require('fs');
|
||||
const rename = require('gulp-rename');
|
||||
|
||||
function minifyHTML(html) {
|
||||
return minify.minify(html, {
|
||||
customAttrAssign: [/\$=/],
|
||||
removeComments: true,
|
||||
removeCommentsFromCDATA: true,
|
||||
removeCDATASectionsFromCDATA: true,
|
||||
collapseWhitespace: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
});
|
||||
}
|
||||
const {
|
||||
stripImportsStrategy,
|
||||
} = require('../common/strategy');
|
||||
const minifyStream = require('../common/transform').minifyStream;
|
||||
const {
|
||||
bundledStreamFromHTML,
|
||||
findDependencies
|
||||
} = require('../common/html');
|
||||
|
||||
const baseVulcanOptions = {
|
||||
inlineScripts: true,
|
||||
inlineCss: true,
|
||||
implicitStrip: true,
|
||||
stripComments: true,
|
||||
};
|
||||
const { polymer_dir } = require('../config');
|
||||
|
||||
const baseExcludes = [
|
||||
const DEPS_TO_STRIP = [
|
||||
'bower_components/font-roboto/roboto.html',
|
||||
'bower_components/paper-styles/color.html',
|
||||
'bower_components/iron-meta/iron-meta.html',
|
||||
];
|
||||
const DEPS_TO_STRIP_RECURSIVELY = [
|
||||
'bower_components/polymer/polymer.html',
|
||||
];
|
||||
|
||||
const toProcess = [
|
||||
// This is the Hass.io configuration panel
|
||||
// It's build standalone because it is embedded in the supervisor.
|
||||
{
|
||||
source: './panels/hassio/hassio-main.html',
|
||||
output: './build-temp/hassio-main.html',
|
||||
vulcan: new Vulcanize(Object.assign({}, baseVulcanOptions, {
|
||||
stripExcludes: baseExcludes.concat([
|
||||
'bower_components/polymer/polymer.html',
|
||||
'bower_components/iron-meta/iron-meta.html',
|
||||
]),
|
||||
})),
|
||||
},
|
||||
];
|
||||
gulp.task(
|
||||
'hassio-panel',
|
||||
async () => {
|
||||
const toStrip = [...DEPS_TO_STRIP];
|
||||
|
||||
function vulcanizeEntry(entry) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log('Processing', entry.source);
|
||||
entry.vulcan.process(entry.source, (err, inlinedHtml) => {
|
||||
if (err !== null) {
|
||||
reject(`${entry.source}: ${err}`);
|
||||
return;
|
||||
for (let dep of DEPS_TO_STRIP_RECURSIVELY) {
|
||||
toStrip.push(dep);
|
||||
const deps = await findDependencies(polymer_dir, dep);
|
||||
for (const importUrl of deps) {
|
||||
toStrip.push(importUrl);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Writing', entry.output);
|
||||
fs.writeFileSync(entry.output, minifyHTML(inlinedHtml));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
const stream = await bundledStreamFromHTML(
|
||||
'panels/hassio/hassio-main.html', {
|
||||
strategy: stripImportsStrategy(toStrip)
|
||||
}
|
||||
);
|
||||
|
||||
gulp.task('hassio-panel', () => {
|
||||
if (!fs.existsSync('build-temp')) {
|
||||
fs.mkdirSync('build-temp');
|
||||
return minifyStream(stream)
|
||||
.pipe(rename('hassio-main.html'))
|
||||
.pipe(gulp.dest('build-temp/'));
|
||||
}
|
||||
|
||||
toProcess.reduce(
|
||||
(p, entry) => p.then(() => vulcanizeEntry(entry)),
|
||||
Promise.resolve());
|
||||
|
||||
return toProcess;
|
||||
});
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user