UNPKG

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