forked from tools/josh
Compare commits
5 Commits
ec6e5b01a1
...
f90d6fd223
Author | SHA1 | Date |
---|---|---|
Florine W. Dekker | f90d6fd223 | |
Florine W. Dekker | ddd7524f5f | |
Florine W. Dekker | 9aeb3ec2f9 | |
Florine W. Dekker | 2abf7538c0 | |
Florine W. Dekker | 1c5927815a |
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 F.W. Dekker
|
||||
Copyright (c) 2018 Florine W. Dekker
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
Binary file not shown.
42
package.json
42
package.json
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "fwdekker.com",
|
||||
"version": "0.40.11",
|
||||
"description": "The source code of [my personal website](https://fwdekker.com/).",
|
||||
"author": "F.W. Dekker",
|
||||
"version": "0.40.16",
|
||||
"description": "The JavaScript Online Shell.",
|
||||
"author": "Florine W. Dekker",
|
||||
"browser": "dist/bundle.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.fwdekker.com:FWDekker/fwdekker.com.git"
|
||||
"url": "git@git.fwdekker.com:tools/josh.git"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -18,33 +18,33 @@
|
|||
"coverage": "nyc npm run test"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-cookie": "^2.2.1",
|
||||
"js-cookie": "^3.0.1",
|
||||
"js-sha256": "^0.9.0",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@types/chai": "^4.2.21",
|
||||
"@types/js-cookie": "^2.2.7",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/semver": "^6.2.1",
|
||||
"chai": "^4.3.4",
|
||||
"grunt": "^1.4.1",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
||||
"@types/chai": "^4.3.4",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/semver": "^7.3.13",
|
||||
"chai": "^4.3.7",
|
||||
"grunt": "^1.6.1",
|
||||
"grunt-cli": "^1.4.3",
|
||||
"grunt-contrib-clean": "^2.0.0",
|
||||
"grunt-contrib-clean": "^2.0.1",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-focus": "^1.0.0",
|
||||
"grunt-text-replace": "^0.4.0",
|
||||
"grunt-webpack": "^4.0.3",
|
||||
"jsdom": "^17.0.0",
|
||||
"grunt-webpack": "^5.0.0",
|
||||
"jsdom": "^21.1.0",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"mocha": "^9.1.0",
|
||||
"mocha": "^10.2.0",
|
||||
"nyc": "^15.1.0",
|
||||
"ts-loader": "^9.2.5",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack": "^5.51.1",
|
||||
"webpack-cli": "^4.8.0"
|
||||
"ts-loader": "^9.4.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,64 +1,58 @@
|
|||
/* Main elements */
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
body > main {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
noscript ul {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
#terminal a {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
.fwd-nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#terminal a, #terminal a:link, #terminal a:visited {
|
||||
color: #00FF00;
|
||||
}
|
||||
|
||||
#terminal a:hover {
|
||||
color: #00BF00;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#terminal a:link.dirLink, #terminal a:visited.dirLink {
|
||||
color: #00FF00;
|
||||
}
|
||||
|
||||
#terminal a:link.fileLink, #terminal a:visited.fileLink {
|
||||
color: #FFFF00;
|
||||
}
|
||||
|
||||
.prefixPath, .prefixPath > a:link, .prefixPath > a:visited {
|
||||
color: #008000;
|
||||
.error-message {
|
||||
color: #FF3333;
|
||||
}
|
||||
|
||||
|
||||
/* Mobile support */
|
||||
@media (max-width: 600px) {
|
||||
.wideScreenOnly {
|
||||
.wide-screen-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.smallScreenOnly {
|
||||
.small-screen-only {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.wideScreenOnly {
|
||||
.wide-screen-only {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.smallScreenOnly {
|
||||
.small-screen-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
/* Terminal */
|
||||
#terminal {
|
||||
min-height: 100%;
|
||||
padding: 25px;
|
||||
|
@ -77,20 +71,20 @@ body {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
#terminalInput {
|
||||
#terminal-input {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#terminalInputField {
|
||||
#terminal-input-field {
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#terminalInputField br {
|
||||
#terminal-input-field br {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.terminalInputFieldHidden {
|
||||
.terminal-input-field-hidden {
|
||||
max-width: 1px !important;
|
||||
overflow: hidden !important;
|
||||
overflow-wrap: normal !important;
|
||||
|
@ -98,17 +92,40 @@ body {
|
|||
vertical-align: top !important;
|
||||
}
|
||||
|
||||
#terminalSuggestions {
|
||||
#terminal-suggestions {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.errorMessage {
|
||||
color: #FF3333;
|
||||
/* Links */
|
||||
#terminal a {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
#nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
#terminal a,
|
||||
#terminal a:link,
|
||||
#terminal a:visited {
|
||||
color: #00FF00;
|
||||
}
|
||||
|
||||
#terminal a:hover {
|
||||
color: #00BF00;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#terminal a:link.dir-link,
|
||||
#terminal a:visited.dir-link {
|
||||
color: #00FF00;
|
||||
}
|
||||
|
||||
#terminal a:link.file-link,
|
||||
#terminal a:visited.file-link {
|
||||
color: #FFFF00;
|
||||
}
|
||||
|
||||
.prefix-path,
|
||||
.prefix-path > a:link,
|
||||
.prefix-path > a:visited {
|
||||
color: #008000;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="en" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="author" content="F.W. Dekker" />
|
||||
<meta name="author" content="Florine W. Dekker" />
|
||||
<meta name="application-name" content="FWDekker" />
|
||||
<meta name="description" content="F.W. Dekker's personal website" />
|
||||
<meta name="description" content="Florine W. Dekker's personal website" />
|
||||
<meta name="theme-color" content="#0033cc" />
|
||||
<meta property="og:url" content="https://fwdekker.com/" />
|
||||
<meta property="og:title" content="FWDekker" />
|
||||
<meta property="og:description" content="F.W. Dekker's personal website">
|
||||
<meta property="og:description" content="Florine W. Dekker's personal website">
|
||||
<meta property="og:locale" content="en_GB" />
|
||||
|
||||
<meta name="fwd:nav:target" content="#nav" />
|
||||
<meta name="fwd:nav:highlight-path" content="/" />
|
||||
|
||||
<title>FWDekker</title>
|
||||
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
|
@ -20,17 +23,16 @@
|
|||
<link rel="apple-touch-icon" href="icon_ios.png?v=%%VERSION_NUMBER%%" />
|
||||
<link rel="manifest" href="manifest.json?v=%%VERSION_NUMBER%%">
|
||||
|
||||
<link rel="stylesheet" href="https://static.fwdekker.com/lib/template/2.x.x/template.css" />
|
||||
<link rel="stylesheet" href="https://static.fwdekker.com/fonts/roboto-mono/roboto-mono.css" />
|
||||
<link rel="stylesheet" href="https://static.fwdekker.com/lib/template/3.x.x/template.css?v=%%VERSION_NUMBER%%" />
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<link rel="stylesheet" href="main.css?v=%%VERSION_NUMBER%%" />
|
||||
<script async src="https://stats.fwdekker.com/count.js"
|
||||
data-goatcounter="https://stats.fwdekker.com/count"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="nav"></nav>
|
||||
<main>
|
||||
<div id="nav"></div>
|
||||
|
||||
<!-- Comment out newlines and indents because of `white-space: pre-wrap` in CSS. -->
|
||||
<div id="terminal"><!--
|
||||
--><noscript><!--
|
||||
|
@ -51,24 +53,19 @@
|
|||
--><li><a href="https://fwdekker.com/api/nav/">JSON site map</a></li><!--
|
||||
--></ul><!--
|
||||
--></noscript><!--
|
||||
--><div id="ie-warning" class="hidden"><!--
|
||||
-->This website does not function with Internet Explorer. <!--
|
||||
-->Please install a newer browser such as <!--
|
||||
--><a href="https://www.microsoft.com/en-us/windows/microsoft-edge">Microsoft Edge</a>.<!--
|
||||
--></div><!--
|
||||
--><span id="terminalOutput"></span><!--
|
||||
--><span id="terminalInput"><!--
|
||||
--><span id="terminalInputPrefix"></span><!--
|
||||
--><span id="terminalInputField" contenteditable="true" autocapitalize="none"
|
||||
--><span id="terminal-output"></span><!--
|
||||
--><span id="terminal-input"><!--
|
||||
--><span id="terminal-input-prefix"></span><!--
|
||||
--><span id="terminal-input-field" contenteditable="true" autocapitalize="none"
|
||||
spellcheck="false"></span><!--
|
||||
--></span><!--
|
||||
--><span id="terminalSuggestions"></span><!--
|
||||
--><span id="terminal-suggestions"></span><!--
|
||||
--></div>
|
||||
</main>
|
||||
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<script src="plain.js?v=%%VERSION_NUMBER%%"></script>
|
||||
<script src="https://static.fwdekker.com/lib/template/2.x.x/template.js"></script>
|
||||
<script src="https://static.fwdekker.com/lib/template/3.x.x/template.js?v=%%VERSION_NUMBER%%"></script>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<script type="module" src="bundle.js?v=%%VERSION_NUMBER%%"></script>
|
||||
</body>
|
||||
|
|
|
@ -57,6 +57,9 @@ export class Commands {
|
|||
localStreams.out = this.toStream(input.redirectTargets[1]) ?? localStreams.out;
|
||||
localStreams.err = this.toStream(input.redirectTargets[2]) ?? localStreams.err;
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error))
|
||||
throw Error(`Error while processing redirection error:\n${error}`);
|
||||
|
||||
streams.err.writeLine(`Error while redirecting output:\n${error.message}`);
|
||||
return ExitCode.MISC;
|
||||
}
|
||||
|
@ -136,9 +139,12 @@ export class Commands {
|
|||
} else {
|
||||
return this.interpretBinary(code, this.environment, this.userList, this.fileSystem);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Failed to interpret script '${targetName}'.`, code, e);
|
||||
return e;
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error))
|
||||
throw Error(`Error while processing interpretation error:\n${error}`);
|
||||
|
||||
console.error(`Failed to interpret script '${targetName}'.`, code, error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,7 +655,7 @@ return new Command(
|
|||
const target = josh.util.isStandalone() ? \`target="_blank"\` : "";
|
||||
streams.out.writeLine(
|
||||
\`The source code of this website is ${n}
|
||||
<a href="https://git.fwdekker.com/FWDekker/fwdekker.com" \${target}>available on git</a>. ${n}
|
||||
<a href="https://git.fwdekker.com/tools/josh" \${target}>available on git</a>. ${n}
|
||||
This website also has a <a href="https://fwdekker.com/privacy/">privacy policy</a> to assure you I won't
|
||||
steal your data.
|
||||
|
||||
|
|
|
@ -39,17 +39,17 @@ export class FileSystem {
|
|||
[
|
||||
new User("root", HashProvider.default.hashPassword("g9PjKu"), "/root",
|
||||
"You're a hacker, Harry!"),
|
||||
new User("f", HashProvider.default.hashPassword("password"), undefined,
|
||||
new User("florine", HashProvider.default.hashPassword("password"), undefined,
|
||||
"Who are <i>you</i>?")
|
||||
].map(it => User.toString(it)).join("\n") + "\n"
|
||||
),
|
||||
}),
|
||||
"home": new Directory({
|
||||
"f": new Directory({
|
||||
"florine": new Directory({
|
||||
"pgp-key.pub": new File("https://fwdkr.co/pgp", "lnk"),
|
||||
"privacy-policy.lnk": new File("https://fwdekker.com/privacy/"),
|
||||
"resume.pdf": new File("https://fwdkr.co/cv", "lnk"),
|
||||
"source-code.lnk": new File("https://git.fwdekker.com/FWDekker/fwdekker.com"),
|
||||
"source-code.lnk": new File("https://git.fwdekker.com/tools/josh"),
|
||||
}),
|
||||
}),
|
||||
"root": new Directory({
|
||||
|
@ -573,7 +573,7 @@ export class Directory extends Node {
|
|||
* @param path the path to this node
|
||||
*/
|
||||
nameString(name: string, path: Path): string {
|
||||
return `<a class="dirLink" onclick="execute('${path.toString(true)}; and ls -l')">${name}</a>`;
|
||||
return `<a class="dir-link" onclick="execute('${path.toString(true)}; and ls -l')">${name}</a>`;
|
||||
}
|
||||
|
||||
visit(path: string,
|
||||
|
@ -673,15 +673,15 @@ export class File extends Node {
|
|||
switch (this.mime ?? getFileExtension(name)) {
|
||||
case "jsh": {
|
||||
const script = `execute('${path.toString(true)}'); return false`;
|
||||
return `<a class="fileLink" onclick="${script}">${name}</a>`;
|
||||
return `<a class="file-link" onclick="${script}">${name}</a>`;
|
||||
}
|
||||
case "lnk": {
|
||||
const script = `execute('open ${path.toString(true)}'); return false`;
|
||||
return `<a href="${this.contents}" class="fileLink" onclick="${script}">${name}</a>`;
|
||||
return `<a href="${this.contents}" class="file-link" onclick="${script}">${name}</a>`;
|
||||
}
|
||||
case "txt": {
|
||||
const script = `execute('cat ${path.toString(true)}')`;
|
||||
return `<a class="fileLink" onclick="${script}">${name}</a>`;
|
||||
return `<a class="file-link" onclick="${script}">${name}</a>`;
|
||||
}
|
||||
default:
|
||||
return name;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const {$, doAfterLoad} = (window as any).fwdekker;
|
||||
import * as semver from "semver";
|
||||
// @ts-ignore
|
||||
const {$, doAfterLoad, nav} = window.fwdekker;
|
||||
|
||||
import {Persistence} from "./Persistence";
|
||||
import {ExpectedGoodbyeError} from "./Shared";
|
||||
import {Terminal} from "./Terminal";
|
||||
|
@ -32,13 +32,13 @@ doAfterLoad(() => {
|
|||
if (semver.lt(userVersion, latestVersion)) {
|
||||
Persistence.reset();
|
||||
Persistence.setWasUpdated(true); // Message is displayed after reload
|
||||
location.reload(true);
|
||||
location.reload();
|
||||
throw new ExpectedGoodbyeError("Goodbye");
|
||||
}
|
||||
|
||||
if (Persistence.getWasUpdated()) {
|
||||
$("#terminalOutput").innerHTML = "" +
|
||||
"<span class=\"errorMessage\">The terminal application has been updated. To prevent unexpected errors, " +
|
||||
$("#terminal-output").innerHTML = "" +
|
||||
"<span class=\"error-message\">The terminal application has been updated. To prevent unexpected errors, " +
|
||||
"all previous user changes have been reset.</span>\n\n";
|
||||
Persistence.setWasUpdated(false);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ doAfterLoad(() => {
|
|||
doAfterLoad(() => {
|
||||
if (!Persistence.getPoweroff()) return;
|
||||
|
||||
$("#terminalOutput").innerText = "Could not connect to fwdekker.com. Retrying in 10 seconds.";
|
||||
$("#terminal-output").innerText = "Could not connect to fwdekker.com. Retrying in 10 seconds.";
|
||||
setTimeout(() => location.reload(), 10000);
|
||||
throw new ExpectedGoodbyeError("Goodbye");
|
||||
});
|
||||
|
@ -61,14 +61,12 @@ doAfterLoad(() => {
|
|||
* Initializes the application.
|
||||
*/
|
||||
doAfterLoad(async () => {
|
||||
$("#nav").appendChild(nav("/"));
|
||||
|
||||
window.terminal = new Terminal(
|
||||
$("#terminal"),
|
||||
$("#terminalInputField"),
|
||||
$("#terminalOutput"),
|
||||
$("#terminalInputPrefix"),
|
||||
$("#terminalSuggestions")
|
||||
$("#terminal-input-field"),
|
||||
$("#terminal-output"),
|
||||
$("#terminal-input-prefix"),
|
||||
$("#terminal-suggestions")
|
||||
);
|
||||
window.execute = (command: string) => window.terminal.processInput(command);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import * as Cookies from "js-cookie";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
import {Environment} from "./Environment";
|
||||
import {Directory, FileSystem, Node} from "./FileSystem";
|
||||
import {InputHistory} from "./InputHistory";
|
||||
|
@ -133,7 +134,7 @@ export class Persistence {
|
|||
* @param value whether the server is "turned off"
|
||||
*/
|
||||
static setPoweroff(value: boolean): void {
|
||||
Cookies.set("poweroff", "" + value, {
|
||||
Cookies?.set("poweroff", "" + value, {
|
||||
expires: new Date(new Date().setSeconds(new Date().getSeconds() + 30)),
|
||||
path: "/",
|
||||
secure: true,
|
||||
|
@ -161,10 +162,10 @@ export class Persistence {
|
|||
|
||||
// Check user in environment
|
||||
if (!environment.has("user")) {
|
||||
environment.set("user", "f");
|
||||
environment.set("user", "florine");
|
||||
} else if (environment.get("user") !== "" && !userList.has(environment.get("user"))) {
|
||||
console.warn(`Invalid user '${environment.get("user")}' in environment.`);
|
||||
environment.set("user", "f");
|
||||
environment.set("user", "florine");
|
||||
}
|
||||
|
||||
// Set home directory
|
||||
|
|
|
@ -16,7 +16,7 @@ const asciiHeader = ` ________ _______ _ _
|
|||
* large enough.
|
||||
*/
|
||||
export const asciiHeaderHtml =
|
||||
`<span class="wideScreenOnly">${asciiHeader}</span><span class="smallScreenOnly"><b><u>FWDekker</u></b></span>`;
|
||||
`<span class="wide-screen-only">${asciiHeader}</span><span class="small-screen-only"><b><u>FWDekker</u></b></span>`;
|
||||
|
||||
/**
|
||||
* A function that does nothing.
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import {Commands, ExitCode} from "./Commands";
|
||||
import {Environment} from "./Environment";
|
||||
import {Directory, FileSystem, Path} from "./FileSystem";
|
||||
import {InputArgs} from "./InputArgs";
|
||||
import {InputHistory} from "./InputHistory";
|
||||
import {Globber, InputParser} from "./InputParser";
|
||||
import {Persistence} from "./Persistence";
|
||||
import {asciiHeaderHtml, ExpectedGoodbyeError, IllegalStateError, isStandalone} from "./Shared";
|
||||
import {OutputStream, StreamSet} from "./Stream";
|
||||
import {asciiHeaderHtml, ExpectedGoodbyeError, isStandalone} from "./Shared";
|
||||
import {StreamSet} from "./Stream";
|
||||
import {EscapeCharacters} from "./Terminal";
|
||||
import {UserList} from "./UserList";
|
||||
|
||||
|
@ -69,9 +68,9 @@ export class Shell {
|
|||
const target = isStandalone() ? `target="_blank"` : "";
|
||||
return `${asciiHeaderHtml}
|
||||
|
||||
PhD student Computer Science <span class="smallScreenOnly">
|
||||
PhD student Computer Science <span class="small-screen-only">
|
||||
</span>@ <a href="https://www.tudelft.nl/en/" ${target}>TU Delft</a>, the Netherlands
|
||||
<span class="wideScreenOnly">${(new Date()).toISOString()}
|
||||
<span class="wide-screen-only">${(new Date()).toISOString()}
|
||||
</span>
|
||||
Type "<a onclick="execute('help');">help</a>" for help.
|
||||
|
||||
|
@ -111,9 +110,9 @@ export class Shell {
|
|||
.join("/");
|
||||
|
||||
const status = this.environment.get("status");
|
||||
const statusString = status === "0" ? "" : ` <span class="errorMessage">[${status}]</span>`;
|
||||
const statusString = status === "0" ? "" : ` <span class="error-message">[${status}]</span>`;
|
||||
|
||||
return `${userName}@fwdekker.com <span class="prefixPath">${rootText}${partText}</span>${statusString}> `;
|
||||
return `${userName}@fwdekker.com <span class="prefix-path">${rootText}${partText}</span>${statusString}> `;
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,7 +125,7 @@ export class Shell {
|
|||
const inputString = streams.ins.readLine().replace("\n", "");
|
||||
if (inputString === "factory-reset") {
|
||||
Persistence.reset();
|
||||
location.reload(true);
|
||||
location.reload();
|
||||
throw new ExpectedGoodbyeError("Goodbye");
|
||||
}
|
||||
|
||||
|
@ -163,6 +162,9 @@ export class Shell {
|
|||
try {
|
||||
inputs = InputParser.create(this.environment, this.fileSystem).parseCommands(inputString);
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error))
|
||||
throw Error(`Error while processing parsing error:\n${error}`);
|
||||
|
||||
streams.err.writeLine(`Could not parse input: ${error.message}`);
|
||||
this.environment.set("status", "" + ExitCode.USAGE);
|
||||
return;
|
||||
|
|
|
@ -72,7 +72,7 @@ export class Terminal {
|
|||
}
|
||||
|
||||
write(string: string) {
|
||||
this.wrappedBuffer.write(`<span class="errorMessage">${string}</span>`);
|
||||
this.wrappedBuffer.write(`<span class="error-message">${string}</span>`);
|
||||
}
|
||||
}(this.standardOutput);
|
||||
|
||||
|
@ -170,7 +170,7 @@ export class Terminal {
|
|||
* Returns `true` if and only if the input field does not display the user's input.
|
||||
*/
|
||||
private get isInputHidden(): boolean {
|
||||
return this.input.classList.contains("terminalInputFieldHidden");
|
||||
return this.input.classList.contains("terminal-input-field-hidden");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,9 +180,9 @@ export class Terminal {
|
|||
*/
|
||||
private set isInputHidden(isInputHidden: boolean) {
|
||||
if (isInputHidden)
|
||||
this.input.classList.add("terminalInputFieldHidden");
|
||||
this.input.classList.add("terminal-input-field-hidden");
|
||||
else
|
||||
this.input.classList.remove("terminalInputFieldHidden");
|
||||
this.input.classList.remove("terminal-input-field-hidden");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
if (/MSIE|Trident/.test(window.navigator.userAgent)) {
|
||||
window.onload = function() {
|
||||
document.getElementById("ie-warning").className = "";
|
||||
};
|
||||
}
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", function() {
|
||||
return navigator.serviceWorker.register("sw.js?v=%%VERSION_NUMBER%%");
|
||||
|
|
|
@ -52,17 +52,17 @@ describe("file", () => {
|
|||
|
||||
it("uses the file extension to determine the value", () => {
|
||||
expect(new File("contents").nameString("file.txt", new Path("/file")))
|
||||
.to.equal(`<a class="fileLink" onclick="execute('cat /file')">file.txt</a>`);
|
||||
.to.equal(`<a class="file-link" onclick="execute('cat /file')">file.txt</a>`);
|
||||
});
|
||||
|
||||
it("uses the mime type if no type is known", () => {
|
||||
expect(new File("contents", "txt").nameString("file", new Path("/file")))
|
||||
.to.equal(`<a class="fileLink" onclick="execute('cat /file')">file</a>`);
|
||||
.to.equal(`<a class="file-link" onclick="execute('cat /file')">file</a>`);
|
||||
});
|
||||
|
||||
it("overrides the file extension with the mime type", () => {
|
||||
expect(new File("link", "lnk").nameString("file.txt", new Path("/file")))
|
||||
.to.equal(`<a href="link" class="fileLink" onclick="execute('open /file'); return false">file.txt</a>`);
|
||||
.to.equal(`<a href="link" class="file-link" onclick="execute('open /file'); return false">file.txt</a>`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
"compilerOptions": {
|
||||
"target": "es2019",
|
||||
"strict": true,
|
||||
// "noUncheckedIndexedAccess": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"rootDir": "./src/main/js/",
|
||||
"outDir": "./dist/js/"
|
||||
"outDir": "./dist/js/",
|
||||
},
|
||||
"include": [
|
||||
"src/main/js/**/*.ts"
|
||||
|
|
Loading…
Reference in New Issue