UNPKG

4.81 kBJavaScriptView Raw
1import { ColoredConsole, coloredConsoleStyles } from "../util/console-color";
2import { sleep } from "../util/sleep";
3import { LineBreakTransformer } from "../util/line-break-transformer";
4import { TimestampTransformer } from "../util/timestamp-transformer";
5export class EwtConsole extends HTMLElement {
6 constructor() {
7 super(...arguments);
8 this.allowInput = true;
9 }
10 logs() {
11 var _a;
12 return ((_a = this._console) === null || _a === void 0 ? void 0 : _a.logs()) || "";
13 }
14 connectedCallback() {
15 if (this._console) {
16 return;
17 }
18 const shadowRoot = this.attachShadow({ mode: "open" });
19 shadowRoot.innerHTML = `
20 <style>
21 :host, input {
22 background-color: #1c1c1c;
23 color: #ddd;
24 font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
25 monospace;
26 line-height: 1.45;
27 display: flex;
28 flex-direction: column;
29 }
30 form {
31 display: flex;
32 align-items: center;
33 padding: 0 8px 0 16px;
34 }
35 input {
36 flex: 1;
37 padding: 4px;
38 margin: 0 8px;
39 border: 0;
40 outline: none;
41 }
42 ${coloredConsoleStyles}
43 </style>
44 <div class="log"></div>
45 ${this.allowInput
46 ? `<form>
47 >
48 <input autofocus>
49 </form>
50 `
51 : ""}
52 `;
53 this._console = new ColoredConsole(this.shadowRoot.querySelector("div"));
54 if (this.allowInput) {
55 const input = this.shadowRoot.querySelector("input");
56 this.addEventListener("click", () => {
57 var _a;
58 // Only focus input if user didn't select some text
59 if (((_a = getSelection()) === null || _a === void 0 ? void 0 : _a.toString()) === "") {
60 input.focus();
61 }
62 });
63 input.addEventListener("keydown", (ev) => {
64 if (ev.key === "Enter") {
65 ev.preventDefault();
66 ev.stopPropagation();
67 this._sendCommand();
68 }
69 });
70 }
71 const abortController = new AbortController();
72 const connection = this._connect(abortController.signal);
73 this._cancelConnection = () => {
74 abortController.abort();
75 return connection;
76 };
77 }
78 async _connect(abortSignal) {
79 this.logger.debug("Starting console read loop");
80 try {
81 await this.port
82 .readable.pipeThrough(new TextDecoderStream(), {
83 signal: abortSignal,
84 })
85 .pipeThrough(new TransformStream(new LineBreakTransformer()))
86 .pipeThrough(new TransformStream(new TimestampTransformer()))
87 .pipeTo(new WritableStream({
88 write: (chunk) => {
89 this._console.addLine(chunk.replace("\r", ""));
90 },
91 }));
92 if (!abortSignal.aborted) {
93 this._console.addLine("");
94 this._console.addLine("");
95 this._console.addLine("Terminal disconnected");
96 }
97 }
98 catch (e) {
99 this._console.addLine("");
100 this._console.addLine("");
101 this._console.addLine(`Terminal disconnected: ${e}`);
102 }
103 finally {
104 await sleep(100);
105 this.logger.debug("Finished console read loop");
106 }
107 }
108 async _sendCommand() {
109 const input = this.shadowRoot.querySelector("input");
110 const command = input.value;
111 const encoder = new TextEncoder();
112 const writer = this.port.writable.getWriter();
113 await writer.write(encoder.encode(command + "\r\n"));
114 this._console.addLine(`> ${command}\r\n`);
115 input.value = "";
116 input.focus();
117 try {
118 writer.releaseLock();
119 }
120 catch (err) {
121 console.error("Ignoring release lock error", err);
122 }
123 }
124 async disconnect() {
125 if (this._cancelConnection) {
126 await this._cancelConnection();
127 this._cancelConnection = undefined;
128 }
129 }
130 async reset() {
131 this.logger.debug("Triggering reset");
132 await this.port.setSignals({
133 dataTerminalReady: false,
134 requestToSend: true,
135 });
136 await sleep(250);
137 await this.port.setSignals({
138 dataTerminalReady: false,
139 requestToSend: false,
140 });
141 await sleep(250);
142 await new Promise((resolve) => setTimeout(resolve, 1000));
143 }
144}
145customElements.define("ewt-console", EwtConsole);