tasmota-esp-web-tools 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.devcontainer/Dockerfile +16 -0
  2. package/.devcontainer/devcontainer.json +44 -0
  3. package/.github/dependabot.yml +10 -0
  4. package/.github/release-drafter.yml +12 -0
  5. package/.github/workflows/ci.yml +22 -0
  6. package/.github/workflows/npmpublish.yml +22 -0
  7. package/.github/workflows/release-drafter.yml +14 -0
  8. package/.prettierignore +1 -0
  9. package/README.md +68 -0
  10. package/dist/components/ewt-button.d.ts +9 -0
  11. package/dist/components/ewt-button.js +17 -0
  12. package/dist/components/ewt-checkbox.d.ts +9 -0
  13. package/dist/components/ewt-checkbox.js +6 -0
  14. package/dist/components/ewt-circular-progress.d.ts +9 -0
  15. package/dist/components/ewt-circular-progress.js +6 -0
  16. package/dist/components/ewt-console.d.ts +20 -0
  17. package/dist/components/ewt-console.js +141 -0
  18. package/dist/components/ewt-dialog.d.ts +9 -0
  19. package/dist/components/ewt-dialog.js +14 -0
  20. package/dist/components/ewt-formfield.d.ts +9 -0
  21. package/dist/components/ewt-formfield.js +6 -0
  22. package/dist/components/ewt-icon-button.d.ts +9 -0
  23. package/dist/components/ewt-icon-button.js +6 -0
  24. package/dist/components/ewt-list-item.d.ts +9 -0
  25. package/dist/components/ewt-list-item.js +6 -0
  26. package/dist/components/ewt-select.d.ts +9 -0
  27. package/dist/components/ewt-select.js +15 -0
  28. package/dist/components/ewt-textfield.d.ts +9 -0
  29. package/dist/components/ewt-textfield.js +15 -0
  30. package/dist/components/svg.d.ts +3 -0
  31. package/dist/components/svg.js +24 -0
  32. package/dist/connect.d.ts +3 -0
  33. package/dist/connect.js +33 -0
  34. package/dist/const.d.ts +94 -0
  35. package/dist/const.js +1 -0
  36. package/dist/flash.d.ts +4 -0
  37. package/dist/flash.js +191 -0
  38. package/dist/install-button.d.ts +17 -0
  39. package/dist/install-button.js +96 -0
  40. package/dist/install-dialog.d.ts +70 -0
  41. package/dist/install-dialog.js +899 -0
  42. package/dist/no-port-picked/index.d.ts +2 -0
  43. package/dist/no-port-picked/index.js +7 -0
  44. package/dist/no-port-picked/no-port-picked-dialog.d.ts +15 -0
  45. package/dist/no-port-picked/no-port-picked-dialog.js +149 -0
  46. package/dist/pages/ewt-page-message.d.ts +14 -0
  47. package/dist/pages/ewt-page-message.js +34 -0
  48. package/dist/pages/ewt-page-progress.d.ts +14 -0
  49. package/dist/pages/ewt-page-progress.js +39 -0
  50. package/dist/styles.d.ts +1 -0
  51. package/dist/styles.js +32 -0
  52. package/dist/util/chip-family-name.d.ts +3 -0
  53. package/dist/util/chip-family-name.js +17 -0
  54. package/dist/util/console-color.d.ts +19 -0
  55. package/dist/util/console-color.js +265 -0
  56. package/dist/util/file-download.d.ts +2 -0
  57. package/dist/util/file-download.js +15 -0
  58. package/dist/util/fire-event.d.ts +5 -0
  59. package/dist/util/fire-event.js +12 -0
  60. package/dist/util/line-break-transformer.d.ts +5 -0
  61. package/dist/util/line-break-transformer.js +17 -0
  62. package/dist/util/manifest.d.ts +2 -0
  63. package/dist/util/manifest.js +12 -0
  64. package/dist/util/sleep.d.ts +1 -0
  65. package/dist/util/sleep.js +1 -0
  66. package/dist/web/connect-3012e6dd.js +886 -0
  67. package/dist/web/esp32-5f88817f.js +1 -0
  68. package/dist/web/esp32c3-596796ad.js +1 -0
  69. package/dist/web/esp32s2-f7a69530.js +1 -0
  70. package/dist/web/esp32s3-314fbacd.js +1 -0
  71. package/dist/web/esp8266-c68f89af.js +1 -0
  72. package/dist/web/index-f110c132.js +126 -0
  73. package/dist/web/install-button.js +1 -0
  74. package/package.json +36 -0
  75. package/rollup.config.js +28 -0
  76. package/script/build +8 -0
  77. package/script/develop +17 -0
  78. package/script/stubgen.py +161 -0
  79. package/src/components/ewt-button.ts +25 -0
  80. package/src/components/ewt-checkbox.ts +14 -0
  81. package/src/components/ewt-circular-progress.ts +14 -0
  82. package/src/components/ewt-console.ts +163 -0
  83. package/src/components/ewt-dialog.ts +22 -0
  84. package/src/components/ewt-formfield.ts +14 -0
  85. package/src/components/ewt-icon-button.ts +14 -0
  86. package/src/components/ewt-list-item.ts +14 -0
  87. package/src/components/ewt-select.ts +23 -0
  88. package/src/components/ewt-textfield.ts +23 -0
  89. package/src/components/svg.ts +27 -0
  90. package/src/connect.ts +42 -0
  91. package/src/const.ts +101 -0
  92. package/src/flash.ts +240 -0
  93. package/src/install-button.ts +128 -0
  94. package/src/install-dialog.ts +981 -0
  95. package/src/no-port-picked/index.ts +10 -0
  96. package/src/no-port-picked/no-port-picked-dialog.ts +158 -0
  97. package/src/pages/ewt-page-message.ts +39 -0
  98. package/src/pages/ewt-page-progress.ts +44 -0
  99. package/src/styles.ts +34 -0
  100. package/src/util/chip-family-name.ts +28 -0
  101. package/src/util/console-color.ts +283 -0
  102. package/src/util/file-download.ts +17 -0
  103. package/src/util/fire-event.ts +20 -0
  104. package/src/util/line-break-transformer.ts +20 -0
  105. package/src/util/manifest.ts +18 -0
  106. package/src/util/sleep.ts +2 -0
  107. package/static/logos/canairio.png +0 -0
  108. package/static/logos/espeasy.png +0 -0
  109. package/static/logos/esphome.svg +1 -0
  110. package/static/logos/tasmota.svg +1 -0
  111. package/static/logos/wled.png +0 -0
  112. package/static/screenshots/dashboard.png +0 -0
  113. package/static/screenshots/logs.png +0 -0
  114. package/static/social.png +0 -0
  115. package/tsconfig.json +21 -0
@@ -0,0 +1,10 @@
1
+ import "./no-port-picked-dialog";
2
+
3
+ export const openNoPortPickedDialog = async (
4
+ doTryAgain?: () => void
5
+ ): Promise<boolean> => {
6
+ const dialog = document.createElement("ewt-no-port-picked-dialog");
7
+ dialog.doTryAgain = doTryAgain;
8
+ document.body.append(dialog);
9
+ return true;
10
+ };
@@ -0,0 +1,158 @@
1
+ import { LitElement, html, css, svg } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+ import "../components/ewt-dialog";
4
+ import "../components/ewt-button";
5
+ import { dialogStyles } from "../styles";
6
+
7
+ const cloudDownload = svg`
8
+ <svg
9
+ version="1.1"
10
+ id="Capa_1"
11
+ xmlns="http://www.w3.org/2000/svg"
12
+ xmlns:xlink="http://www.w3.org/1999/xlink"
13
+ x="0px"
14
+ y="0px"
15
+ viewBox="0 0 510.322 510.322"
16
+ xml:space="preserve"
17
+ style="width: 28px; vertical-align: middle;"
18
+ >
19
+ <g>
20
+ <path
21
+ style="fill:currentColor;"
22
+ d="M429.064,159.505c0-0.151,0.086-1.057,0.086-1.057c0-75.282-61.261-136.521-136.543-136.521 c-52.244,0-97.867,30.587-120.753,76.339c-11.67-9.081-25.108-15.682-40.273-15.682c-37.166,0-67.387,30.199-67.387,67.387 c0,0,0.453,3.279,0.798,5.824C27.05,168.716,0,203.423,0,244.516c0,25.389,9.901,49.268,27.848,67.171 c17.968,17.99,41.804,27.869,67.193,27.869h130.244v46.83h-54.66l97.694,102.008l95.602-102.008h-54.66v-46.83H419.25 c50.174,0,91.072-40.855,91.072-90.986C510.3,201.827,474.428,164.639,429.064,159.505z M419.207,312.744H309.26v-55.545h-83.975 v55.545H95.019c-18.184,0-35.333-7.075-48.211-19.996c-12.878-12.878-19.953-30.005-19.953-48.189 c0-32.68,23.21-60.808,55.264-66.956l12.511-2.394l-2.092-14.431l-1.488-10.785c0-22.347,18.184-40.51,40.531-40.51 c13.266,0,25.691,6.514,33.305,17.408l15.229,21.873l8.52-25.303c15.013-44.652,56.796-74.656,103.906-74.656 c60.506,0,109.709,49.203,109.709,109.644l-1.337,25.712l15.121,0.302l3.149-0.086c35.419,0,64.216,28.797,64.216,64.216 C483.401,283.969,454.604,312.744,419.207,312.744z"
23
+ />
24
+ </g>
25
+ </svg>
26
+ `;
27
+
28
+ @customElement("ewt-no-port-picked-dialog")
29
+ class EwtNoPortPickedDialog extends LitElement {
30
+ public doTryAgain?: () => void;
31
+
32
+ public render() {
33
+ return html`
34
+ <ewt-dialog
35
+ open
36
+ heading="No port selected"
37
+ scrimClickAction
38
+ @closed=${this._handleClose}
39
+ >
40
+ <div>
41
+ If you didn't select a port because you didn't see your device listed,
42
+ try the following steps:
43
+ </div>
44
+ <ol>
45
+ <li>
46
+ Make sure that the device is connected to this computer (the one
47
+ that runs the browser that shows this website)
48
+ </li>
49
+ <li>
50
+ Most devices have a tiny light when it is powered on. If yours has
51
+ one, make sure it is on.
52
+ </li>
53
+ <li>
54
+ Make sure that the USB cable you use can be used for data and is not
55
+ a power-only cable.
56
+ </li>
57
+ <li>
58
+ Make sure you have the right drivers installed. Below are the
59
+ drivers for common chips used in ESP devices:
60
+ <ul>
61
+ <li>
62
+ CP2102 drivers:
63
+ <a
64
+ href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers"
65
+ target="_blank"
66
+ rel="noopener"
67
+ >Windows & Mac</a
68
+ >
69
+ </li>
70
+ <li>
71
+ CH342, CH343, CH9102 drivers:
72
+ <a
73
+ href="https://www.wch.cn/downloads/CH343SER_ZIP.html"
74
+ target="_blank"
75
+ rel="noopener"
76
+ >Windows</a
77
+ >,
78
+ <a
79
+ href="https://www.wch.cn/downloads/CH34XSER_MAC_ZIP.html"
80
+ target="_blank"
81
+ rel="noopener"
82
+ >Mac</a
83
+ >
84
+ <br />
85
+ (download via blue button with ${cloudDownload} icon)
86
+ </li>
87
+ <li>
88
+ CH340, CH341 drivers:
89
+ <a
90
+ href="https://www.wch.cn/downloads/CH341SER_ZIP.html"
91
+ target="_blank"
92
+ rel="noopener"
93
+ >Windows</a
94
+ >,
95
+ <a
96
+ href="https://www.wch.cn/downloads/CH341SER_MAC_ZIP.html"
97
+ target="_blank"
98
+ rel="noopener"
99
+ >Mac</a
100
+ >
101
+ <br />
102
+ (download via blue button with ${cloudDownload} icon)
103
+ </li>
104
+ </ul>
105
+ </li>
106
+ </ol>
107
+ ${this.doTryAgain
108
+ ? html`
109
+ <ewt-button
110
+ slot="primaryAction"
111
+ dialogAction="close"
112
+ label="Try Again"
113
+ @click=${this.doTryAgain}
114
+ ></ewt-button>
115
+
116
+ <ewt-button
117
+ no-attention
118
+ slot="secondaryAction"
119
+ dialogAction="close"
120
+ label="Cancel"
121
+ ></ewt-button>
122
+ `
123
+ : html`
124
+ <ewt-button
125
+ slot="primaryAction"
126
+ dialogAction="close"
127
+ label="Close"
128
+ ></ewt-button>
129
+ `}
130
+ </ewt-dialog>
131
+ `;
132
+ }
133
+
134
+ private async _handleClose() {
135
+ this.parentNode!.removeChild(this);
136
+ }
137
+
138
+ static styles = [
139
+ dialogStyles,
140
+ css`
141
+ li + li,
142
+ li > ul {
143
+ margin-top: 8px;
144
+ }
145
+ ul,
146
+ ol {
147
+ margin-bottom: 0;
148
+ padding-left: 1.5em;
149
+ }
150
+ `,
151
+ ];
152
+ }
153
+
154
+ declare global {
155
+ interface HTMLElementTagNameMap {
156
+ "ewt-no-port-picked-dialog": EwtNoPortPickedDialog;
157
+ }
158
+ }
@@ -0,0 +1,39 @@
1
+ import { LitElement, html, css, TemplateResult } from "lit";
2
+ import { property } from "lit/decorators.js";
3
+ import "../components/ewt-circular-progress";
4
+
5
+ class EwtPageMessage extends LitElement {
6
+ @property() icon!: string;
7
+
8
+ @property() label!: string | TemplateResult;
9
+
10
+ render() {
11
+ return html`
12
+ <div class="icon">${this.icon}</div>
13
+ ${this.label}
14
+ `;
15
+ }
16
+
17
+ static styles = css`
18
+ :host {
19
+ display: flex;
20
+ flex-direction: column;
21
+ text-align: center;
22
+ }
23
+ .icon {
24
+ font-size: 50px;
25
+ line-height: 80px;
26
+ color: black;
27
+ }
28
+ ewt-circular-progress {
29
+ margin-bottom: 16px;
30
+ }
31
+ `;
32
+ }
33
+ customElements.define("ewt-page-message", EwtPageMessage);
34
+
35
+ declare global {
36
+ interface HTMLElementTagNameMap {
37
+ "ewt-page-message": EwtPageMessage;
38
+ }
39
+ }
@@ -0,0 +1,44 @@
1
+ import { LitElement, html, css, TemplateResult } from "lit";
2
+ import { property } from "lit/decorators.js";
3
+ import "../components/ewt-circular-progress";
4
+
5
+ class EwtPageProgress extends LitElement {
6
+ @property() label!: string | TemplateResult;
7
+
8
+ @property() progress: number | undefined;
9
+
10
+ render() {
11
+ return html`
12
+ <div>
13
+ <ewt-circular-progress
14
+ active
15
+ ?indeterminate=${this.progress === undefined}
16
+ .progress=${this.progress !== undefined
17
+ ? this.progress / 100
18
+ : undefined}
19
+ density="8"
20
+ ></ewt-circular-progress>
21
+ ${this.progress !== undefined ? html`<div>${this.progress}%</div>` : ""}
22
+ </div>
23
+ ${this.label}
24
+ `;
25
+ }
26
+
27
+ static styles = css`
28
+ :host {
29
+ display: flex;
30
+ flex-direction: column;
31
+ text-align: center;
32
+ }
33
+ ewt-circular-progress {
34
+ margin-bottom: 16px;
35
+ }
36
+ `;
37
+ }
38
+ customElements.define("ewt-page-progress", EwtPageProgress);
39
+
40
+ declare global {
41
+ interface HTMLElementTagNameMap {
42
+ "ewt-page-progress": EwtPageProgress;
43
+ }
44
+ }
package/src/styles.ts ADDED
@@ -0,0 +1,34 @@
1
+ import { css } from "lit";
2
+
3
+ // We set font-size to 16px and all the mdc typography styles
4
+ // because it defaults to rem, which means that the font-size
5
+ // of the host website would influence the ESP Web Tools dialog.
6
+
7
+ export const dialogStyles = css`
8
+ :host {
9
+ --mdc-theme-primary: var(--improv-primary-color, #03a9f4);
10
+ --mdc-theme-on-primary: var(--improv-on-primary-color, #fff);
11
+ --improv-danger-color: #db4437;
12
+ --improv-text-color: rgba(0, 0, 0, 0.6);
13
+ --mdc-theme-text-primary-on-background: var(--improv-text-color);
14
+ --mdc-dialog-content-ink-color: var(--improv-text-color);
15
+ text-align: left;
16
+ font-size: 16px;
17
+ --mdc-typography-headline6-font-size: 1.25em;
18
+ --mdc-typography-headline6-line-height: 2em;
19
+ --mdc-typography-body1-font-size: 1em;
20
+ --mdc-typography-body1-line-height: 1.5em;
21
+ --mdc-typography-button-font-size: 0.875em;
22
+ --mdc-typography-button-line-height: 2.25em;
23
+ --mdc-typography-subtitle1-font-size: 1em;
24
+ --mdc-typography-subtitle1-line-height: 1.75em;
25
+ }
26
+
27
+ a {
28
+ color: var(--improv-primary-color, #03a9f4);
29
+ }
30
+
31
+ a.button {
32
+ text-decoration: none;
33
+ }
34
+ `;
@@ -0,0 +1,28 @@
1
+ import {
2
+ CHIP_FAMILY_ESP32,
3
+ CHIP_FAMILY_ESP32S2,
4
+ CHIP_FAMILY_ESP32S3,
5
+ CHIP_FAMILY_ESP8266,
6
+ CHIP_FAMILY_ESP32C3,
7
+ ESPLoader,
8
+ } from "tasmota-webserial-esptool";
9
+ import type { BaseFlashState } from "../const";
10
+
11
+ export const getChipFamilyName = (
12
+ esploader: ESPLoader
13
+ ): NonNullable<BaseFlashState["chipFamily"]> => {
14
+ switch (esploader.chipFamily) {
15
+ case CHIP_FAMILY_ESP32:
16
+ return "ESP32";
17
+ case CHIP_FAMILY_ESP8266:
18
+ return "ESP8266";
19
+ case CHIP_FAMILY_ESP32S2:
20
+ return "ESP32-S2";
21
+ case CHIP_FAMILY_ESP32S3:
22
+ return "ESP32-S3";
23
+ case CHIP_FAMILY_ESP32C3:
24
+ return "ESP32-C3";
25
+ default:
26
+ return "Unknown Chip";
27
+ }
28
+ };
@@ -0,0 +1,283 @@
1
+ interface ConsoleState {
2
+ bold: boolean;
3
+ italic: boolean;
4
+ underline: boolean;
5
+ strikethrough: boolean;
6
+ foregroundColor: string | null;
7
+ backgroundColor: string | null;
8
+ carriageReturn: boolean;
9
+ secret: boolean;
10
+ }
11
+
12
+ export class ColoredConsole {
13
+ public state: ConsoleState = {
14
+ bold: false,
15
+ italic: false,
16
+ underline: false,
17
+ strikethrough: false,
18
+ foregroundColor: null,
19
+ backgroundColor: null,
20
+ carriageReturn: false,
21
+ secret: false,
22
+ };
23
+
24
+ constructor(public targetElement: HTMLElement) {}
25
+
26
+ logs(): string {
27
+ return this.targetElement.innerText;
28
+ }
29
+
30
+ addLine(line: string) {
31
+ const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g;
32
+ let i = 0;
33
+
34
+ if (this.state.carriageReturn) {
35
+ if (line !== "\n") {
36
+ // don't remove if \r\n
37
+ this.targetElement.removeChild(this.targetElement.lastChild!);
38
+ }
39
+ this.state.carriageReturn = false;
40
+ }
41
+
42
+ if (line.includes("\r")) {
43
+ this.state.carriageReturn = true;
44
+ }
45
+
46
+ const lineSpan = document.createElement("span");
47
+ lineSpan.classList.add("line");
48
+ this.targetElement.appendChild(lineSpan);
49
+
50
+ const addSpan = (content: string) => {
51
+ if (content === "") return;
52
+
53
+ const span = document.createElement("span");
54
+ if (this.state.bold) span.classList.add("log-bold");
55
+ if (this.state.italic) span.classList.add("log-italic");
56
+ if (this.state.underline) span.classList.add("log-underline");
57
+ if (this.state.strikethrough) span.classList.add("log-strikethrough");
58
+ if (this.state.secret) span.classList.add("log-secret");
59
+ if (this.state.foregroundColor !== null)
60
+ span.classList.add(`log-fg-${this.state.foregroundColor}`);
61
+ if (this.state.backgroundColor !== null)
62
+ span.classList.add(`log-bg-${this.state.backgroundColor}`);
63
+ span.appendChild(document.createTextNode(content));
64
+ lineSpan.appendChild(span);
65
+
66
+ if (this.state.secret) {
67
+ const redacted = document.createElement("span");
68
+ redacted.classList.add("log-secret-redacted");
69
+ redacted.appendChild(document.createTextNode("[redacted]"));
70
+ lineSpan.appendChild(redacted);
71
+ }
72
+ };
73
+
74
+ while (true) {
75
+ const match = re.exec(line);
76
+ if (match === null) break;
77
+
78
+ const j = match.index;
79
+ addSpan(line.substring(i, j));
80
+ i = j + match[0].length;
81
+
82
+ if (match[1] === undefined) continue;
83
+
84
+ for (const colorCode of match[1].split(";")) {
85
+ switch (parseInt(colorCode)) {
86
+ case 0:
87
+ // reset
88
+ this.state.bold = false;
89
+ this.state.italic = false;
90
+ this.state.underline = false;
91
+ this.state.strikethrough = false;
92
+ this.state.foregroundColor = null;
93
+ this.state.backgroundColor = null;
94
+ this.state.secret = false;
95
+ break;
96
+ case 1:
97
+ this.state.bold = true;
98
+ break;
99
+ case 3:
100
+ this.state.italic = true;
101
+ break;
102
+ case 4:
103
+ this.state.underline = true;
104
+ break;
105
+ case 5:
106
+ this.state.secret = true;
107
+ break;
108
+ case 6:
109
+ this.state.secret = false;
110
+ break;
111
+ case 9:
112
+ this.state.strikethrough = true;
113
+ break;
114
+ case 22:
115
+ this.state.bold = false;
116
+ break;
117
+ case 23:
118
+ this.state.italic = false;
119
+ break;
120
+ case 24:
121
+ this.state.underline = false;
122
+ break;
123
+ case 29:
124
+ this.state.strikethrough = false;
125
+ break;
126
+ case 30:
127
+ this.state.foregroundColor = "black";
128
+ break;
129
+ case 31:
130
+ this.state.foregroundColor = "red";
131
+ break;
132
+ case 32:
133
+ this.state.foregroundColor = "green";
134
+ break;
135
+ case 33:
136
+ this.state.foregroundColor = "yellow";
137
+ break;
138
+ case 34:
139
+ this.state.foregroundColor = "blue";
140
+ break;
141
+ case 35:
142
+ this.state.foregroundColor = "magenta";
143
+ break;
144
+ case 36:
145
+ this.state.foregroundColor = "cyan";
146
+ break;
147
+ case 37:
148
+ this.state.foregroundColor = "white";
149
+ break;
150
+ case 39:
151
+ this.state.foregroundColor = null;
152
+ break;
153
+ case 41:
154
+ this.state.backgroundColor = "red";
155
+ break;
156
+ case 42:
157
+ this.state.backgroundColor = "green";
158
+ break;
159
+ case 43:
160
+ this.state.backgroundColor = "yellow";
161
+ break;
162
+ case 44:
163
+ this.state.backgroundColor = "blue";
164
+ break;
165
+ case 45:
166
+ this.state.backgroundColor = "magenta";
167
+ break;
168
+ case 46:
169
+ this.state.backgroundColor = "cyan";
170
+ break;
171
+ case 47:
172
+ this.state.backgroundColor = "white";
173
+ break;
174
+ case 40:
175
+ case 49:
176
+ this.state.backgroundColor = null;
177
+ break;
178
+ }
179
+ }
180
+ }
181
+ addSpan(line.substring(i));
182
+
183
+ if (
184
+ this.targetElement.scrollTop + 56 >=
185
+ this.targetElement.scrollHeight - this.targetElement.offsetHeight
186
+ ) {
187
+ // at bottom
188
+ this.targetElement.scrollTop = this.targetElement.scrollHeight;
189
+ }
190
+ }
191
+ }
192
+
193
+ export const coloredConsoleStyles = `
194
+ .log {
195
+ flex: 1;
196
+ background-color: #1c1c1c;
197
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
198
+ monospace;
199
+ font-size: 12px;
200
+ padding: 16px;
201
+ overflow: auto;
202
+ line-height: 1.45;
203
+ border-radius: 3px;
204
+ white-space: pre-wrap;
205
+ overflow-wrap: break-word;
206
+ color: #ddd;
207
+ }
208
+
209
+ .log-bold {
210
+ font-weight: bold;
211
+ }
212
+ .log-italic {
213
+ font-style: italic;
214
+ }
215
+ .log-underline {
216
+ text-decoration: underline;
217
+ }
218
+ .log-strikethrough {
219
+ text-decoration: line-through;
220
+ }
221
+ .log-underline.log-strikethrough {
222
+ text-decoration: underline line-through;
223
+ }
224
+ .log-secret {
225
+ -webkit-user-select: none;
226
+ -moz-user-select: none;
227
+ -ms-user-select: none;
228
+ user-select: none;
229
+ }
230
+ .log-secret-redacted {
231
+ opacity: 0;
232
+ width: 1px;
233
+ font-size: 1px;
234
+ }
235
+ .log-fg-black {
236
+ color: rgb(128, 128, 128);
237
+ }
238
+ .log-fg-red {
239
+ color: rgb(255, 0, 0);
240
+ }
241
+ .log-fg-green {
242
+ color: rgb(0, 255, 0);
243
+ }
244
+ .log-fg-yellow {
245
+ color: rgb(255, 255, 0);
246
+ }
247
+ .log-fg-blue {
248
+ color: rgb(0, 0, 255);
249
+ }
250
+ .log-fg-magenta {
251
+ color: rgb(255, 0, 255);
252
+ }
253
+ .log-fg-cyan {
254
+ color: rgb(0, 255, 255);
255
+ }
256
+ .log-fg-white {
257
+ color: rgb(187, 187, 187);
258
+ }
259
+ .log-bg-black {
260
+ background-color: rgb(0, 0, 0);
261
+ }
262
+ .log-bg-red {
263
+ background-color: rgb(255, 0, 0);
264
+ }
265
+ .log-bg-green {
266
+ background-color: rgb(0, 255, 0);
267
+ }
268
+ .log-bg-yellow {
269
+ background-color: rgb(255, 255, 0);
270
+ }
271
+ .log-bg-blue {
272
+ background-color: rgb(0, 0, 255);
273
+ }
274
+ .log-bg-magenta {
275
+ background-color: rgb(255, 0, 255);
276
+ }
277
+ .log-bg-cyan {
278
+ background-color: rgb(0, 255, 255);
279
+ }
280
+ .log-bg-white {
281
+ background-color: rgb(255, 255, 255);
282
+ }
283
+ `;
@@ -0,0 +1,17 @@
1
+ export const fileDownload = (href: string, filename = ""): void => {
2
+ const a = document.createElement("a");
3
+ a.target = "_blank";
4
+ a.href = href;
5
+ a.download = filename;
6
+
7
+ document.body.appendChild(a);
8
+ a.dispatchEvent(new MouseEvent("click"));
9
+ document.body.removeChild(a);
10
+ };
11
+
12
+ export const textDownload = (text: string, filename = ""): void => {
13
+ const blob = new Blob([text], { type: "text/plain" });
14
+ const url = URL.createObjectURL(blob);
15
+ fileDownload(url, filename);
16
+ setTimeout(() => URL.revokeObjectURL(url), 0);
17
+ };
@@ -0,0 +1,20 @@
1
+ export const fireEvent = <Event extends keyof HTMLElementEventMap>(
2
+ eventTarget: EventTarget,
3
+ type: Event,
4
+ // @ts-ignore
5
+ detail?: HTMLElementEventMap[Event]["detail"],
6
+ options?: {
7
+ bubbles?: boolean;
8
+ cancelable?: boolean;
9
+ composed?: boolean;
10
+ }
11
+ ): void => {
12
+ options = options || {};
13
+ const event = new CustomEvent(type, {
14
+ bubbles: options.bubbles === undefined ? true : options.bubbles,
15
+ cancelable: Boolean(options.cancelable),
16
+ composed: options.composed === undefined ? true : options.composed,
17
+ detail,
18
+ });
19
+ eventTarget.dispatchEvent(event);
20
+ };
@@ -0,0 +1,20 @@
1
+ export class LineBreakTransformer implements Transformer<string, string> {
2
+ private chunks = "";
3
+
4
+ transform(
5
+ chunk: string,
6
+ controller: TransformStreamDefaultController<string>
7
+ ) {
8
+ // Append new chunks to existing chunks.
9
+ this.chunks += chunk;
10
+ // For each line breaks in chunks, send the parsed lines out.
11
+ const lines = this.chunks.split("\r\n");
12
+ this.chunks = lines.pop()!;
13
+ lines.forEach((line) => controller.enqueue(line + "\r\n"));
14
+ }
15
+
16
+ flush(controller: TransformStreamDefaultController<string>) {
17
+ // When the stream is closed, flush any remaining chunks out.
18
+ controller.enqueue(this.chunks);
19
+ }
20
+ }
@@ -0,0 +1,18 @@
1
+ import { Manifest } from "../const";
2
+
3
+ export const downloadManifest = async (manifestPath: string) => {
4
+ const manifestURL = new URL(manifestPath, location.toString()).toString();
5
+ const resp = await fetch(manifestURL);
6
+ const manifest: Manifest = await resp.json();
7
+
8
+ if ("new_install_skip_erase" in manifest) {
9
+ console.warn(
10
+ 'Manifest option "new_install_skip_erase" is deprecated. Use "new_install_prompt_erase" instead.'
11
+ );
12
+ if (manifest.new_install_skip_erase) {
13
+ manifest.new_install_prompt_erase = true;
14
+ }
15
+ }
16
+
17
+ return manifest;
18
+ };
@@ -0,0 +1,2 @@
1
+ export const sleep = (time: number) =>
2
+ new Promise((resolve) => setTimeout(resolve, time));
Binary file
Binary file
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 73"><g fill="none" fill-rule="evenodd"><path d="M72.63 16.18V12c0-1.47 1.19-2.66 2.66-2.66 1.47 0 2.66 1.19 2.66 2.66v4.18m-14.27 0V12c0-1.47 1.19-2.66 2.66-2.66A2.65 2.65 0 0 1 69 11.99v4.18m-14.28.01V12c0-1.47 1.19-2.66 2.66-2.66 1.47 0 2.66 1.19 2.66 2.66v4.18m-14.28 0V12c0-1.47 1.19-2.66 2.66-2.66 1.47 0 2.66 1.19 2.66 2.66v4.18m-14.28 0V12c0-1.47 1.19-2.66 2.66-2.66 1.47 0 2.66 1.19 2.66 2.66v4.18m-14.27 0V12c0-1.47 1.19-2.66 2.66-2.66 1.47 0 2.66 1.19 2.66 2.66v4.18M77.95 56.07v4.68c0 1.47-1.19 2.66-2.66 2.66-1.47 0-2.66-1.19-2.66-2.66v-4.68m-3.63 0v4.68c0 1.47-1.19 2.66-2.66 2.66-1.47 0-2.66-1.19-2.66-2.66v-4.68m-3.64 0v4.68c0 1.47-1.19 2.66-2.66 2.66-1.47 0-2.66-1.19-2.66-2.66v-4.68m-3.64 0v4.68c0 1.47-1.19 2.66-2.66 2.66-1.47 0-2.66-1.19-2.66-2.66v-4.68m-3.64 0v4.68c0 1.47-1.19 2.66-2.66 2.66-1.47 0-2.66-1.19-2.66-2.66v-4.68m-3.63.26v4.43c0 1.47-1.19 2.66-2.66 2.66-1.47 0-2.66-1.19-2.66-2.66v-4.43" fill="#fff" stroke="#000" stroke-width="2.178"/><path fill="#fff" stroke="#000" stroke-width="2.42" d="M79.29 16.18H26.51a.97.97 0 0 0-.97.97v37.96c0 .53.43.97.97.97h52.77c.53 0 .97-.43.97-.97V17.15c0-.54-.43-.97-.96-.97z"/><path fill="#000" fill-rule="nonzero" d="M61.6 35.42v-5.07h-1.8v3.28l-6.81-6.81-11.49 11.5h2.87v7.75h17.25v-7.75h2.87z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.961" d="M61.6 35.42v-5.07h-1.8v3.28l-6.81-6.81-11.49 11.5h2.87v7.75h17.25v-7.75h2.87z"/><path d="M25.34 53.77H9.52v-3.89h11.86v-3.89H9.52v-3.88h11.86v-3.89H9.52v-3.89h11.86v-3.88H9.52V18.47" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.159"/></g></svg>