ESPresense/ui/rollup.config.js

187 lines
6.8 KiB
JavaScript

import svelte from 'rollup-plugin-svelte';
import image from '@rollup/plugin-image';
import resolve from '@rollup/plugin-node-resolve';
import terser from "@rollup/plugin-terser";
import postcss from 'rollup-plugin-postcss'
import htmlTemplate from 'rollup-plugin-generate-html-template';
import { readFile, writeFile } from 'fs';
import { basename } from 'path';
import { promisify } from 'util';
import zlib from 'node:zlib';
import { VERSION, } from 'rollup';
import { pascalCase } from "pascal-case";
import mime from 'mime';
function hexdump(buffer) {
let lines = [];
for (let i = 0; i < buffer.length; i += 16) {
let block = buffer.slice(i, i + 16); // cut buffer into blocks of 16
let hexArray = [];
for (let value of block) {
hexArray.push("0x" + value.toString(16).padStart(2, "0"));
}
let hexString = hexArray.join(", ");
let line = ` ${hexString}`;
lines.push(line);
}
return lines.join(",\n");
}
function cppCompressed(input, fileName, contentType) {
return new Promise((resolve, reject) => zlib.gzip(input, { level: zlib.constants.Z_BEST_COMPRESSION }, function (error, result) {
if (error) {
reject(err);
}
console.info(fileName + " compressed " + result.length + " bytes");
const array = hexdump(result);
const src = `/*
* Binary array for the Web UI.
* Gzip is used for smaller size and improved speeds.
*/
// Autogenerated do not edit!!
const uint16_t ${fileName.replace(".","_").toUpperCase()}_L = ${result.length};
const uint8_t ${fileName.replace(".","_").toUpperCase()}[] PROGMEM = {
${array}
};
void serve${pascalCase(fileName)}(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "${contentType || mime.getType(fileName)}", ${fileName.replace(".","_").toUpperCase()}, ${fileName.replace(".","_").toUpperCase()}_L);
response->addHeader(F("Content-Encoding"), "gzip");
request->send(response);
}
`;
resolve(src);
}));
}
const isFunction = (arg) => typeof arg === 'function';
const isRegExp = (arg) => Object.prototype.toString.call(arg) === '[object RegExp]';
const readFilePromise = promisify(readFile);
const writeFilePromise = promisify(writeFile);
function isOutputChunk(file) {
return typeof file.code === 'string';
}
function getOutputFileContent(outputFileName, outputFile, outputOptions) {
if (isOutputChunk(outputFile)) {
let source;
source = outputFile.code;
if (outputOptions.sourcemap && outputFile.map) {
const url = outputOptions.sourcemap === 'inline'
? outputFile.map.toUrl()
: `${basename(outputFileName)}.map`;
source += `//# source` + `MappingURL=${url}\n`;
}
return source;
}
else {
return typeof outputFile.source === 'string'
? outputFile.source
: // just to be sure, as it is typed string | Uint8Array in rollup 2.0.0
Buffer.from(outputFile.source);
}
}
function cpp(options = {}) {
const mapFileName = isFunction(options.fileName)
? options.fileName
: (fileName) => fileName + (options.fileName || '.cpp');
const plugin = {
name: 'cpp',
generateBundle(outputOptions, bundle, isWrite) {
if (!isWrite)
return;
return Promise.all(Object.keys(bundle)
.map(fileName => {
const fileEntry = bundle[fileName];
// file name filter option check
const fileNameFilter = options.filter || /\.(js|mjs|json|css|html)$/;
if (isRegExp(fileNameFilter) &&
!fileName.match(fileNameFilter)) {
return Promise.resolve();
}
if (isFunction(fileNameFilter) &&
!fileNameFilter(fileName)) {
return Promise.resolve();
}
const fileContent = getOutputFileContent(fileName, fileEntry, outputOptions);
// minSize option check
if (options.minSize &&
options.minSize > fileContent.length) {
return Promise.resolve();
}
return Promise.resolve(cppCompressed(fileContent, fileName))
.then(compressedContent => {
writeFilePromise(mapFileName(fileName), compressedContent);
return null;
})
.catch((err) => {
console.error(err);
return Promise.reject('[rollup-plugin-cpp] Error compressing file ' +
fileName);
});
})
.concat([
(() => {
if (!options.additionalFiles ||
!options.additionalFiles.length)
return Promise.resolve();
const compressAdditionalFiles = () => Promise.all(options.additionalFiles.map(filePath => readFilePromise(filePath)
.then(fileContent => cppCompressed(fileContent, basename(filePath)))
.then(compressedContent => {
return writeFilePromise(mapFileName(filePath), compressedContent);
})
.catch((err) => {
return Promise.reject('[rollup-plugin-cpp] Error compressing additional file ' +
filePath + '\n' + err);
})));
// additional files can be processed outside of rollup after a delay
// for older plugins or plugins that write to disk (curcumventing rollup) without awaiting
const additionalFilesDelay = options.additionalFilesDelay ||
(VERSION >= '2.0.0' ? 0 : 2000);
if (additionalFilesDelay) {
setTimeout(compressAdditionalFiles, additionalFilesDelay);
return Promise.resolve();
}
else {
return compressAdditionalFiles();
}
})(),
]));
},
};
return plugin;
}
export default {
input: 'src/main.js',
output: {
format: 'iife',
file: './dist/index.js',
name: 'app'
},
plugins: [
svelte({}),
resolve(),
image(),
postcss({ extract: 'bundle.css' }),
htmlTemplate({
template: 'src/template.html',
target: 'index.html',
}),
terser(),
cpp({
additionalFiles: ['dist/index.html'],
fileName: function(a) { return "../src/ui_" + basename(a).replace(".", "_") + ".h"; }
})
]
};