Arduino Core 3 (#407)

* Add and remove libs and components for Arduino Core 3

* Arduino Core 3

* Add back Solo1

* Change ESP32-S3 to 4MB build

* Update README.md

* Fix retain and number of retries

* Fix rolling log

* Fix defaults

* Fix BleScanner on Solo1

* Export settings

* Import settings

* Fix HA Battery voltage

* Change submodule

* Update espMqttClient and AsyncTCP

* Webserial and MQTT/Network reconnecting

* Update nuki_ble

---------

Co-authored-by: iranl <iranl@github.com>
This commit is contained in:
iranl
2024-07-05 18:45:39 +02:00
committed by GitHub
parent 193ebb5f91
commit 6b0100fd61
236 changed files with 16390 additions and 9740 deletions

View File

@@ -0,0 +1,19 @@
# Frontend
The `index.html` is the only page of WebSerialLite and you can modify the page yourself and regenerate it.
In addition, I am also very happy that you can participate in fixing the bugs of the library or enhancing the functions of the library.
## Quick Start
You can modify and regenerate the page in three step. The execution of the following commands is based on the project root directory and you should install NodeJS and pnpm first.
```shell
cd .\frontend\
pnpm i
pnpm build
```
The `finalize.js` will compress and html and generate a new `WebSerialWebPage.h` in `../src` floder automatically.
Then you can rebuild your program, the new page ought be embedded in the firmware as expected.

View File

@@ -0,0 +1,66 @@
let path = require('path');
let fs = require('fs');
const {minify} = require('html-minifier-terser');
let gzipAsync = require('@gfx/zopfli').gzipAsync;
const SAVE_PATH = '../src';
function chunkArray(myArray, chunk_size) {
let index = 0;
let arrayLength = myArray.length;
let tempArray = [];
for (index = 0; index < arrayLength; index += chunk_size) {
let myChunk = myArray.slice(index, index + chunk_size);
tempArray.push(myChunk);
}
return tempArray;
}
function addLineBreaks(buffer) {
let data = '';
let chunks = chunkArray(buffer, 30);
chunks.forEach((chunk, index) => {
data += chunk.join(',');
if (index + 1 !== chunks.length) {
data += ',\n';
}
});
return data;
}
(async function(){
const indexHtml = fs.readFileSync(path.resolve(__dirname, './index.html')).toString();
const indexHtmlMinify = await minify(indexHtml, {
collapseWhitespace: true,
removeComments: true,
removeAttributeQuotes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true,
minifyCSS: true,
minifyJS: true,
sortAttributes: true, // 不会改变生成的html长度 但会优化压缩后体积
sortClassName: true, // 不会改变生成的html长度 但会优化压缩后体积
});
console.log(`[finalize.js] Minified index.html | Original Size: ${(indexHtml.length / 1024).toFixed(2) }KB | Minified Size: ${(indexHtmlMinify.length / 1024).toFixed(2) }KB`);
try{
const GZIPPED_INDEX = await gzipAsync(indexHtmlMinify, { numiterations: 15 });
const FILE =
`#ifndef _webserial_webapge_h
#define _webserial_webpage_h
const uint32_t WEBSERIAL_HTML_SIZE = ${GZIPPED_INDEX.length};
const uint8_t WEBSERIAL_HTML[] PROGMEM = {
${ addLineBreaks(GZIPPED_INDEX) }
};
#endif
`;
fs.writeFileSync(path.resolve(__dirname, SAVE_PATH+'/WebSerialWebPage.h'), FILE);
console.log(`[finalize.js] Compressed Bundle into WebSerialWebPage.h header file | Total Size: ${(GZIPPED_INDEX.length / 1024).toFixed(2) }KB`)
}catch(err){
return console.error(err);
}
})();

View File

@@ -0,0 +1,364 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Web Console</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
div {
display: block;
}
a {
margin: 0.4rem;
text-decoration: none;
}
*,
::after,
::before {
-webkit-box-sizing: inherit;
box-sizing: inherit;
}
p {
margin: 0 0 1rem;
}
body {
overscroll-behavior: none;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", sans-serif;
}
.text-center {
text-align: center;
}
.gray {
color: #667189;
}
.shadow {
filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
}
.w-full {
width: 100%;
}
.grid {
display: grid;
}
.gap-2 {
gap: 0.5rem;
}
.flex {
display: flex;
}
.grow {
flex-grow: 1;
}
.justify-items-end {
justify-items: end;
}
.rounded {
border-radius: 0.5rem;
}
.section {
box-sizing: border-box;
background-color: #f8f9fa;
}
.main {
/* padding-top: 3rem; */
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100dvh;
}
.main .pannel {
position: relative;
border: #fff;
border-style: solid;
border-width: 0.5rem;
border-radius: 1rem;
background-color: #fff;
width: calc(100% - 1rem);
font-size: medium;
margin-top: 2.5rem;
}
.pannel button {
cursor: pointer;
padding: 8px 10px 8px;
font-size: medium;
outline-style: none;
border: 0px;
color: #fff;
background-color: #0067f4;
}
.pannel button:disabled {
background-color: #5a6169;
}
.pannel #record {
min-height: 3.25rem;
padding: 0.5rem;
resize: vertical;
overscroll-behavior: none;
}
#control-button {
position: absolute;
top: 0.5rem;
right: 0.5rem;
}
#control-button button {
background-color: #5a6169;
}
.alert span {
user-select: none;
background: #ffe14d;
padding: 2px 10px;
display: block;
color: black;
}
.footer {
padding: 1rem 0.5rem;
background-color: white;
}
.copyright {
padding-bottom: 1rem;
}
.float-left {
float: left;
}
.float-right {
float: right;
}
</style>
</head>
<body>
<div class="section main text-center">
<h1 id="title" style="display: none;">Web Console</h1>
<a href="/">
<img id="logo" src="/logo" onerror="removeLogo();" />
</a>
<div class="pannel shadow grid gap-2">
<div id="control-button">
<button class="rounded shadow" onclick="terminalClean()">
<svg viewBox="64 64 896 896" focusable="false" data-icon="delete" width="1em" height="1em"
fill="currentColor" aria-hidden="true">
<path
d="M864 256H736v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zm-200 0H360v-72h304v72z">
</path>
</svg>
</button>
<button class="rounded shadow" onclick="enableFlowLock=!enableFlowLock">
<svg viewBox="64 64 896 896" focusable="false" data-icon="lock" width="1em" height="1em"
fill="currentColor" aria-hidden="true">
<path
d="M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240zm460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53a48.01 48.01 0 10-56 0z">
</path>
</svg>
</button>
<button class="rounded shadow" onclick="enableTimestamp=!enableTimestamp">
<svg viewBox="64 64 896 896" focusable="false" data-icon="clock-circle" width="1em" height="1em"
fill="currentColor" aria-hidden="true">
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z">
</path>
<path
d="M686.7 638.6L544.1 535.5V288c0-4.4-3.6-8-8-8H488c-4.4 0-8 3.6-8 8v275.4c0 2.6 1.2 5 3.3 6.5l165.4 120.6c3.6 2.6 8.6 1.8 11.2-1.7l28.6-39c2.6-3.7 1.8-8.7-1.8-11.2z">
</path>
</svg>
</button>
</div>
<textarea class="w-full rounded" title="record" id="record" cols="30" rows="40" disabled></textarea>
<div class="flex w-full grid gap-2" id="terminal">
<input type="text" name="cmd" id="command-text" class="grow rounded" /><button
class="grid justify-items-end rounded shadow" id="command-button">
SEND
</button>
</div>
</div>
<h1 />
</div>
</body>
<script>
let gateway = `ws://${window.location.host + window.location.pathname}ws`;
let websocket;
let textArea = document.getElementById("record");
let enableFlowLock = false;
let enableTimestamp = false;
let pingTimeout;
let connectTimeout;
let commandHistory = [];
let commandHistoryIdx = 0;
function removeLogo() {
document.getElementById("logo").remove();
document.getElementById("title").style.display = "block";
}
function initWebPage() {
document.getElementById("command-button").disabled = true;
document.getElementById("command-text").disabled = true;
initCommandHistory();
initWebSocket();
initButton();
trapKeyPress();
}
function initCommandHistory() {
const json = localStorage.history;
commandHistory = json ? JSON.parse(json) : [];
commandHistoryIdx = commandHistory.length;
}
function initWebSocket() {
clearTimeout(connectTimeout);
clearTimeout(pingTimeout);
pingTimeout = false;
connectTimeout = setTimeout(() => {
terminalWrite("[WebSerial] Connect timeout.");
websocket.close();
initWebSocket();
}, 3000);
terminalWrite("[WebSerial] Connecting...");
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
websocket.onerror = onError;
}
function initButton() {
document.getElementById("command-button").addEventListener("click", sendCommand);
}
function trapKeyPress() {
document.getElementById("command-text").addEventListener("keypress", (event) => {
if (event.code === "Enter") {
event.preventDefault();
document.getElementById("command-button").click();
}
});
document.addEventListener("keydown", (event) => {
if (document.activeElement && document.activeElement.id === 'command-text') {
if (event.code === "ArrowUp") {
commandHistoryIdx--;
if (commandHistoryIdx < 0)
commandHistoryIdx = commandHistory.length > 0 ? commandHistory.length - 1 : 0;
if (commandHistoryIdx >= 0 && commandHistoryIdx < commandHistory.length)
document.getElementById("command-text").value = commandHistory[commandHistoryIdx];
} else if (event.code === "ArrowDown") {
commandHistoryIdx++;
if (commandHistoryIdx >= commandHistory.length)
commandHistoryIdx = 0;
if (commandHistoryIdx >= 0 && commandHistoryIdx < commandHistory.length)
document.getElementById("command-text").value = commandHistory[commandHistoryIdx];
}
}
});
}
function onOpen(event) {
clearTimeout(connectTimeout);
terminalWrite("[WebSerial] Connected...");
document.getElementById("command-button").disabled = false;
document.getElementById("command-text").disabled = false;
}
function onError(e) {
console.log("[WebSerial] Error!", e);
websocket.close();
}
function onClose(e) {
console.log("[WebSerial] Connection closed.", e);
}
function onMessage(event) {
if (event.data == 'pong') {
clearTimeout(pingTimeout);
pingTimeout = false;
} else {
terminalWrite(event.data);
}
}
function terminalWrite(raw) {
if (enableTimestamp) {
let now = new Date();
raw = "[" + now.toLocaleTimeString() + "] " + raw + "\n";
}
textArea.value += raw + "\n";
if (!enableFlowLock) {
textArea.scrollTop = textArea.scrollHeight;
}
}
function terminalClean() {
textArea.value = "";
textArea.scrollTop = textArea.scrollHeight;
}
function sendCommand() {
let cmd = document.getElementById("command-text").value;
console.log('send command: ', cmd);
websocket.send(cmd);
commandHistory.push(cmd);
console.log('history size: ', commandHistory.length);
if (commandHistory.length > 20) {
console.log('history cleanup');
commandHistory.splice(0, commandHistory.length - 20);
console.log('history size: ', commandHistory.length);
}
commandHistoryIdx = commandHistory.length;
document.getElementById("command-text").value = "";
localStorage.history = JSON.stringify(commandHistory);
}
setInterval(() => {
if (!pingTimeout && websocket.readyState == WebSocket.OPEN) {
pingTimeout = setTimeout(() => {
terminalWrite("[WebSerial] Ping timeout.");
websocket.close();
initWebSocket();
}, 3000);
websocket.send("ping");
}
}, 2000);
window.addEventListener("DOMContentLoaded", function () {
initWebPage();
}, false);
</script>
</html>

View File

@@ -0,0 +1,240 @@
{
"name": "frontend",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@gfx/zopfli": "^1.0.15",
"html-minifier-terser": "^7.1.0"
}
},
"node_modules/@gfx/zopfli": {
"version": "1.0.15",
"license": "Apache-2.0",
"dependencies": {
"base64-js": "^1.3.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3",
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.1",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.1.2",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.5",
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.19",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/acorn": {
"version": "8.10.0",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"license": "MIT"
},
"node_modules/camel-case": {
"version": "4.1.2",
"license": "MIT",
"dependencies": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
}
},
"node_modules/clean-css": {
"version": "5.3.2",
"license": "MIT",
"dependencies": {
"source-map": "~0.6.0"
},
"engines": {
"node": ">= 10.0"
}
},
"node_modules/commander": {
"version": "10.0.1",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/dot-case": {
"version": "3.0.4",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/entities": {
"version": "4.5.0",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/html-minifier-terser": {
"version": "7.2.0",
"license": "MIT",
"dependencies": {
"camel-case": "^4.1.2",
"clean-css": "~5.3.2",
"commander": "^10.0.0",
"entities": "^4.4.0",
"param-case": "^3.0.4",
"relateurl": "^0.2.7",
"terser": "^5.15.1"
},
"bin": {
"html-minifier-terser": "cli.js"
},
"engines": {
"node": "^14.13.1 || >=16.0.0"
}
},
"node_modules/lower-case": {
"version": "2.0.2",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/no-case": {
"version": "3.0.4",
"license": "MIT",
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node_modules/param-case": {
"version": "3.0.4",
"license": "MIT",
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/pascal-case": {
"version": "3.1.2",
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/relateurl": {
"version": "0.2.7",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/terser": {
"version": "5.21.0",
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"license": "MIT"
},
"node_modules/tslib": {
"version": "2.6.2",
"license": "0BSD"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"scripts": {
"build": "node finalize.js"
},
"dependencies": {
"@gfx/zopfli": "^1.0.15",
"html-minifier-terser": "^7.1.0"
}
}

177
lib/WebSerialLite/frontend/pnpm-lock.yaml generated Normal file
View File

@@ -0,0 +1,177 @@
lockfileVersion: 5.3
specifiers:
'@gfx/zopfli': ^1.0.15
html-minifier-terser: ^7.1.0
dependencies:
'@gfx/zopfli': 1.0.15
html-minifier-terser: 7.1.0
packages:
/@gfx/zopfli/1.0.15:
resolution: {integrity: sha512-7mBgpi7UD82fsff5ThQKet0uBTl4BYerQuc+/qA1ELTwWEiIedRTcD3JgiUu9wwZ2kytW8JOb165rSdAt8PfcQ==}
engines: {node: '>= 8'}
dependencies:
base64-js: 1.5.1
dev: false
/@jridgewell/gen-mapping/0.3.2:
resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==}
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.14
'@jridgewell/trace-mapping': 0.3.17
dev: false
/@jridgewell/resolve-uri/3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'}
dev: false
/@jridgewell/set-array/1.1.2:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
engines: {node: '>=6.0.0'}
dev: false
/@jridgewell/source-map/0.3.2:
resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==}
dependencies:
'@jridgewell/gen-mapping': 0.3.2
'@jridgewell/trace-mapping': 0.3.17
dev: false
/@jridgewell/sourcemap-codec/1.4.14:
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
dev: false
/@jridgewell/trace-mapping/0.3.17:
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
dependencies:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
dev: false
/acorn/8.8.2:
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: false
/base64-js/1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: false
/buffer-from/1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
dev: false
/camel-case/4.1.2:
resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
dependencies:
pascal-case: 3.1.2
tslib: 2.5.0
dev: false
/clean-css/5.2.0:
resolution: {integrity: sha512-2639sWGa43EMmG7fn8mdVuBSs6HuWaSor+ZPoFWzenBc6oN+td8YhTfghWXZ25G1NiiSvz8bOFBS7PdSbTiqEA==}
engines: {node: '>= 10.0'}
dependencies:
source-map: 0.6.1
dev: false
/commander/2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
dev: false
/commander/9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
engines: {node: ^12.20.0 || >=14}
dev: false
/dot-case/3.0.4:
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
dependencies:
no-case: 3.0.4
tslib: 2.5.0
dev: false
/entities/4.4.0:
resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==}
engines: {node: '>=0.12'}
dev: false
/html-minifier-terser/7.1.0:
resolution: {integrity: sha512-BvPO2S7Ip0Q5qt+Y8j/27Vclj6uHC6av0TMoDn7/bJPhMWHI2UtR2e/zEgJn3/qYAmxumrGp9q4UHurL6mtW9Q==}
engines: {node: ^14.13.1 || >=16.0.0}
hasBin: true
dependencies:
camel-case: 4.1.2
clean-css: 5.2.0
commander: 9.5.0
entities: 4.4.0
param-case: 3.0.4
relateurl: 0.2.7
terser: 5.16.3
dev: false
/lower-case/2.0.2:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
dependencies:
tslib: 2.5.0
dev: false
/no-case/3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
dependencies:
lower-case: 2.0.2
tslib: 2.5.0
dev: false
/param-case/3.0.4:
resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==}
dependencies:
dot-case: 3.0.4
tslib: 2.5.0
dev: false
/pascal-case/3.1.2:
resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
dependencies:
no-case: 3.0.4
tslib: 2.5.0
dev: false
/relateurl/0.2.7:
resolution: {integrity: sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=}
engines: {node: '>= 0.10'}
dev: false
/source-map-support/0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
dependencies:
buffer-from: 1.1.2
source-map: 0.6.1
dev: false
/source-map/0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
dev: false
/terser/5.16.3:
resolution: {integrity: sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==}
engines: {node: '>=10'}
hasBin: true
dependencies:
'@jridgewell/source-map': 0.3.2
acorn: 8.8.2
commander: 2.20.3
source-map-support: 0.5.21
dev: false
/tslib/2.5.0:
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
dev: false