Initial commit
This commit is contained in:
		
							
								
								
									
										0
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										8
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
FROM node:lts-alpine3.20
 | 
			
		||||
 | 
			
		||||
WORKDIR /app
 | 
			
		||||
COPY src/ .
 | 
			
		||||
 | 
			
		||||
RUN npm install --global serve
 | 
			
		||||
EXPOSE 3000
 | 
			
		||||
CMD [ "serve", "." ]
 | 
			
		||||
							
								
								
									
										9
									
								
								compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								compose.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
services:                                                                                                     
 | 
			
		||||
  sitewterminal:
 | 
			
		||||
    build: .                                                                                                  
 | 
			
		||||
    labels:                                                                                                   
 | 
			
		||||
      - "traefik.http.routers.sitewillem.rule=Host(`willem.truyen.network`) && PathPrefix(`/`)"                                           
 | 
			
		||||
      - "traefik.http.routers.sitewillem.entrypoints=websecure"
 | 
			
		||||
      - "traefik.http.routers.sitewillem.tls=true"
 | 
			
		||||
      - "traefik.http.routers.sitewillem.tls.certresolver=myresolver"
 | 
			
		||||
      - "traefik.enable=true"
 | 
			
		||||
							
								
								
									
										38
									
								
								src/addon.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/addon.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>WTerminal as addon</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <!-- <link rel="stylesheet" href="css/wterminal.css" /> -->
 | 
			
		||||
 | 
			
		||||
  <script src="js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="index.html">Home</a>
 | 
			
		||||
    <a href="static-terminal.html">Static</a>
 | 
			
		||||
    <a href="dropdown.html">Dropdown</a>
 | 
			
		||||
    <a href="pong.html">Pong</a>
 | 
			
		||||
    <a href="addon.html">Addon</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>WTerminal as addon:</h1>
 | 
			
		||||
    <p>WTerminal can be used as a browser addon/plugin.<br>
 | 
			
		||||
      By using the addon you can have a WTerminal on every site you visit!</p>
 | 
			
		||||
 | 
			
		||||
    <p>Visit <a href="https://addons.mozilla.org/en-US/firefox/addon/wterminal/">addons.mozilla.org</a> to get WTerminal
 | 
			
		||||
      as a firefox addon. </p>
 | 
			
		||||
 | 
			
		||||
    <p>Or download the source code <a href="#">here</a>.</p>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										17
									
								
								src/css/game.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/css/game.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
*/
 | 
			
		||||
.game-area {
 | 
			
		||||
  margin: 8px auto;
 | 
			
		||||
  width: fit-content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.game-area p {
 | 
			
		||||
  margin: 0 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
canvas {
 | 
			
		||||
  border: solid 2px #3b3b3b;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  outline: none;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										102
									
								
								src/css/main.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/css/main.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
/* Author:      Ward Truyen
 | 
			
		||||
 * Version:     1.3.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
html,
 | 
			
		||||
body {
 | 
			
		||||
  margin: 0px;
 | 
			
		||||
  padding: 0px;
 | 
			
		||||
  background-image: linear-gradient(30deg, #73B2736F 70%, #73B2732F);
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main {
 | 
			
		||||
  margin: auto;
 | 
			
		||||
  width: 80%;
 | 
			
		||||
  border: 2px solid darkgreen;
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
  background-color: white;
 | 
			
		||||
  box-shadow: 3px 3px 3px black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main > a, main > pre, main > p{
 | 
			
		||||
  margin-left: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
  margin-top: 4px;
 | 
			
		||||
  margin-bottom: 8px;
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
header {
 | 
			
		||||
  padding: 2px 16px 4px 16px;
 | 
			
		||||
  /* width: 100%; */
 | 
			
		||||
  border-bottom: 1px solid black;
 | 
			
		||||
  /* background-image: linear-gradient(#0000008f, #0000004f); */
 | 
			
		||||
  background-color: #80808080;
 | 
			
		||||
  /* linear-gradient(#0000008f, #0000004f);*/
 | 
			
		||||
  /* margin-top: 16px; */
 | 
			
		||||
  text-shadow: 1px 1px 1px #0000004f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
header a {
 | 
			
		||||
  /* border: solid 1px black; */
 | 
			
		||||
  padding: 2px;
 | 
			
		||||
  margin: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
footer {
 | 
			
		||||
  padding: 8px 16px 4px 16px;
 | 
			
		||||
  /* width: 100%; */
 | 
			
		||||
  border-top: 1px solid black;
 | 
			
		||||
  /* background-color: #0000004f; */
 | 
			
		||||
  background-image: linear-gradient(#0000008f, #0000004f);
 | 
			
		||||
  /* margin-top: 16px; */
 | 
			
		||||
  margin-top: auto;
 | 
			
		||||
  text-shadow: 1px 1px 1px #0000004f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
footer h1,
 | 
			
		||||
footer h2,
 | 
			
		||||
footer h3,
 | 
			
		||||
footer p {
 | 
			
		||||
  display: inline;
 | 
			
		||||
  margin: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.float-right {
 | 
			
		||||
  float: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.text-red {
 | 
			
		||||
  color: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-red {
 | 
			
		||||
  background-color: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-black {
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html.theme-dark {
 | 
			
		||||
  color-scheme: dark;
 | 
			
		||||
  background-image: linear-gradient(-10deg, #1010206F 60%, #5050506F);
 | 
			
		||||
  color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.theme-dark>body>main {
 | 
			
		||||
  border: 1px solid darkgray;
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  box-shadow: 3px 3px 5px #101010C0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.theme-dark>body>main>h1 {
 | 
			
		||||
  text-shadow: 0px 0px 3px blue, 2px 2px 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										166
									
								
								src/css/wterminal.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								src/css/wterminal.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.1.0
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
.wterminal-background {
 | 
			
		||||
  z-index: 9995;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  top: 0px;
 | 
			
		||||
  left: 0px;
 | 
			
		||||
  color: black;
 | 
			
		||||
  line-height: normal;
 | 
			
		||||
  visibility: hidden;
 | 
			
		||||
  background: unset;
 | 
			
		||||
  transition: all 0.2s ease-out 0s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-background .wterminal-container{
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin: 0px auto;
 | 
			
		||||
  width: 70%;
 | 
			
		||||
  border: 1px solid #888;
 | 
			
		||||
  border-top: 0px solid grey;
 | 
			
		||||
  border-bottom-left-radius: 4px;
 | 
			
		||||
  border-bottom-right-radius: 4px;
 | 
			
		||||
  padding: 0px 4px 4px 4px;
 | 
			
		||||
  background: linear-gradient(24deg, rgba(209,211,196,1) 20%, rgba(221,221,221,1) 50%, rgba(221,221,221,1) 70%, rgba(190,199,207,1) 90%);
 | 
			
		||||
  box-shadow: 3px 3px 3px black;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  margin-top: -50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-container pre {
 | 
			
		||||
  color: unset;
 | 
			
		||||
  border: 2px solid #a0a0a0d0;
 | 
			
		||||
  min-height: 20em;
 | 
			
		||||
  max-height: 20em;
 | 
			
		||||
  margin: 0px 0px 2px;
 | 
			
		||||
  padding: 2px 4px 6px 4px;
 | 
			
		||||
  background-color: #F0F0F0;
 | 
			
		||||
  overflow-y: scroll;
 | 
			
		||||
  font-family: Monospace, Incosolata, Courier;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  line-height: 1.08;
 | 
			
		||||
  width: unset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-output u{ 
 | 
			
		||||
  /* adds a nice fat blue underline to titles */
 | 
			
		||||
  text-decoration-color: #8cb4ff;
 | 
			
		||||
  text-decoration-thickness: .15rem;
 | 
			
		||||
  text-underline-offset: .1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-input {
 | 
			
		||||
  padding: 1px 2px;
 | 
			
		||||
  margin: 0px;
 | 
			
		||||
  background-color: #F0F0F0;
 | 
			
		||||
  color: black;
 | 
			
		||||
  border: 1px solid #ccc;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-input:hover{
 | 
			
		||||
  background-color: #DDD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-container input[type="submit"]:hover,
 | 
			
		||||
.wterminal-container button:hover{
 | 
			
		||||
  background-color: #DDD;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
.wterminal-container input, .wterminal-container label{
 | 
			
		||||
  line-height: unset;
 | 
			
		||||
  display: unset;
 | 
			
		||||
  /* width: unset; */
 | 
			
		||||
  height: unset;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  margin-left: 2px;
 | 
			
		||||
}
 | 
			
		||||
.wterminal-container input[type="submit"],
 | 
			
		||||
.wterminal-container button{
 | 
			
		||||
  width: unset;
 | 
			
		||||
  height: unset;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  margin-left: 2px;
 | 
			
		||||
  padding: 1px 4px;
 | 
			
		||||
  color: black;
 | 
			
		||||
  background-color: #eee;
 | 
			
		||||
  border: 1px solid #aaa;
 | 
			
		||||
  border-radius: 3px;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-background.wterminal-visible{
 | 
			
		||||
  background-color: #0000008F;
 | 
			
		||||
  backdrop-filter: blur(4px);
 | 
			
		||||
  visibility: visible;
 | 
			
		||||
  transition: background-color .1s ease-out 0s, backdrop-filter .1s ease-out 0s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-visible .wterminal-container{
 | 
			
		||||
  margin-top: 0px;
 | 
			
		||||
  transition: margin-top .2s ease-out 0s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wterminal-container form{
 | 
			
		||||
  margin-left: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Width */
 | 
			
		||||
@media screen and (max-width: 480px) {
 | 
			
		||||
  .wterminal-input{
 | 
			
		||||
    width: 40%;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@media screen and (min-width: 480px) and (max-width: 720px) {
 | 
			
		||||
  .wterminal-input{
 | 
			
		||||
    width: 50%;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@media screen and (min-width: 720px) and (max-width: 1080px) {
 | 
			
		||||
  .wterminal-input{
 | 
			
		||||
    width: 60%;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@media screen and (min-width: 1080px) {
 | 
			
		||||
  .wterminal-input{
 | 
			
		||||
    width: 70%;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Height */
 | 
			
		||||
@media screen and (min-height: 512px) and (max-height: 1024px) {
 | 
			
		||||
  .wterminal-background .wterminal-container .wterminal-output{
 | 
			
		||||
    min-height: 32em;
 | 
			
		||||
    max-height: 32em;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@media screen and (min-height: 1024px) and (max-height: 1536px) {
 | 
			
		||||
  .wterminal-background .wterminal-container .wterminal-output{
 | 
			
		||||
    min-height: 48em;
 | 
			
		||||
    max-height: 48em;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@media screen and (min-height: 1536px) {
 | 
			
		||||
  .wterminal-background .wterminal-container .wterminal-output{
 | 
			
		||||
    min-height: 64em;
 | 
			
		||||
    max-height: 64em;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.theme-dark .wterminal-background .wterminal-container{
 | 
			
		||||
  color: #F0F0F0;
 | 
			
		||||
  background: #303030;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.theme-dark .wterminal-container pre,
 | 
			
		||||
.theme-dark .wterminal-container button,
 | 
			
		||||
.theme-dark .wterminal-container input
 | 
			
		||||
{
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  /* color: #F0F0F0; */
 | 
			
		||||
  color: white;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								src/dropdown.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/dropdown.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>WTerminal dropdown sample</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <link rel="stylesheet" href="css/wterminal.css" />
 | 
			
		||||
 | 
			
		||||
  <script src="js/wterminal.js"></script>
 | 
			
		||||
  <script src="js/wterminal-autoextend.js"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="index.html">Home</a>
 | 
			
		||||
    <a href="static-terminal.html">Static</a>
 | 
			
		||||
    <a href="dropdown.html">Dropdown</a>
 | 
			
		||||
    <a href="pong.html">Pong</a>
 | 
			
		||||
    <a href="addon.html">Addon</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>Dropdown terminal</h1>
 | 
			
		||||
    <p>WTerminal is installed on this site as a dropdown/quake style terminal.</p>
 | 
			
		||||
    <h2>How to use the terminal:</h2>
 | 
			
		||||
    <ul>
 | 
			
		||||
      <li>Open terminal: press Backquote <b>`</b> AKA tilde, or click the "Open terminal" button below.</li>
 | 
			
		||||
      <li>Use terminal commands: type "help" or "?" and press enter to get started.</li>
 | 
			
		||||
      <li>Close terminal: press Escape</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    <button onclick="WTerminal.open()">Open terminal</button>
 | 
			
		||||
    <h2>How to add the terminal to a site:</h2>
 | 
			
		||||
    <p>Add the CSS and JavaScript files to your site header:<br>
 | 
			
		||||
      <code><link rel="stylesheet" href="css/wterminal.css" /><br>
 | 
			
		||||
        <script src="js/wterminal.js"></script></code>
 | 
			
		||||
    </p>
 | 
			
		||||
    <p>Then add a script ellement with:<br>
 | 
			
		||||
      <code>WTerminal.instalDropdownTerminal();</code>
 | 
			
		||||
      Or
 | 
			
		||||
      <code>new WTerminal("dropdown", null, null);</code>
 | 
			
		||||
    </p>
 | 
			
		||||
    <script>
 | 
			
		||||
      WTerminal.instalDropdownTerminal();
 | 
			
		||||
      // Or
 | 
			
		||||
      //new WTerminal("dropdown", null, null);
 | 
			
		||||
    </script>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 9.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/img/kitty.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/img/kitty.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 31 KiB  | 
							
								
								
									
										45
									
								
								src/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>WTerminal home</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <!-- <link rel="stylesheet" href="css/wterminal.css" /> -->
 | 
			
		||||
 | 
			
		||||
  <script src="js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="index.html">Home</a>
 | 
			
		||||
    <a href="static-terminal.html">Static</a>
 | 
			
		||||
    <a href="dropdown.html">Dropdown</a>
 | 
			
		||||
    <a href="pong.html">Pong</a>
 | 
			
		||||
    <a href="addon.html">Addon</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>WTerminal home:</h1>
 | 
			
		||||
    <pre>*  _  .  _  _____ .----..----. .-.   .-..-..-. .-.  .--.  .-.   
 | 
			
		||||
* | |/ \| |[_   _]| {__ | {)  }| .`-'. ||~|| .`| | / {} \ | |   
 | 
			
		||||
* |  ,-,  |  | |  | {__ | .-. \| |\ /| || || |\  |/  /\  \| `--.
 | 
			
		||||
* '-'   `-'  '-'  `----'`-' `-'`-' ` `-'`-'`-' `-'`-'  `-'`----'
 | 
			
		||||
For terminal fun on the web.</pre>
 | 
			
		||||
    <p>The following pages show multiple ways that this terminal can be used.</p>
 | 
			
		||||
    <h2>Pages:</h2>
 | 
			
		||||
    <a href="static-terminal.html">Static terminal</a><br>
 | 
			
		||||
    <a href="dropdown.html">Dropdown terminal</a><br>
 | 
			
		||||
    <a href="pong.html">Ping pong game + dropdown terminal</a><br>
 | 
			
		||||
    <a href="addon.html">Browser addon</a><br>
 | 
			
		||||
 | 
			
		||||
    <h2>Testing:</h2>
 | 
			
		||||
    <a href="/test/">terminal testing</a><br>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										471
									
								
								src/js/game-pong-context2d.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										471
									
								
								src/js/game-pong-context2d.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,471 @@
 | 
			
		||||
/* About: Pingpong for HTML, you can insert it in anny Div tagged with an id
 | 
			
		||||
 *     This is a simple elegant sample for how to work with a Canvas
 | 
			
		||||
 */
 | 
			
		||||
class PingPong_CTX2D {
 | 
			
		||||
  static get DEBUG_PARENT_OBJECT() { return true; };
 | 
			
		||||
  static get AUTO_CONTINUE_ON_FOCUS() { return false; };
 | 
			
		||||
  static get SHOW_FPS_INTERVAL() { return 1000 / 4; }; // four times per second
 | 
			
		||||
 | 
			
		||||
  static get STATE_COUNTDOWN() { return 0; };
 | 
			
		||||
  static get STATE_PLAYING() { return 1; };
 | 
			
		||||
  static get STATE_ENDED() { return 2; };
 | 
			
		||||
  static get BALL_SIZE() { return 8; };
 | 
			
		||||
  static get SPEED_HUMAN() { return 180; };
 | 
			
		||||
  static get SPEED_CPU() { return 210; };
 | 
			
		||||
 | 
			
		||||
  static get PADDLE_WIDTH() { return 10; };
 | 
			
		||||
  static get PADDLE_HEIGHT() { return 60; };
 | 
			
		||||
  static get PADDLE_MARGIN() { return 10; };
 | 
			
		||||
 | 
			
		||||
  static get KEY_ARROW_UP() { return 'ArrowUp'; };
 | 
			
		||||
  static get KEY_ARROW_DOWN() { return 'ArrowDown'; };
 | 
			
		||||
  static get KEY_W() { return 'w'; };
 | 
			
		||||
  static get KEY_S() { return 's'; };
 | 
			
		||||
  static get KEY_ENTER() { return 'Enter'; };
 | 
			
		||||
  static get KEY_SPACEBAR() { return ' '; };
 | 
			
		||||
  static get KEY_ESCAPE() { return 'Escape'; };
 | 
			
		||||
 | 
			
		||||
  animationRequestId = 0;
 | 
			
		||||
  running = false;
 | 
			
		||||
 | 
			
		||||
  constructor(divId, width, height, zoom = 1, showFps = false) {
 | 
			
		||||
    this.createCanvas(divId, width, height, zoom);
 | 
			
		||||
    this.canvasEl.title = "Playing: PingPong";
 | 
			
		||||
    this.ctx = this.canvasEl.getContext("2d");
 | 
			
		||||
    this.ctx.textAlign = "center";
 | 
			
		||||
 | 
			
		||||
    this.audioCtx = new AudioContext();
 | 
			
		||||
    this.sounds = [];
 | 
			
		||||
    this.sounds[0] = new Audio('./snd/glass-knock.mp3');
 | 
			
		||||
    this.audioCtx.createMediaElementSource(this.sounds[0]).connect(this.audioCtx.destination);
 | 
			
		||||
    this.sounds[1] = new Audio('./snd/short-success.mp3');
 | 
			
		||||
    this.audioCtx.createMediaElementSource(this.sounds[1]).connect(this.audioCtx.destination);
 | 
			
		||||
 | 
			
		||||
    this.showFps = showFps;
 | 
			
		||||
    if (showFps) {
 | 
			
		||||
      // add framecounter and fps variables and html
 | 
			
		||||
      this.frameCounter = 0;
 | 
			
		||||
      this.initTime = performance.now();
 | 
			
		||||
      const el = document.createElement('p');
 | 
			
		||||
      this.frameLabel = document.createElement('span');
 | 
			
		||||
      const floatRight = document.createElement('span');
 | 
			
		||||
      floatRight.style = "float: right;";
 | 
			
		||||
      this.fpsCounter = 0;
 | 
			
		||||
      this.fpsLabel = document.createElement('span');
 | 
			
		||||
      el.appendChild(document.createTextNode('fps: '));
 | 
			
		||||
      el.appendChild(this.fpsLabel);
 | 
			
		||||
      floatRight.appendChild(document.createTextNode('frame: '));
 | 
			
		||||
      floatRight.appendChild(this.frameLabel);
 | 
			
		||||
      el.appendChild(floatRight);
 | 
			
		||||
      this.divEl.appendChild(el);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.restartGame();
 | 
			
		||||
    this.canvasEl.addEventListener("keydown", (e) => this.onKeyDown(e));
 | 
			
		||||
    this.canvasEl.addEventListener("keyup", (e) => this.onKeyUp(e));
 | 
			
		||||
    this.canvasEl.addEventListener("blur", (e) => this.onBlur(e));
 | 
			
		||||
    this.canvasEl.addEventListener("focus", (e) => this.onFocus(e));
 | 
			
		||||
 | 
			
		||||
    if (PingPong_CTX2D.DEBUG_PARENT_OBJECT) window.game = this;
 | 
			
		||||
    if (typeof WTerminal === "function") {
 | 
			
		||||
      WTerminal.terminalAddCommand("restartgame", (t) => this.terminalRestartGame(t));
 | 
			
		||||
      WTerminal.terminalAddCommand("printgame", (t) => t.printVar(this, "pong"));
 | 
			
		||||
      WTerminal.printLn("new PingPong: @", divId, ' ', width, 'x', height, ':', zoom, ' showFps=', showFps);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.drawCanvas();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  playSound(index) {
 | 
			
		||||
    try {
 | 
			
		||||
      const snd = this.sounds[index];
 | 
			
		||||
      snd.currentTime = 0;
 | 
			
		||||
      snd.play();
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.log(`Failed to play sound '${index}': ${e}}`)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  restartGame() {
 | 
			
		||||
    this.scoreCpu = 0;
 | 
			
		||||
    this.scoreHuman = 0;
 | 
			
		||||
    this.newRound();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  newRound() {
 | 
			
		||||
    this.countDown = 3; // seconds;
 | 
			
		||||
    this.gameState = PingPong_CTX2D.STATE_COUNTDOWN;
 | 
			
		||||
    // randomize ball speed
 | 
			
		||||
    let vx = 200 + Math.random() * 100;
 | 
			
		||||
    let vy = -20 + Math.random() * 20;
 | 
			
		||||
    if (Math.random() > 0.5) vx = - vx;
 | 
			
		||||
    if (Math.random() > 0.5) vy = - vy;
 | 
			
		||||
    // generate objects
 | 
			
		||||
    this.ball = new Ball(this.width / 2 - PingPong_CTX2D.BALL_SIZE / 2, this.height / 2 - PingPong_CTX2D.BALL_SIZE / 2,
 | 
			
		||||
      PingPong_CTX2D.BALL_SIZE, PingPong_CTX2D.BALL_SIZE, vx, vy);
 | 
			
		||||
    this.human = new Paddle(PingPong_CTX2D.PADDLE_MARGIN, this.height / 2 - PingPong_CTX2D.PADDLE_HEIGHT / 2,
 | 
			
		||||
      PingPong_CTX2D.PADDLE_WIDTH, PingPong_CTX2D.PADDLE_HEIGHT);
 | 
			
		||||
    this.cpu = new Paddle(this.width - PingPong_CTX2D.PADDLE_MARGIN - PingPong_CTX2D.PADDLE_WIDTH, this.height / 2 - PingPong_CTX2D.PADDLE_HEIGHT / 2,
 | 
			
		||||
      PingPong_CTX2D.PADDLE_WIDTH, PingPong_CTX2D.PADDLE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
    this.prevNow = performance.now();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  createCanvas(divId, width = 0, height = 0, zoom = 1) {
 | 
			
		||||
    this.divEl = document.getElementById(divId);
 | 
			
		||||
    if (this.divEl === null) throw new Error("elementId not found: " + divId);
 | 
			
		||||
    while (this.divEl.firstChild) {
 | 
			
		||||
      this.divEl.removeChild(this.divEl.lastChild);
 | 
			
		||||
    }
 | 
			
		||||
    this.canvasEl = this.divEl.appendChild(document.createElement("canvas"));
 | 
			
		||||
    const c = this.canvasEl;
 | 
			
		||||
    this.width = width;
 | 
			
		||||
    this.height = height;
 | 
			
		||||
    if (width > 0 && height > 0) {
 | 
			
		||||
      c.style.width = width * zoom + 'px';
 | 
			
		||||
      c.style.height = height * zoom + 'px';
 | 
			
		||||
      c.width = width;
 | 
			
		||||
      c.height = height;
 | 
			
		||||
    }
 | 
			
		||||
    c.tabIndex = 0; // improtant for keyboard focus!
 | 
			
		||||
    // c.style.imageRendering = 'pixelated';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  drawCanvas() {
 | 
			
		||||
    if (this.showFps) {
 | 
			
		||||
      this.frameCounter++;
 | 
			
		||||
      this.fpsCounter++;
 | 
			
		||||
 | 
			
		||||
      const now = performance.now();
 | 
			
		||||
      const diff = now - this.initTime;
 | 
			
		||||
      if (PingPong_CTX2D.SHOW_FPS_INTERVAL < diff || !this.running) {
 | 
			
		||||
        this.initTime = now;
 | 
			
		||||
        const seconds = diff / 1000;
 | 
			
		||||
        const fps = this.fpsCounter / seconds;
 | 
			
		||||
        this.fpsCounter = 0;
 | 
			
		||||
        if (this.frameLabel) this.frameLabel.innerHTML = this.frameCounter;
 | 
			
		||||
        if (this.fpsLabel) {
 | 
			
		||||
          this.fpsLabel.innerHTML = Math.round((fps + Number.EPSILON) * 100) / 100;
 | 
			
		||||
          if (!this.running) this.fpsLabel.innerHTML += " (not running)";
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    const ctx = this.ctx;
 | 
			
		||||
    ctx.clearRect(0, 0, this.width, this.height);
 | 
			
		||||
    //# print score
 | 
			
		||||
    const FONT_SIZE = this.width > 440 ? 24 : 16;
 | 
			
		||||
    ctx.font = FONT_SIZE + "px serif";
 | 
			
		||||
    ctx.fillStyle = 'red';
 | 
			
		||||
    ctx.fillText(this.scoreHuman + " - " + this.scoreCpu, this.width / 2, FONT_SIZE * 2);
 | 
			
		||||
    //# print count down
 | 
			
		||||
    if (this.gameState == PingPong_CTX2D.STATE_COUNTDOWN) {
 | 
			
		||||
      ctx.font = 2 * FONT_SIZE + "px serif";
 | 
			
		||||
      ctx.fillText(Math.ceil(this.countDown), this.width / 2, this.height / 2);
 | 
			
		||||
    }
 | 
			
		||||
    //# shadow
 | 
			
		||||
    ctx.save();
 | 
			
		||||
    ctx.shadowColor = '#000000bf';
 | 
			
		||||
    ctx.shadowBlur = 3;
 | 
			
		||||
    ctx.shadowOffsetX = 2;
 | 
			
		||||
    ctx.shadowOffsetY = 2;
 | 
			
		||||
    //# draw ball
 | 
			
		||||
    ctx.strokeStyle = 'black';
 | 
			
		||||
    ctx.fillStyle = 'orange';
 | 
			
		||||
    ctx.globalAlpha = 0.3;
 | 
			
		||||
    ctx.beginPath();
 | 
			
		||||
    ctx.arc(this.ball.prevX + PingPong_CTX2D.BALL_SIZE / 2, this.ball.prevY + PingPong_CTX2D.BALL_SIZE / 2, PingPong_CTX2D.BALL_SIZE / 2, 0, Math.PI * 2, true);
 | 
			
		||||
    ctx.fill();
 | 
			
		||||
    ctx.stroke();
 | 
			
		||||
    ctx.globalAlpha = 1;
 | 
			
		||||
    ctx.beginPath();
 | 
			
		||||
    ctx.arc(this.ball.x + PingPong_CTX2D.BALL_SIZE / 2, this.ball.y + PingPong_CTX2D.BALL_SIZE / 2, PingPong_CTX2D.BALL_SIZE / 2, 0, Math.PI * 2, true);
 | 
			
		||||
    ctx.fill();
 | 
			
		||||
    ctx.stroke();
 | 
			
		||||
    //# draw players paddle
 | 
			
		||||
    ctx.fillStyle = 'green';
 | 
			
		||||
    ctx.fillRect(this.human.x, this.human.y, this.human.width, this.human.height);
 | 
			
		||||
    ctx.strokeRect(this.human.x, this.human.y, this.human.width, this.human.height);
 | 
			
		||||
    ctx.fillStyle = 'blue';
 | 
			
		||||
    ctx.fillRect(this.cpu.x, this.cpu.y, this.cpu.width, this.cpu.height);
 | 
			
		||||
    ctx.strokeRect(this.cpu.x, this.cpu.y, this.cpu.width, this.cpu.height);
 | 
			
		||||
    ctx.restore(); //end shadow
 | 
			
		||||
    // unfocused & paused banner
 | 
			
		||||
    if (!this.running) {
 | 
			
		||||
      const x = this.width / 2;
 | 
			
		||||
      const y = this.height / 2;
 | 
			
		||||
      const y2 = y - FONT_SIZE / 2;
 | 
			
		||||
      ctx.strokeStyle = 'black';
 | 
			
		||||
      const g = ctx.createLinearGradient(0, 0, this.width, 0);
 | 
			
		||||
      g.addColorStop(0, '#404040a0');
 | 
			
		||||
      g.addColorStop(0.2, '#404040df');
 | 
			
		||||
      g.addColorStop(0.8, '#404040df');
 | 
			
		||||
      g.addColorStop(1, '#404040a0');
 | 
			
		||||
      ctx.fillStyle = g;
 | 
			
		||||
      ctx.fillRect(0, y2 - 2, this.width + 1, FONT_SIZE + 5 * 2);
 | 
			
		||||
      ctx.strokeRect(0, y2 - 2, this.width + 1, FONT_SIZE + 5 * 2);
 | 
			
		||||
      ctx.fillStyle = (this.gameState === PingPong_CTX2D.STATE_ENDED) ? 'red' : 'gray';
 | 
			
		||||
      ctx.font = 4 * FONT_SIZE + "px serif";
 | 
			
		||||
      let text = (this.gameState === PingPong_CTX2D.STATE_ENDED) ? "Score!" : "Paused";
 | 
			
		||||
      ctx.fillText(text, x, y - 2 * FONT_SIZE);
 | 
			
		||||
      ctx.strokeText(text, x, y - 2 * FONT_SIZE);
 | 
			
		||||
      ctx.fillStyle = this.isFocused ? 'goldenrod' : 'lightgray';
 | 
			
		||||
      ctx.font = FONT_SIZE + "px serif";
 | 
			
		||||
      text = this.isFocused ? `Press space or enter to ${(this.gameState === PingPong_CTX2D.STATE_ENDED) ? "start next round" : "continue"}.` : "Click here to continue. (unfocused)";
 | 
			
		||||
      ctx.strokeText(text, x, y2 + FONT_SIZE);
 | 
			
		||||
      ctx.fillText(text, x, y2 + FONT_SIZE);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateCanvas() {
 | 
			
		||||
    const now = performance.now();
 | 
			
		||||
    const timeDelta = (now - this.prevNow) / 1000; //timeDelta = (milli - milli) / toSeconds
 | 
			
		||||
    this.prevNow = now;
 | 
			
		||||
    //#state switch
 | 
			
		||||
    if (this.gameState == PingPong_CTX2D.STATE_COUNTDOWN) {
 | 
			
		||||
      this.human.move(timeDelta);
 | 
			
		||||
      this.human.borderTopAndBottom(this.height);
 | 
			
		||||
 | 
			
		||||
      this.cpu.move(timeDelta);
 | 
			
		||||
      this.cpu.borderTopAndBottom(this.height);
 | 
			
		||||
 | 
			
		||||
      this.countDown -= timeDelta;//PONG_UPDATE_INTERVAL;
 | 
			
		||||
      if (this.countDown < 0) {
 | 
			
		||||
        this.gameState = PingPong_CTX2D.STATE_PLAYING;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (this.gameState == PingPong_CTX2D.STATE_PLAYING) {
 | 
			
		||||
      //cpu actions
 | 
			
		||||
      if (this.ball.y + this.ball.height / 2 < this.cpu.y + this.cpu.height / 2) {
 | 
			
		||||
        this.cpu.vy = -PingPong_CTX2D.SPEED_CPU;
 | 
			
		||||
      } else if (this.ball.y > this.cpu.y + this.cpu.height / 2) {
 | 
			
		||||
        this.cpu.vy = PingPong_CTX2D.SPEED_CPU;
 | 
			
		||||
      } else {
 | 
			
		||||
        this.cpu.vy = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //move ball and paddles
 | 
			
		||||
      this.ball.move(timeDelta);
 | 
			
		||||
      if (this.ball.borderTopAndBottom(this.height)) {
 | 
			
		||||
        this.playSound(0);
 | 
			
		||||
      }
 | 
			
		||||
      //Horizontal
 | 
			
		||||
      if (this.ball.x < 0) {
 | 
			
		||||
        this.win(0);
 | 
			
		||||
        this.playSound(1);
 | 
			
		||||
      } else if (this.ball.x > this.width - this.ball.width) {
 | 
			
		||||
        this.win(1);
 | 
			
		||||
        this.playSound(1);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.human.move(timeDelta);
 | 
			
		||||
      this.human.borderTopAndBottom(this.height);
 | 
			
		||||
 | 
			
		||||
      this.cpu.move(timeDelta);
 | 
			
		||||
      this.cpu.borderTopAndBottom(this.height);
 | 
			
		||||
 | 
			
		||||
      // collide ball vs paddles
 | 
			
		||||
      if (this.human.x + this.human.width < this.ball.prevX && this.human.x + this.human.width > this.ball.x) {
 | 
			
		||||
        // console.log("pass 1.1");
 | 
			
		||||
        if (this.human.y < this.ball.y + this.ball.height && this.human.y + this.human.height > this.ball.y) {
 | 
			
		||||
          // console.log("pass 1.2");
 | 
			
		||||
          this.ball.vx = this.ball.vx * -1.05;
 | 
			
		||||
          this.ball.x = this.human.x + this.human.width;
 | 
			
		||||
          this.ball.vy += ((this.ball.height / 2 + this.ball.y) - (this.human.height / 2 + this.human.y)) * 10;
 | 
			
		||||
          this.playSound(0);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this.cpu.x < this.ball.x + this.ball.width && this.cpu.x > this.ball.prevX + this.ball.width) {
 | 
			
		||||
        // console.log("pass 2.1");
 | 
			
		||||
        if (this.cpu.y < this.ball.y + this.ball.height && this.cpu.y + this.cpu.height > this.ball.y) {
 | 
			
		||||
          // console.log("pass 2.2");
 | 
			
		||||
          this.ball.vx = this.ball.vx * -1.05;
 | 
			
		||||
          this.ball.x = this.cpu.x - this.ball.width;
 | 
			
		||||
          let temp = ((this.ball.height / 2 + this.ball.y) - (this.cpu.height / 2 + this.cpu.y)) * 10;
 | 
			
		||||
          this.ball.vy += temp;
 | 
			
		||||
          this.playSound(0);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.drawCanvas();
 | 
			
		||||
    if (this.running) { // loop
 | 
			
		||||
      this.animationRequestId = requestAnimationFrame(() => this.updateCanvas());
 | 
			
		||||
    } else { // not looping
 | 
			
		||||
      this.animationRequestId = 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  startRunning(fn) {
 | 
			
		||||
    if (this.animationRequestId != 0) cancelAnimationFrame(this.animationRequestId);
 | 
			
		||||
    this.running = true;
 | 
			
		||||
    this.prevNow = performance.now();
 | 
			
		||||
    if (this.showFps) {
 | 
			
		||||
      this.initTime = performance.now();
 | 
			
		||||
    }
 | 
			
		||||
    this.animationRequestId = requestAnimationFrame(fn);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  close() {
 | 
			
		||||
    if (this.animationRequestId != 0) {
 | 
			
		||||
      cancelAnimationFrame(this.animationRequestId);
 | 
			
		||||
      this.animationRequestId = 0;
 | 
			
		||||
    }
 | 
			
		||||
    this.running = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pausePlayGame() {
 | 
			
		||||
    if (this.gameState == PingPong_CTX2D.STATE_ENDED) return;
 | 
			
		||||
    this.running = !this.running;
 | 
			
		||||
    if (this.running) {
 | 
			
		||||
      this.startRunning(() => this.updateCanvas());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  terminalPrintGame(term) {
 | 
			
		||||
    term.printVar(this, "pong");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  terminalRestartGame(term) {
 | 
			
		||||
    term.terminalClose();
 | 
			
		||||
    this.restartGame();
 | 
			
		||||
    // this.canvasEl.focus();
 | 
			
		||||
    setTimeout(() => { this.canvasEl.focus(); this.pausePlayGame(); }, 200);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  win(winner) {
 | 
			
		||||
    this.running = false; //this.stopRunning();
 | 
			
		||||
    this.gameState = PingPong_CTX2D.STATE_ENDED;
 | 
			
		||||
    if (winner == 0) {
 | 
			
		||||
      this.scoreCpu++;
 | 
			
		||||
      if (typeof WTerminal === "function") WTerminal.printLn("CPU scored?!");
 | 
			
		||||
    } else {
 | 
			
		||||
      this.scoreHuman++;
 | 
			
		||||
      if (typeof WTerminal === "function") WTerminal.printLn("Human scored!");
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof WTerminal === "function") WTerminal.printLn("Scores: Human " + this.scoreHuman + " - " + this.scoreCpu + " CPU");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onKeyDown(e) {
 | 
			
		||||
    if (e.key == PingPong_CTX2D.KEY_ESCAPE) {
 | 
			
		||||
      if (this.running) this.pausePlayGame()
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (e.key == PingPong_CTX2D.KEY_ARROW_UP || e.key == PingPong_CTX2D.KEY_W) {
 | 
			
		||||
      this.human.vy = -PingPong_CTX2D.SPEED_HUMAN;
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      return false;
 | 
			
		||||
    } else if (e.key == PingPong_CTX2D.KEY_ARROW_DOWN || e.key == PingPong_CTX2D.KEY_S) {
 | 
			
		||||
      this.human.vy = PingPong_CTX2D.SPEED_HUMAN;
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      return false;
 | 
			
		||||
    } else if (e.key == PingPong_CTX2D.KEY_ENTER || e.key == PingPong_CTX2D.KEY_SPACEBAR) {
 | 
			
		||||
      //# next round/pause/play
 | 
			
		||||
      if (this.gameState == PingPong_CTX2D.STATE_ENDED) {
 | 
			
		||||
        this.newRound();
 | 
			
		||||
        this.startRunning(() => this.updateCanvas());
 | 
			
		||||
      } else {
 | 
			
		||||
        this.pausePlayGame();
 | 
			
		||||
      }
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onKeyUp(e) {
 | 
			
		||||
    if (e.key == PingPong_CTX2D.KEY_ARROW_UP || e.key == PingPong_CTX2D.KEY_W) {
 | 
			
		||||
      this.human.vy = 0;
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      return false;
 | 
			
		||||
    } else if (e.key == PingPong_CTX2D.KEY_ARROW_DOWN || e.key == PingPong_CTX2D.KEY_S) {
 | 
			
		||||
      this.human.vy = 0;
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onBlur() {
 | 
			
		||||
    this.isFocused = false;
 | 
			
		||||
    this.canvasEl.style.borderColor = null;
 | 
			
		||||
    if (this.running) {
 | 
			
		||||
      this.pausePlayGame();
 | 
			
		||||
    } else {
 | 
			
		||||
      this.drawCanvas();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onFocus() {
 | 
			
		||||
    this.isFocused = true;
 | 
			
		||||
    this.canvasEl.style.borderColor = "red";
 | 
			
		||||
    if (!this.running && PingPong_CTX2D.AUTO_CONTINUE_ON_FOCUS) {
 | 
			
		||||
      this.pausePlayGame();
 | 
			
		||||
    } else {
 | 
			
		||||
      this.drawCanvas();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Rectangle {
 | 
			
		||||
  constructor(x, y, width, height) {
 | 
			
		||||
    this.x = x;
 | 
			
		||||
    this.y = y;
 | 
			
		||||
    this.width = width;
 | 
			
		||||
    this.height = height;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Ball extends Rectangle {
 | 
			
		||||
  constructor(x, y, width, height, vx, vy) {
 | 
			
		||||
    super(x, y, width, height);
 | 
			
		||||
    this.vx = vx;
 | 
			
		||||
    this.vy = vy;
 | 
			
		||||
    this.prevX = this.x;
 | 
			
		||||
    this.prevY = this.y;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  move(timeDelta) {
 | 
			
		||||
    this.prevX = this.x;
 | 
			
		||||
    this.prevY = this.y;
 | 
			
		||||
    this.x += this.vx * timeDelta;
 | 
			
		||||
    this.y += this.vy * timeDelta;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  borderTopAndBottom(height) {
 | 
			
		||||
    if (this.y < 0) {
 | 
			
		||||
      this.y = 0;
 | 
			
		||||
      this.vy = -this.vy;
 | 
			
		||||
      return true;
 | 
			
		||||
    } else if (this.y > height - this.height) {
 | 
			
		||||
      this.y = height - this.height;
 | 
			
		||||
      this.vy = - this.vy;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Paddle extends Rectangle {
 | 
			
		||||
  constructor(x, y, width = 20, height = 20) {
 | 
			
		||||
    super(x, y, width, height);
 | 
			
		||||
    this.vy = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  move(timeDelta) {
 | 
			
		||||
    this.y += this.vy * timeDelta;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  borderTopAndBottom(height) {
 | 
			
		||||
    if (this.y < 0) {
 | 
			
		||||
      this.y = 0;
 | 
			
		||||
      this.vy = 0;
 | 
			
		||||
    } else if (this.y > height - this.height) {
 | 
			
		||||
      this.y = height - this.height;
 | 
			
		||||
      this.vy = 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startPingPong(divId, width = 480, height = 320, zoom = 1, showFps = true) {
 | 
			
		||||
  return new PingPong_CTX2D(divId, width, height, zoom, showFps);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								src/js/static-terminal-buttons.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/js/static-terminal-buttons.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
const TERMINAL_NAME = "static";
 | 
			
		||||
 | 
			
		||||
window.addEventListener("load", 
 | 
			
		||||
  ()=>getWTerminal(TERMINAL_NAME).inputTextEl.focus());
 | 
			
		||||
 | 
			
		||||
function btn_terminalHelp() {
 | 
			
		||||
  let term = getWTerminal(TERMINAL_NAME);
 | 
			
		||||
  term.terminalCommand("help");
 | 
			
		||||
  term.inputTextEl.focus();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function btn_promptSample() {
 | 
			
		||||
  let term = getWTerminal(TERMINAL_NAME);
 | 
			
		||||
  term.printTitle("Prompt sample:");
 | 
			
		||||
  let age = prompt("Enter your age:", "404");
 | 
			
		||||
  term.printLn("Age-input: " + age);
 | 
			
		||||
  let days = age * 365;
 | 
			
		||||
  term.printLn(`Days alive: ${days}`);
 | 
			
		||||
  let weeks = Math.round(days / 7);
 | 
			
		||||
  term.printLn(`Weeks alive: ${weeks}`);
 | 
			
		||||
  let adult = age >= 18;
 | 
			
		||||
  term.printLn("Type: " + (adult ? "adult" : "minor"));
 | 
			
		||||
  term.inputTextEl.focus();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function btn_kittySample() {
 | 
			
		||||
  let term = getWTerminal(TERMINAL_NAME);
 | 
			
		||||
  term.printTitle("Kitty sample:");
 | 
			
		||||
  term.printError("Error: Kitties are cute!");
 | 
			
		||||
  // term.printLn('<img src="img/kitty.jpg">Hello kitty!');
 | 
			
		||||
  let img = document.createElement("img");
 | 
			
		||||
  img.src = "img/kitty.jpg";
 | 
			
		||||
  term.printLn(img, "Hello kitty!");
 | 
			
		||||
  term.inputTextEl.focus();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function btn_printObjectSample() {
 | 
			
		||||
  let term = getWTerminal(TERMINAL_NAME);
 | 
			
		||||
  term.printTitle("print Object sample 1:");
 | 
			
		||||
  term.printVar("hello");
 | 
			
		||||
  term.printVar(3.1419);
 | 
			
		||||
  term.printTitle("print Object sample 2:");
 | 
			
		||||
  let myObject = { hello: "World", number:100};
 | 
			
		||||
  myObject.InnerObject = { foo: "bar", myFunction: btn_printObjectSample}
 | 
			
		||||
  myObject.array = [1,2,4,8];
 | 
			
		||||
  term.printVar(myObject, "sample");
 | 
			
		||||
  term.inputTextEl.focus();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function btn_terminalClear(){
 | 
			
		||||
  let term = getWTerminal(TERMINAL_NAME);
 | 
			
		||||
  term.clearOutput();
 | 
			
		||||
  term.inputTextEl.focus();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										103
									
								
								src/js/termext/ext-cookies.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/js/termext/ext-cookies.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   Cookie data managing
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
if (WTerminal) {
 | 
			
		||||
  const initTerminalCookieCommands = function() {
 | 
			
		||||
    //getcookie
 | 
			
		||||
    WTerminal.terminalAddCommand("getcookie", (term, argLine) => {
 | 
			
		||||
      function getCookie(name, defaultValue = undefined) {
 | 
			
		||||
        if (name === null || name === undefined || typeof name != "string" || name == '') {
 | 
			
		||||
          console.log('error: cookie needs a name');
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        let pair = document.cookie.split(/; */).find((row) => row.startsWith(name + '='))
 | 
			
		||||
        //console.log("cookie pair: ", pair); 
 | 
			
		||||
        if (pair === undefined)
 | 
			
		||||
          return defaultValue;
 | 
			
		||||
        else
 | 
			
		||||
          return pair.split('=')[1];
 | 
			
		||||
      }
 | 
			
		||||
      return getCookie(...WTerminal.splitToArguments(argLine));
 | 
			
		||||
    });
 | 
			
		||||
    //setcookie
 | 
			
		||||
    WTerminal.terminalAddCommand("setcookie", (term, argLine) => {
 | 
			
		||||
      function setCookie(name, value = 1, days = 7) {
 | 
			
		||||
        let date = new Date();
 | 
			
		||||
        date.setDate(date.getDate() + days); // add x days to date
 | 
			
		||||
        document.cookie = name + "=" + value + "; expires=" + date.toUTCString() + "; SameSite=strict; Secure";
 | 
			
		||||
      }
 | 
			
		||||
      return setCookie(...WTerminal.splitToArguments(argLine));
 | 
			
		||||
    });
 | 
			
		||||
    //removecookies
 | 
			
		||||
    WTerminal.terminalAddCommand("removecookies", function(term) {
 | 
			
		||||
      function removeCookie(name) {
 | 
			
		||||
        document.cookie = name + "=0; max-age=-1" + "; SameSite=strict; Secure";
 | 
			
		||||
      }
 | 
			
		||||
      if (document.cookie == '') {
 | 
			
		||||
        term.printError("No cookies found.");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      const cookies = document.cookie.split(/; */);
 | 
			
		||||
      term.printLn("Cookies found: " + cookies.length);
 | 
			
		||||
      cookies.forEach(c => {
 | 
			
		||||
        const name = c.split('=')[0];
 | 
			
		||||
        term.printLn("removing: " + name);
 | 
			
		||||
        removeCookie(name);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    //cookies
 | 
			
		||||
    WTerminal.terminalAddCommand("cookies",
 | 
			
		||||
      function(term, argLine) {
 | 
			
		||||
        if (document.cookie === '') {
 | 
			
		||||
          if (!argLine.includes("-s")) term.printError("No cookies found.")
 | 
			
		||||
        } else {
 | 
			
		||||
          term.printList(document.cookie.split(/; */), false);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      function(term) {
 | 
			
		||||
        term.printLn("Usage:");
 | 
			
		||||
        term.printLn("  cookies        //Prints all cookies.");
 | 
			
		||||
        term.printLn("  cookies -s     //(silent)Prints only cookies, no error.");
 | 
			
		||||
      });
 | 
			
		||||
    //doCookiesWork
 | 
			
		||||
    WTerminal.terminalAddCommand("docookieswork", (term) => {
 | 
			
		||||
      function getCookie(name, defaultValue = undefined) {
 | 
			
		||||
        if (name === null || name === undefined || typeof name != "string" || name == '') {
 | 
			
		||||
          console.log('error: cookie needs a name');
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        let pair = document.cookie.split(/; */).find((row) => row.startsWith(name + '='))
 | 
			
		||||
        //console.log("cookie pair: ", pair); 
 | 
			
		||||
        if (pair === undefined)
 | 
			
		||||
          return defaultValue;
 | 
			
		||||
        else
 | 
			
		||||
          return pair.split('=')[1];
 | 
			
		||||
      }
 | 
			
		||||
      function setCookie(name, value = 1, days = 7) {
 | 
			
		||||
        let date = new Date();
 | 
			
		||||
        date.setDate(date.getDate() + days); // add x days to date
 | 
			
		||||
        document.cookie = name + "=" + value + "; expires=" + date.toUTCString() + "; SameSite=strict; Secure";
 | 
			
		||||
      }
 | 
			
		||||
      function removeCookie(name) {
 | 
			
		||||
        document.cookie = name + "=0; max-age=-1" + "; SameSite=strict; Secure";
 | 
			
		||||
      }
 | 
			
		||||
      const name = "testCookie";
 | 
			
		||||
      setCookie(name);
 | 
			
		||||
      let itWorks = getCookie(name) !== undefined;
 | 
			
		||||
      if (itWorks) {
 | 
			
		||||
        removeCookie(name);
 | 
			
		||||
      }
 | 
			
		||||
      term.printLn(itWorks);
 | 
			
		||||
      return itWorks;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    initTerminalCookieCommands();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", initTerminalCookieCommands);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/js/termext/ext-eval.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/js/termext/ext-eval.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds the eval command to the terminal.
 | 
			
		||||
*/
 | 
			
		||||
{
 | 
			
		||||
  const evalHelp = function(term) {
 | 
			
		||||
    term.printLn("Uses the function eval(string) on the argLine");
 | 
			
		||||
  }
 | 
			
		||||
  const evalRun = function(term, argLine) {
 | 
			
		||||
    try {
 | 
			
		||||
      const result = eval(argLine);
 | 
			
		||||
      term.printVar(result, '`' + argLine + '`');
 | 
			
		||||
      return result;
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      term.printError(`Eval error: \`${argLine}\` -> ${error.message}`);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  const initTerminalEvalCommand = function() {
 | 
			
		||||
    if (WTerminal === undefined) { //is WTerminal not available?
 | 
			
		||||
      console.error("WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    WTerminal.terminalAddCommand("eval", evalRun, evalHelp);
 | 
			
		||||
  };
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    initTerminalEvalCommand();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", initTerminalEvalCommand);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								src/js/termext/ext-featuretest.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/js/termext/ext-featuretest.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds the test command to the terminal.
 | 
			
		||||
*               current test is to get local variables
 | 
			
		||||
*/
 | 
			
		||||
{
 | 
			
		||||
  const help = function(term) {
 | 
			
		||||
    term.printLn("Runs a test (nothing).");
 | 
			
		||||
  }
 | 
			
		||||
  const run = function(term) {
 | 
			
		||||
    term.printLn("Feature test warning: Under construction, can have unexpected results, errors and crashes.");
 | 
			
		||||
    // todo: add test ... like throw errors and stuff
 | 
			
		||||
 | 
			
		||||
    // throw {name : "NotImplementedError", message : "too lazy to implement"};
 | 
			
		||||
    // throw new Error("too lazy to implement", "some name perhaps?");
 | 
			
		||||
    // class TerminalError extends Error{
 | 
			
		||||
    //   constructor(msg, name="TerminalError"){
 | 
			
		||||
    //     super(msg);
 | 
			
		||||
    //     this.name = name;
 | 
			
		||||
    //   }
 | 
			
		||||
    // }
 | 
			
		||||
    // throw new TerminalError("my message", "MyName");
 | 
			
		||||
    let num = 1;
 | 
			
		||||
    num.toPrecision(500);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const addExtention = function() {
 | 
			
		||||
    if (WTerminal === undefined) { //is WTerminal not available?
 | 
			
		||||
      console.error("AddExtention Error: WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    WTerminal.terminalAddCommand("featuretest", run, help);
 | 
			
		||||
    //add alias
 | 
			
		||||
    WTerminal.terminalAddAlias("ft", "featuretest");
 | 
			
		||||
  };
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    addExtention();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", addExtention);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								src/js/termext/ext-passw.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/js/termext/ext-passw.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds a password generatiing- and testing function
 | 
			
		||||
*/
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  const generatePasswordHelp = function(term) {
 | 
			
		||||
    term.printLn("Generates a new password and prints it out. But also copies it for you.");
 | 
			
		||||
  }
 | 
			
		||||
  const generatePassword = function(term, argLine) {
 | 
			
		||||
    const UPPERCASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 | 
			
		||||
    const LOWERCASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
 | 
			
		||||
    const NUMBERS = "1234567890";
 | 
			
		||||
    const SPECIAL_CHARACTERS = "!@#$%^&*()_-+=,./<>\\|[]{}";
 | 
			
		||||
    const ALL_CHARACTERS = UPPERCASE_LETTERS + LOWERCASE_LETTERS + NUMBERS + SPECIAL_CHARACTERS;
 | 
			
		||||
    let passwd = "";
 | 
			
		||||
    let length = 15;
 | 
			
		||||
    for (let i = 0; i < length; i++) {
 | 
			
		||||
      passwd += ALL_CHARACTERS.charAt(Math.floor(Math.random() * ALL_CHARACTERS.length));
 | 
			
		||||
    }
 | 
			
		||||
    const el = document.createElement('span');
 | 
			
		||||
    el.innerText = passwd;
 | 
			
		||||
    // el.style.fontSize = 'x-large';
 | 
			
		||||
    el.style.paddingLeft = '1em';
 | 
			
		||||
    term.printLn("Generated password(length=" + length + "):", el);
 | 
			
		||||
    navigator.clipboard.writeText(passwd);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const isPasswordSafeHelp = function(term) {
 | 
			
		||||
    term.printLn("Checks if a password is posted as breached by pwnedpasswords.com");
 | 
			
		||||
  };
 | 
			
		||||
  const isPasswordSafe = function(term, argLine) {
 | 
			
		||||
    const sha1 = function(string) {
 | 
			
		||||
      const buffer = new TextEncoder("utf-8").encode(string);
 | 
			
		||||
      return crypto.subtle.digest("SHA-1", buffer).then(function(buffer) {
 | 
			
		||||
        // Get the hex code
 | 
			
		||||
        let hexCodes = [];
 | 
			
		||||
        const padding = '00000000'
 | 
			
		||||
        const view = new DataView(buffer);
 | 
			
		||||
        for (let i = 0; i < view.byteLength; i += 4) {
 | 
			
		||||
          // Using getUint32 reduces the number of iterations needed (we process 4 bytes each time)
 | 
			
		||||
          const value = view.getUint32(i)
 | 
			
		||||
          // toString(16) will give the hex representation of the number without padding
 | 
			
		||||
          const stringValue = value.toString(16)
 | 
			
		||||
          // We use concatenation and slice for padding
 | 
			
		||||
          const paddedValue = (padding + stringValue).slice(-padding.length)
 | 
			
		||||
          hexCodes.push(paddedValue);
 | 
			
		||||
        }
 | 
			
		||||
        // Join all the hex strings into one
 | 
			
		||||
        return hexCodes.join("");
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
    const password = argLine;
 | 
			
		||||
    term.printLn("Checking password, please wait...");
 | 
			
		||||
 | 
			
		||||
    sha1(password).then((hash) => {
 | 
			
		||||
      fetch("https://api.pwnedpasswords.com/range/" + hash.substr(0, 5)).then((response) => response.text()).then((response) => {
 | 
			
		||||
 | 
			
		||||
        const respLines = response.split('\n');
 | 
			
		||||
        const hashSub = hash.slice(5).toUpperCase();
 | 
			
		||||
        let isSafe = true;
 | 
			
		||||
        // console.log('hash: ' + hashSub);
 | 
			
		||||
        for (let i in respLines) {
 | 
			
		||||
          // console.log(i+': '+respLines[i])
 | 
			
		||||
          if (respLines[i].substring(0, hashSub.length) == hashSub) {
 | 
			
		||||
            isSafe = false;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (isSafe) {
 | 
			
		||||
          term.printLn("Password is safe.");
 | 
			
		||||
        } else {
 | 
			
		||||
          term.printLn("Password has been breached.");
 | 
			
		||||
        }
 | 
			
		||||
      }).catch((err) => {
 | 
			
		||||
        outputSafe.innerText = "Could not check if password is safe: " + err;
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const initTerminalPasswCommands = function() {
 | 
			
		||||
    if (WTerminal === undefined) { //is WTerminal not available?
 | 
			
		||||
      console.error("WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WTerminal.terminalAddCommand("generatepassword", generatePassword, generatePasswordHelp);
 | 
			
		||||
    WTerminal.terminalAddCommand("ispasswordsafe", isPasswordSafe, isPasswordSafeHelp);
 | 
			
		||||
  };
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    initTerminalPasswCommands();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", initTerminalPasswCommands);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										164
									
								
								src/js/termext/ext-popvar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								src/js/termext/ext-popvar.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,164 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds the test command to the terminal.
 | 
			
		||||
*               current test is to get local variables
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
{// this code block hides the variables below from other scripts.
 | 
			
		||||
  const runPopVar = function(term, argLine) {
 | 
			
		||||
    const PAUSE_SYMBOL = "◼";
 | 
			
		||||
    const INTERVAL_TIME = "1000"; // 1000 == 1second
 | 
			
		||||
 | 
			
		||||
    class PopUpWindow {
 | 
			
		||||
      static popupCounter = 0;
 | 
			
		||||
      constructor(variableName, term) {
 | 
			
		||||
        this.variableName = variableName;
 | 
			
		||||
        this.printVar = term.printVar;
 | 
			
		||||
        this._getObjType = term._getObjType;
 | 
			
		||||
        this._printObject = term._printObject;
 | 
			
		||||
        this.printLn = term.printLn;
 | 
			
		||||
        this.options = {};
 | 
			
		||||
        let o = this.options;
 | 
			
		||||
        let to = term.options;
 | 
			
		||||
        o.printToConsoleLog = false;
 | 
			
		||||
        o.tpo_unknownObjectPrint = to.tpo_unknownObjectPrint;
 | 
			
		||||
        o.tpo_objectPrefix = to.tpo_objectPrefix;
 | 
			
		||||
        o.tpo_specialPrefix = to.tpo_specialPrefix;
 | 
			
		||||
        o.tpo_maxDepth = to.tpo_maxDepth;
 | 
			
		||||
        o.tpo_innerMaxLength = to.tpo_innerMaxLength;
 | 
			
		||||
        this.createPopup();
 | 
			
		||||
        this.printVariable();
 | 
			
		||||
        this.intervalId = setInterval(() => this.printVariable(), INTERVAL_TIME);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      createPopup() {
 | 
			
		||||
        const t = 2 + PopUpWindow.popupCounter++;
 | 
			
		||||
        let containerStyle = 'border: 1px solid black; z-index: 9990; position: absolute; background: #ffffffa0; border-radius: 2px; backdrop-filter: blur(3px); box-shadow: 3px 3px 3px #00000066;';
 | 
			
		||||
        containerStyle += ` top: ${t}em; left: ${t}em;`;
 | 
			
		||||
        this.container = WTerminal.createElement('div', { style: containerStyle, title: this.variableName });
 | 
			
		||||
        const outputStyle = 'margin: 2px; font-family: Monospace, Incosolata, Courier; font-size: 12px; line-height: 1.05;';// overflow-y: scroll; max-height: ' + (window.innerHeight-80) +'px;';
 | 
			
		||||
        this.outputEl = WTerminal.createElement('pre', { style: outputStyle });
 | 
			
		||||
        this.btnPauseContinue = WTerminal.createElement('button', { title: "pause" });
 | 
			
		||||
        this.btnPauseContinue.innerHTML = PAUSE_SYMBOL;
 | 
			
		||||
        this.btnPauseContinue.addEventListener("click", () => this.onPausePlay());
 | 
			
		||||
        let btnRefresh = WTerminal.createElement('button', { title: "refresh" });
 | 
			
		||||
        btnRefresh.innerHTML = '↻';
 | 
			
		||||
        btnRefresh.addEventListener("click", () => this.printVariable());
 | 
			
		||||
        let btnClose = WTerminal.createElement('button', { title: 'close' });
 | 
			
		||||
        btnClose.addEventListener("click", () => this.closePopup());
 | 
			
		||||
        btnClose.innerHTML = "✖";
 | 
			
		||||
        let headerDiv = WTerminal.createElement('div', { style: "border-bottom: 1px solid black; padding: 2px; background: #00000060" });
 | 
			
		||||
        headerDiv.appendChild(btnRefresh);
 | 
			
		||||
        headerDiv.appendChild(this.btnPauseContinue);
 | 
			
		||||
        headerDiv.appendChild(document.createTextNode(" Popvar " + PopUpWindow.popupCounter));
 | 
			
		||||
        let spanForClose = WTerminal.createElement('span', { style: "float: right;" }, btnClose);
 | 
			
		||||
        headerDiv.appendChild(spanForClose);
 | 
			
		||||
        this.container.appendChild(headerDiv);
 | 
			
		||||
        this.container.appendChild(this.outputEl);
 | 
			
		||||
        document.body.appendChild(this.container);
 | 
			
		||||
 | 
			
		||||
        headerDiv.onmousedown = (e) => this.startDrag(e);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      onPausePlay() {
 | 
			
		||||
        if (this.intervalId === 0) {
 | 
			
		||||
          this.intervalId = setInterval(() => this.printVariable(), INTERVAL_TIME);
 | 
			
		||||
          this.printVariable();
 | 
			
		||||
          this.btnPauseContinue.innerHTML = PAUSE_SYMBOL;
 | 
			
		||||
          this.btnPauseContinue.title = "pause";
 | 
			
		||||
        } else {
 | 
			
		||||
          clearInterval(this.intervalId);
 | 
			
		||||
          this.intervalId = 0;
 | 
			
		||||
          this.btnPauseContinue.innerHTML = "►";
 | 
			
		||||
          this.btnPauseContinue.title = "play";
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      printVariable() {
 | 
			
		||||
        const oldOutput = this.outputEl;
 | 
			
		||||
        const outputStyle = 'margin: 2px; font-family: Monospace, Incosolata, Courier; font-size: 12px; line-height: 1.05;';// overflow-y: scroll; max-height: ' + (window.innerHeight-80) +'px;';
 | 
			
		||||
        this.outputEl = WTerminal.createElement('pre', { style: outputStyle });
 | 
			
		||||
        this.printVar(WTerminal.getGlobalVariable(this.variableName), this.variableName);
 | 
			
		||||
        oldOutput.replaceWith(this.outputEl);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      closePopup() {
 | 
			
		||||
        document.body.removeChild(this.container);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      startDrag(e) {
 | 
			
		||||
        if (e.button !== 0) return;
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        this.pos3 = e.clientX;
 | 
			
		||||
        this.pos4 = e.clientY;
 | 
			
		||||
        document.onmouseup = () => this.endDrag();
 | 
			
		||||
        document.onmousemove = (e) => this.dragPopup(e);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      dragPopup(e) {
 | 
			
		||||
        // e = e || window.event;
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        this.pos1 = this.pos3 - e.clientX;
 | 
			
		||||
        this.pos2 = this.pos4 - e.clientY;
 | 
			
		||||
        this.pos3 = e.clientX;
 | 
			
		||||
        this.pos4 = e.clientY;
 | 
			
		||||
        this.container.style.top = (this.container.offsetTop - this.pos2) + "px";
 | 
			
		||||
        this.container.style.left = (this.container.offsetLeft - this.pos1) + "px";
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      endDrag() {
 | 
			
		||||
        document.onmouseup = null;
 | 
			
		||||
        document.onmousemove = null;
 | 
			
		||||
      }
 | 
			
		||||
    };//class PopUpWindow
 | 
			
		||||
 | 
			
		||||
    if (globalThis === undefined) {
 | 
			
		||||
      term.printError("Popvar error: Missing globalThis");
 | 
			
		||||
    } else if (argLine == '') {
 | 
			
		||||
      term.printError("Popvar error: No name");
 | 
			
		||||
    } else {
 | 
			
		||||
      // return new PopUpWindow(argLine, term);
 | 
			
		||||
      new PopUpWindow(argLine, term);
 | 
			
		||||
    }
 | 
			
		||||
  }// runPopvar
 | 
			
		||||
 | 
			
		||||
  const initTerminalVariableCommands = function() {
 | 
			
		||||
    const ext = {
 | 
			
		||||
      popvar: {
 | 
			
		||||
        run: runPopVar,
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Creates a popup window with (refreshable) the given variable contents.");
 | 
			
		||||
          term.printBold("Usage:");
 | 
			
		||||
          term.printLn("popvar VARIABLE_NAME               //shows VARIABLE_NAME contents in a popup");
 | 
			
		||||
          term.printBold("Samples:");
 | 
			
		||||
          term.printLn("popvar terminal                    //Shows the terminal variable contents in a popup");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const aliases = {
 | 
			
		||||
      pop: "popvar",
 | 
			
		||||
      pt: "popvar terminal",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (WTerminal === undefined) { //is WTerminal not available?
 | 
			
		||||
      console.error("WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    //add commands in ext
 | 
			
		||||
    for (let c of Object.keys(ext)) {
 | 
			
		||||
      WTerminal.terminalAddCommand(c, ext[c].run, ext[c].help);
 | 
			
		||||
    }
 | 
			
		||||
    //add aliases
 | 
			
		||||
    for (let c of Object.keys(aliases)) {
 | 
			
		||||
      WTerminal.terminalAddAlias(c, aliases[c]);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    initTerminalVariableCommands();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", initTerminalVariableCommands);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/js/termext/ext-stresstest.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/js/termext/ext-stresstest.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds the test command to the terminal.
 | 
			
		||||
*               current test is to get local variables
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
{// this code block hides the variables below from other scripts.
 | 
			
		||||
  const initTerminalStressTestCommand = function() {
 | 
			
		||||
    const help = function(term) {
 | 
			
		||||
      term.printLn("Runs a stress test on the terminal.");
 | 
			
		||||
    };
 | 
			
		||||
    const run = function(term, argLine) {
 | 
			
		||||
      const testArgLine = function(str) {
 | 
			
		||||
        term.printVar(WTerminal.splitToArguments(str), '`' + argLine + '`.<b>splitToArguments()</b>');
 | 
			
		||||
      };
 | 
			
		||||
      if (argLine != '') testArgLine(argLine);
 | 
			
		||||
      term.terminalCommand("? && alias && const && option && date && time && uptime && starttime && echo OK", true);
 | 
			
		||||
      term.terminalCommand("? help && help alias && ? const && ? option && ? date && ? time && ? uptime", true);
 | 
			
		||||
      term.terminalCommand("thisterminal && gg", true);
 | 
			
		||||
      term.terminalCommand('gdb && result .2 && result .children.0 && result .innerHTML', true);
 | 
			
		||||
      term.terminalCommand('eval 10000+4*(1+4*10) + Math.PI', true);
 | 
			
		||||
      term.terminalCommand('dovar alert "finished stresstest"', true);
 | 
			
		||||
      // term.terminalCommand('dovar document.getElementById ' + TERMINAL_OUTPUT_ID + ' && result .innerHTML', true);
 | 
			
		||||
 | 
			
		||||
      return term.lastResult;
 | 
			
		||||
    };
 | 
			
		||||
    //add command
 | 
			
		||||
    if (WTerminal === undefined) {
 | 
			
		||||
      console.error("WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    WTerminal.terminalAddCommand("stresstest", run, help);
 | 
			
		||||
  };
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    initTerminalStressTestCommand();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", initTerminalStressTestCommand);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								src/js/termext/ext-timerdebug.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/js/termext/ext-timerdebug.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds the test command to the terminal.
 | 
			
		||||
*               current test is to get local variables
 | 
			
		||||
*/
 | 
			
		||||
{
 | 
			
		||||
  const addExtention = function() {
 | 
			
		||||
    const help = function(term) {
 | 
			
		||||
      term.printLn("Installs a logger at setTimeout and setInterval.");
 | 
			
		||||
    }
 | 
			
		||||
    const run = function(term) {
 | 
			
		||||
      //capture setTimeout
 | 
			
		||||
      const oldSetTimeout = setTimeout;
 | 
			
		||||
      setTimeout = function() {
 | 
			
		||||
        const e = new Error('Just for stack trace');
 | 
			
		||||
        const result = oldSetTimeout.apply(this, arguments);
 | 
			
		||||
        if (term) term.printLn(`New timeout ${result} registered.\n from: ${e.stack}`);
 | 
			
		||||
        else console.log(`New timeout ${result} registered from: ${e.stack}`);
 | 
			
		||||
        return result;
 | 
			
		||||
      };
 | 
			
		||||
      //capture setInterval
 | 
			
		||||
      const oldSetInterval = setInterval;
 | 
			
		||||
      setInterval = function() {
 | 
			
		||||
        const e = new Error('Just for stack trace');
 | 
			
		||||
        const result = oldSetInterval.apply(this, arguments);
 | 
			
		||||
        if (term) term.printLn(`New interval ${result} registered.\n from: ${e.stack}`);
 | 
			
		||||
        else console.log(`New interval ${result} registered from: ${e.stack}`);
 | 
			
		||||
        return result;
 | 
			
		||||
      }
 | 
			
		||||
      term.printLn("activated");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (WTerminal === undefined) { //is WTerminal not available?
 | 
			
		||||
      console.error("WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    WTerminal.terminalAddCommand("timerdebug", run, help);
 | 
			
		||||
  };
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    addExtention();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", addExtention);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										348
									
								
								src/js/termext/ext-variables.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								src/js/termext/ext-variables.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,348 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This adds the test command to the terminal.
 | 
			
		||||
*               current test is to get local variables
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
{// this code block hides the variables below from other scripts.
 | 
			
		||||
  const initTerminalVariableCommands = function() {
 | 
			
		||||
    const ext =
 | 
			
		||||
    {
 | 
			
		||||
      dovar: {
 | 
			
		||||
        run: function(term, argLine) {
 | 
			
		||||
          function _doFunction(gVar, functionKey, args) {
 | 
			
		||||
            if (typeof gVar === "object" && typeof gVar[functionKey] === "function") {
 | 
			
		||||
              // term.printVar(args, "do args");
 | 
			
		||||
              return gVar[functionKey](...args);
 | 
			
		||||
            } else {
 | 
			
		||||
              term.printError("Do error: " + functionKey + " is not a function");
 | 
			
		||||
            }
 | 
			
		||||
          };
 | 
			
		||||
          /* To run a function of a Class (like document.getElementById(..))
 | 
			
		||||
          *  We need the parent- /class-object from witch we call it from, to prevent errors (illegal acces) 
 | 
			
		||||
          *  todo: ? --> use apply https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
 | 
			
		||||
          */
 | 
			
		||||
          if (globalThis === undefined) {
 | 
			
		||||
            term.printError("Do error: Missing globalThis");
 | 
			
		||||
          } else if (argLine == '') {
 | 
			
		||||
            term.printError("Do error: No name");
 | 
			
		||||
          } else {
 | 
			
		||||
            let args = WTerminal.splitToArguments(argLine);
 | 
			
		||||
            const verbal = args.includes("-v");
 | 
			
		||||
            if (verbal) {
 | 
			
		||||
              args = args.filter(e => e !== '-v');
 | 
			
		||||
            }
 | 
			
		||||
            const gName = args.shift(); //full global function name
 | 
			
		||||
            args.forEach(e => e = WTerminal.stringToValue(e));
 | 
			
		||||
            let pName = gName.split('.'); //last object's parent name
 | 
			
		||||
            let result;
 | 
			
		||||
            if (pName.length == 1) {
 | 
			
		||||
              result = _doFunction(globalThis, gName, args)
 | 
			
		||||
            } else {
 | 
			
		||||
              const lastName = pName.pop(); //last object name
 | 
			
		||||
              result = _doFunction(WTerminal.getGlobalVariable(pName.join('.')), lastName, args);
 | 
			
		||||
            }
 | 
			
		||||
            if (verbal) term.printVar(result, gName + "(" + args.join(' ') + ")");
 | 
			
		||||
            return result;
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Runs given global function with arguments, and returns result.");
 | 
			
		||||
          term.printBold("Usage:");
 | 
			
		||||
          term.printLn("dovar FUNCTION_NAME [ArgumentS]                 //Runs function FUNCTION_NAME with optional ArgumentS");
 | 
			
		||||
          term.printLn("dovar -v FUNCTION_NAME [ArgumentS]              //Same as above but prints result too.");
 | 
			
		||||
          term.printBold("Samples:");
 | 
			
		||||
          term.printLn("dovar window.open https://developer.mozilla.org  //Runs function window.open() with the url as argument");
 | 
			
		||||
          term.printLn("dovar -v document.getElementById terminal-up     //Runs function document.getElementById with terminal-up as argument")
 | 
			
		||||
          term.printLn("dovar document.body.remove                       //Warning: removes all page content");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      getvar: {
 | 
			
		||||
        run: function(term, argLine) {
 | 
			
		||||
          if (globalThis === undefined) {
 | 
			
		||||
            term.printError("Getvar error: Missing globalThis");
 | 
			
		||||
          } else if (argLine == '') {
 | 
			
		||||
            term.printError("Getvar error: Missing argument: VARIABLE_NAME");
 | 
			
		||||
          } else {
 | 
			
		||||
            let result = {};
 | 
			
		||||
            const args = WTerminal.splitToArguments(argLine);
 | 
			
		||||
            for (const gName of args) {
 | 
			
		||||
              result[gName] = WTerminal.getGlobalVariable(gName);
 | 
			
		||||
            }
 | 
			
		||||
            const keys = Object.keys(result);
 | 
			
		||||
            if (keys.length == 1) {
 | 
			
		||||
              return result[keys[0]];
 | 
			
		||||
            } else {
 | 
			
		||||
              return result;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Gets a global variable and returns it.");
 | 
			
		||||
          term.printLn("The returned result will be found in terminal.lastResult")
 | 
			
		||||
          term.printBold("Usage:");
 | 
			
		||||
          term.printLn("getvar VARIABLE_NAME");
 | 
			
		||||
          term.printBold("Samples:");
 | 
			
		||||
          term.printLn("getvar terminal                  //Returns terminal");
 | 
			
		||||
          term.printLn("getvar terminal.version          //Returns terminal.version");
 | 
			
		||||
          term.printLn("getvar var1 var2 var3            //Returns an object with var1 var2 and var3 keys and their global found value.");
 | 
			
		||||
          term.printLn("getvar document                  //Returns global document object.");
 | 
			
		||||
          term.printLn("getvar document.body.children    //Returns a list of the children in the body.");
 | 
			
		||||
          term.printLn("getvar document.head.children    //Returns a list of the children in the head.");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      globals: {
 | 
			
		||||
        run: function(term) {
 | 
			
		||||
          if (globalThis !== undefined) {
 | 
			
		||||
            term.printVar(globalThis, "globalThis");
 | 
			
		||||
          } else if (self !== undefined) {
 | 
			
		||||
            term.printVar(self, "self");
 | 
			
		||||
          } else if (global !== undefined) {
 | 
			
		||||
            term.printVar(global, "global");
 | 
			
		||||
          } else {
 | 
			
		||||
            term.printError("Globals error: No globals!?");
 | 
			
		||||
          }
 | 
			
		||||
          if (document !== undefined && globalThis.document !== document) term.printVar(document, "document");
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Prints all global variables.");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      logvar: {
 | 
			
		||||
        run: function(term, argLine) {
 | 
			
		||||
          if (globalThis === undefined) {
 | 
			
		||||
            term.printError("LogVar error: Missing globalThis");
 | 
			
		||||
          } else if (argLine == '') {
 | 
			
		||||
            term.printError("LogVar error: Missing argument: VARIABLE_NAME");
 | 
			
		||||
          } else {
 | 
			
		||||
            let result = {};
 | 
			
		||||
            let args = WTerminal.splitToArguments(argLine);
 | 
			
		||||
            const returnResult = args.includes("-r");
 | 
			
		||||
            if (returnResult) {
 | 
			
		||||
              args = args.filter(e => e !== '-r');
 | 
			
		||||
            }
 | 
			
		||||
            for (const gName of args) {
 | 
			
		||||
              result[gName] = WTerminal.getGlobalVariable(gName);
 | 
			
		||||
            }
 | 
			
		||||
            if (Object.keys(result).length == 1) {
 | 
			
		||||
              result = result[Object.keys(result)[0]];
 | 
			
		||||
            }
 | 
			
		||||
            // term.printVar(result);
 | 
			
		||||
            console.log(result);
 | 
			
		||||
            if (returnResult) return result;
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Like printvar but Logs variable(s) to console.");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      printvar: {
 | 
			
		||||
        run: function(term, argLine) {
 | 
			
		||||
          if (globalThis === undefined) {
 | 
			
		||||
            term.printError("PrintVar error: Missing globalThis");
 | 
			
		||||
          } else if (argLine == '') {
 | 
			
		||||
            term.printError("PrintVar error: Missing argument: VARIABLE_NAME");
 | 
			
		||||
          } else {
 | 
			
		||||
            let result = {};
 | 
			
		||||
            let args = WTerminal.splitToArguments(argLine);
 | 
			
		||||
            const returnResult = args.includes("-r");
 | 
			
		||||
            if (returnResult) {
 | 
			
		||||
              args = args.filter(e => e !== '-r');
 | 
			
		||||
            }
 | 
			
		||||
            for (const gName of args) {
 | 
			
		||||
              result[gName] = WTerminal.getGlobalVariable(gName);
 | 
			
		||||
            }
 | 
			
		||||
            const keys = Object.keys(result);
 | 
			
		||||
            if (keys.length == 1) {
 | 
			
		||||
              result = result[keys[0]];
 | 
			
		||||
              term.printVar(result, keys[0]);
 | 
			
		||||
            } else {
 | 
			
		||||
              term.printVar(result);
 | 
			
		||||
            }
 | 
			
		||||
            if (returnResult) return result;
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Prints value of global variable.");
 | 
			
		||||
          term.printBold("Usage:");
 | 
			
		||||
          term.printLn("printvar VARIABLE_NAME           //Prints variable, returns nothing.");
 | 
			
		||||
          term.printLn("printvar -r VARIABLE_NAME        //Prints variable, returns variable.");
 | 
			
		||||
          term.printBold("Samples:");
 | 
			
		||||
          term.printLn("printvar terminal                //Prints terminal");
 | 
			
		||||
          term.printLn("printvar terminal.version        //Prints terminal.version");
 | 
			
		||||
          term.printLn("printvar -r terminal.lastResult  //Prints terminal.lastResult and returns it.");
 | 
			
		||||
          term.printLn("printvar document                //Prints global document object.");
 | 
			
		||||
          term.printLn("printvar document.body.children  //Prints body elements.");
 | 
			
		||||
          term.printLn("printvar document.head.children  //Prints head elements.");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      removevar: {
 | 
			
		||||
        run: function(term, argLine) {
 | 
			
		||||
          if (globalThis === undefined) {
 | 
			
		||||
            term.printError("RemoveVar error: Missing globalThis");
 | 
			
		||||
          } else if (argLine == '') {
 | 
			
		||||
            term.printError("RemoveVar error: Missing arguments");
 | 
			
		||||
          } else {
 | 
			
		||||
            let args = WTerminal.splitToArguments(argLine);
 | 
			
		||||
            const keys = Object.keys(globalThis);
 | 
			
		||||
            const verbal = args.includes("-v");
 | 
			
		||||
            if (verbal) {
 | 
			
		||||
              args = args.filter(e => e !== '-v');
 | 
			
		||||
            }
 | 
			
		||||
            let count = 0;
 | 
			
		||||
            if (args.includes("-a")) {
 | 
			
		||||
              count = keys.length;
 | 
			
		||||
              keys.forEach(key => {
 | 
			
		||||
                if (verbal) term.printLn("removing: " + key)
 | 
			
		||||
                delete globalThis[key];
 | 
			
		||||
              });
 | 
			
		||||
              term.printLn("Removed " + count + " keys.")
 | 
			
		||||
              return;
 | 
			
		||||
            } else if (args.includes("-n")) {
 | 
			
		||||
              args = args.filter(e => e !== '-n');
 | 
			
		||||
              keys.forEach(key => {
 | 
			
		||||
                if (globalThis[key] === null || globalThis[key] === undefined) {
 | 
			
		||||
                  if (verbal) term.printLn("removing: " + key)
 | 
			
		||||
                  delete globalThis[key];
 | 
			
		||||
                  count++;
 | 
			
		||||
                }
 | 
			
		||||
              });
 | 
			
		||||
            } else if (args.includes("-f")) {
 | 
			
		||||
              args = args.filter(e => e !== '-f');
 | 
			
		||||
              keys.forEach(key => {
 | 
			
		||||
                if (globalThis[key] !== globalThis &&
 | 
			
		||||
                  !(typeof globalThis[key] === "function" && globalThis[key].toString().includes("[native code]"))) {
 | 
			
		||||
                  if (verbal) term.printLn("removing: " + key)
 | 
			
		||||
                  delete globalThis[key];
 | 
			
		||||
                  count++;
 | 
			
		||||
                }
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
            while (args.length > 0) {
 | 
			
		||||
              const gName = args.shift(); //full global function name
 | 
			
		||||
              const pName = gName.split('.'); //last object's parent name
 | 
			
		||||
              const lastName = pName.pop(); //last object name
 | 
			
		||||
              let obj = globalThis;
 | 
			
		||||
              if (pName.length > 0) {
 | 
			
		||||
                obj = WTerminal.getGlobalVariable(pName.join('.')); //parent object
 | 
			
		||||
              }
 | 
			
		||||
              if (obj !== undefined && obj[lastName] !== undefined) {
 | 
			
		||||
                if (verbal) term.printLn("removing: " + gName)
 | 
			
		||||
                delete obj[lastName];
 | 
			
		||||
                count++;
 | 
			
		||||
              } else {
 | 
			
		||||
                if (obj === undefined) {
 | 
			
		||||
                  term.printError("Variable " + pName.join(".") + " = undefined")
 | 
			
		||||
                } else {
 | 
			
		||||
                  term.printError("Variable " + gName + " = undefined");
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            term.printLn("Removed " + (count > 1 ? (count + " keys.") : (count === 0 ? "nothing" : "1 key")));
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printLn("Removes global variables.");
 | 
			
		||||
          term.printBold("Usage:");
 | 
			
		||||
          term.printLn("removevar -v ...            //Prints removing VARIABLE_NAME.");
 | 
			
		||||
          term.printLn("removevar -f                //Removes all global variables that are not a parent redefinition or native function.");
 | 
			
		||||
          term.printLn("removevar -n                //Removes all null or undefined global variables.");
 | 
			
		||||
          term.printLn("removevar -a                //Removes ALL global variables.");
 | 
			
		||||
          term.printLn("removevar VARIABLE_NAMES    //Removes the global variables provided.")
 | 
			
		||||
          term.printBold("Samples:");
 | 
			
		||||
          term.printLn("removevar terminal          //Removes the global variable terminal.");
 | 
			
		||||
          term.printLn("removevar var1 var2         //Removes the 2 global variables var1 and var2.");
 | 
			
		||||
          term.printLn("removevar terminal.history  //Removes history from terminal.");
 | 
			
		||||
          term.printLn("removevar -n terminal.history  //Removes history from terminal, and all null or undefined global variables.");
 | 
			
		||||
          term.printLn("removevar -n -v             //Prints variable names of all null or undefined global variables it removes.");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      setvar: {
 | 
			
		||||
        run: function(term, argLine) {
 | 
			
		||||
          if (globalThis === undefined) {
 | 
			
		||||
            term.printError("Setvar error: Missing globalThis");
 | 
			
		||||
          } else {
 | 
			
		||||
            if (argLine == '') {
 | 
			
		||||
              term.printError("Setvar error: no name");
 | 
			
		||||
            } else {
 | 
			
		||||
              let args = WTerminal.splitToArguments(argLine);
 | 
			
		||||
              for (const element of args) {
 | 
			
		||||
                const keyValuePair = element.split("=");
 | 
			
		||||
                  if(keyValuePair.length < 2) throw new Error("missing arguements.");
 | 
			
		||||
                const names = keyValuePair[0].split(".");
 | 
			
		||||
                const value = WTerminal.stringToValue(keyValuePair[1]);
 | 
			
		||||
                if (names.length == 1) {
 | 
			
		||||
                  globalThis[names[0]] = value;
 | 
			
		||||
                  term.printVar(globalThis[names[0]], keyValuePair[0]);
 | 
			
		||||
                } else {
 | 
			
		||||
                  let obj = globalThis;
 | 
			
		||||
                  for (let i = 0; i < names.length - 1; i++) {
 | 
			
		||||
                    if (typeof obj[names[i]] === "object") obj = obj[names[i]];
 | 
			
		||||
                    else {
 | 
			
		||||
                      let rem = names.length - 1 - i;
 | 
			
		||||
                      names.splice(names.length - rem, rem);
 | 
			
		||||
                      let name = names.join('.');
 | 
			
		||||
                      term.printError(`Variable ${keyValuePair[0]} is not an object!`);
 | 
			
		||||
                      term.printVar(obj[names[i]], name);
 | 
			
		||||
                      return;
 | 
			
		||||
                    };
 | 
			
		||||
                  }
 | 
			
		||||
                  obj[names[names.length - 1]] = value;
 | 
			
		||||
                  return obj[names[names.length - 1]];
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        help: function(term) {
 | 
			
		||||
          term.printBold("Usage:");
 | 
			
		||||
          term.printLn("setvar NAME=VALUE                                //Sets VALUE to a global variable, NAME, and returns it.");
 | 
			
		||||
          term.printBold("Samples:");
 | 
			
		||||
          term.printLn("setvar terminal                                  //Sets terminal to undefined");
 | 
			
		||||
          term.printLn("setvar terminal.version=prehistoric              //Sets terminal.version to string `prehistoric`");
 | 
			
		||||
          term.printLn("setvar myNumber=8                                //Sets myNumber to number 8");
 | 
			
		||||
          term.printLn("setvar myNumber=(number)-8.1                     //Sets myNumber to number -8.1");
 | 
			
		||||
          term.printLn("setvar var1 var2 var3                            //Creates 3 undefined variables");
 | 
			
		||||
          term.printLn("setvar myName=\"Ward Truyen\"                      //Sets myName to string");
 | 
			
		||||
          term.printLn('setvar obj={"1":"test","2":true}                 //Sets obj to JSON.stringified object');
 | 
			
		||||
          term.printLn("setvar myFunc=(function)terminalPrintLn(\"Hello\");//Creates a function");
 | 
			
		||||
          term.printLn("setvar myVar=(global)myFunc                      //Sets(binds) myVar to the contents of myFunc");
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
    const aliases = {
 | 
			
		||||
      run: "dovar",
 | 
			
		||||
      pdo: "dovar -v ",
 | 
			
		||||
      g: "getvar",
 | 
			
		||||
      gg: "globals",
 | 
			
		||||
      db: "printvar -r document.body.children",
 | 
			
		||||
      dh: "printvar -r document.head.children",
 | 
			
		||||
      gdb: "printvar -r document.body.children ",
 | 
			
		||||
      gdh: "printvar -r document.head.children ",
 | 
			
		||||
      result: "printvar -r terminal.lastResult",
 | 
			
		||||
      error: "printvar terminal.lastError",
 | 
			
		||||
      pv: "printvar -r ",
 | 
			
		||||
      terminal: "printvar -r terminal",
 | 
			
		||||
      // history: "printvar terminal.history",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //add commands in ext
 | 
			
		||||
    if (WTerminal === undefined) {
 | 
			
		||||
      console.error("WTerminal is missing!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    for (let c of Object.keys(ext)) {
 | 
			
		||||
      WTerminal.terminalAddCommand(c, ext[c].run, ext[c].help);
 | 
			
		||||
    }
 | 
			
		||||
    //add aliases
 | 
			
		||||
    for (let c of Object.keys(aliases)) {
 | 
			
		||||
      WTerminal.terminalAddAlias(c, aliases[c]);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  //init
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    initTerminalVariableCommands();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", initTerminalVariableCommands);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								src/js/theme.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/js/theme.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
function toggleTheme() {
 | 
			
		||||
  const theme = "theme-dark";//localStorage.getItem('theme');
 | 
			
		||||
  const root = document.querySelector(":root");
 | 
			
		||||
  root.classList.toggle(theme);
 | 
			
		||||
  if (root.classList.contains(theme)) {
 | 
			
		||||
    localStorage.setItem('theme', theme);
 | 
			
		||||
  } else {
 | 
			
		||||
    localStorage.setItem('theme', "theme-light");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setTheme(themeName) {
 | 
			
		||||
  console.log("setting theme: " + themeName);
 | 
			
		||||
  const root = document.querySelector(":root");
 | 
			
		||||
  root.classList.add(themeName);
 | 
			
		||||
  localStorage.setItem('theme', themeName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function detectTheme() {
 | 
			
		||||
  const theme = localStorage.getItem('theme');
 | 
			
		||||
  if (theme === 'theme-dark' || theme === 'theme-light') {
 | 
			
		||||
    setTheme(theme);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
 | 
			
		||||
    setTheme('theme-dark');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (window.matchMedia('(prefers-color-scheme: light)').matches) {
 | 
			
		||||
    setTheme('theme-light');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setTheme('theme-light');
 | 
			
		||||
}
 | 
			
		||||
detectTheme();
 | 
			
		||||
							
								
								
									
										33
									
								
								src/js/wterminal-autoextend.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/js/wterminal-autoextend.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   This auromaticly adds the other terminal extention scripts.
 | 
			
		||||
* THIS SCRIPT DOES NOT WORK FOR A BROWSER-ADDON/EXTENTION!
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
{// this code block hides the variables below from other scripts.
 | 
			
		||||
  const addScripts = function() {
 | 
			
		||||
    // location of script files
 | 
			
		||||
    const extentionScripts = [
 | 
			
		||||
      "js/termext/ext-variables.js",
 | 
			
		||||
      "js/termext/ext-cookies.js",
 | 
			
		||||
      "js/termext/ext-eval.js",
 | 
			
		||||
      "js/termext/ext-timerdebug.js",
 | 
			
		||||
      "js/termext/ext-stresstest.js",
 | 
			
		||||
      "js/termext/ext-popvar.js",
 | 
			
		||||
      "js/termext/ext-passw.js",
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    for (let ext of extentionScripts) {
 | 
			
		||||
      const element = document.createElement("script");
 | 
			
		||||
      // element.addAttribute("src", ext);
 | 
			
		||||
      element.src = ext;
 | 
			
		||||
      document.head.append(element);
 | 
			
		||||
    }
 | 
			
		||||
  }//--> addScripts = function()  {
 | 
			
		||||
 | 
			
		||||
  if (document.body) {
 | 
			
		||||
    addScripts();
 | 
			
		||||
  } else {
 | 
			
		||||
    window.addEventListener("load", addScripts);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1353
									
								
								src/js/wterminal.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1353
									
								
								src/js/wterminal.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										57
									
								
								src/pong.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/pong.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>Sample: Ping pong</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/game.css" />
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <link rel="stylesheet" href="css/wterminal.css" />
 | 
			
		||||
 | 
			
		||||
  <script src="js/wterminal.js"></script>
 | 
			
		||||
  <script src="js/wterminal-autoextend.js"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="js/theme.js"></script>
 | 
			
		||||
  <script src="js/game-pong-context2d.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="index.html">Home</a>
 | 
			
		||||
    <a href="static-terminal.html">Static</a>
 | 
			
		||||
    <a href="dropdown.html">Dropdown</a>
 | 
			
		||||
    <a href="pong.html">Pong</a>
 | 
			
		||||
    <a href="addon.html">Addon</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <span style="float:right">
 | 
			
		||||
      <button onclick="WTerminal.open()">Open terminal</button>
 | 
			
		||||
    </span>
 | 
			
		||||
    <h1>Game sample: Ping pong</h1>
 | 
			
		||||
 | 
			
		||||
    <div id="game-area" class="game-area"></div>
 | 
			
		||||
 | 
			
		||||
    <p><b><u>How to:</u></b><br>
 | 
			
		||||
      Use the arrow keys up and down to move, or [W] and [S].<br>
 | 
			
		||||
      Press spacebar or enter, to start a next round, or to pause/resume.</p>
 | 
			
		||||
    <p>To restart the game use the buttons below. Or open the terminal, type "restartgame" and press enter.</p>
 | 
			
		||||
    <p>To get more information about pong open the terminal, type "printgame" and press enter.<br>
 | 
			
		||||
      Or open the terminal, type "popvar game" and press enter (DEBUG_PARENT_OBJECT must be true for this to work).</p>
 | 
			
		||||
 | 
			
		||||
    <button onclick="startPingPong('game-area');">start normal</button>
 | 
			
		||||
    <button onclick="startPingPong('game-area', 640, 480, 1);">start large</button>
 | 
			
		||||
    <button onclick="startPingPong('game-area', 320, 240, 2);">start zoomed</button>
 | 
			
		||||
 | 
			
		||||
    <script>
 | 
			
		||||
      WTerminal.instalDropdownTerminal();
 | 
			
		||||
      startPingPong('game-area');
 | 
			
		||||
    </script>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/snd/glass-knock.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/snd/glass-knock.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/snd/short-success.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/snd/short-success.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										61
									
								
								src/static-terminal.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/static-terminal.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>WTerminal static sample</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <link rel="stylesheet" href="css/wterminal.css" />
 | 
			
		||||
 | 
			
		||||
  <script src="js/wterminal.js"></script>
 | 
			
		||||
  <script src="js/wterminal-autoextend.js"></script>
 | 
			
		||||
  <script src="js/static-terminal-buttons.js"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="index.html">Home</a>
 | 
			
		||||
    <a href="static-terminal.html">Static</a>
 | 
			
		||||
    <a href="dropdown.html">Dropdown</a>
 | 
			
		||||
    <a href="pong.html">Pong</a>
 | 
			
		||||
    <a href="addon.html">Addon</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <img style="display: none;" src="img/kitty.jpg" />
 | 
			
		||||
    <h1>Static-terminal:</h1>
 | 
			
		||||
    <p>Below we have created a WTerminal, by using it's constructor with a name ("static") and
 | 
			
		||||
      element-id("static-terminal") to generate a terminal as a 'static element on our page'.</p>
 | 
			
		||||
    <div id="static-terminal"></div>
 | 
			
		||||
    <script>
 | 
			
		||||
      new WTerminal("static", "static-terminal", null);
 | 
			
		||||
    </script>
 | 
			
		||||
    <div style="padding-top: 4px;">
 | 
			
		||||
      Samples:
 | 
			
		||||
      <input type="button" value="help" onclick="btn_terminalHelp();" />
 | 
			
		||||
      <input type="button" value="prompt" onclick="btn_promptSample();" />
 | 
			
		||||
      <input type="button" value="kitty" onclick="btn_kittySample();" /> |
 | 
			
		||||
      <input type="button" value="object" onclick="btn_printObjectSample();" /> |
 | 
			
		||||
      <input title="Clear terminal" type="button" class="button-red" value="clear" onclick="btn_terminalClear();" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <h2>How to add the terminal to a site:</h2>
 | 
			
		||||
    <p>Add the CSS and JavaScript files to your site header:<br>
 | 
			
		||||
      <code><link rel="stylesheet" href="css/wterminal.css" /><br>
 | 
			
		||||
        <script src="js/wterminal.js"></script></code>
 | 
			
		||||
    </p>
 | 
			
		||||
    <p>Where the terminal should be add a div element, with id "static-terminal":<br>
 | 
			
		||||
      <code><div id="static-terminal"></div></code>
 | 
			
		||||
    </p>
 | 
			
		||||
    <p>Finally add a script element with:<br>
 | 
			
		||||
      <code>new WTerminal("static", "static-terminal", null);</code>
 | 
			
		||||
    </p>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										38
									
								
								src/test/asserts.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/test/asserts.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>Test Asserts</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <link rel="stylesheet" href="../css/wterminal.css" />
 | 
			
		||||
 | 
			
		||||
  <script src="../js/wterminal.js"></script>
 | 
			
		||||
  <script src="../js/wterminal-autoextend.js"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="../js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="/test/">WTerminal testing home</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>Test Asserts:</h1>
 | 
			
		||||
    <div id="static-terminal"></div>
 | 
			
		||||
    <script>
 | 
			
		||||
      let term = new WTerminal("static", "static-terminal", null);
 | 
			
		||||
      term.terminalCommand("height 40em");
 | 
			
		||||
      term.clearOutput();
 | 
			
		||||
    </script>
 | 
			
		||||
    <script src="js/asserts.js"></script>
 | 
			
		||||
    <script src="js/test-asserts.js"></script>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										99
									
								
								src/test/css/main.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/test/css/main.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
/* Author:      Ward Truyen
 | 
			
		||||
 * Version:     1.3.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
html,
 | 
			
		||||
body {
 | 
			
		||||
  margin: 0px;
 | 
			
		||||
  padding: 0px;
 | 
			
		||||
  background: radial-gradient(ellipse at top, #8888ff, transparent),
 | 
			
		||||
            radial-gradient(ellipse at bottom, #ad9fff, transparent);
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main {
 | 
			
		||||
  margin: auto;
 | 
			
		||||
  width: 80%;
 | 
			
		||||
  border: 2px solid darkgreen;
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
  background-color: white;
 | 
			
		||||
  box-shadow: 3px 3px 3px black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
  margin-top: 4px;
 | 
			
		||||
  margin-bottom: 8px;
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
header {
 | 
			
		||||
  padding: 2px 16px 4px 16px;
 | 
			
		||||
  /* width: 100%; */
 | 
			
		||||
  border-bottom: 1px solid black;
 | 
			
		||||
  /* background-image: linear-gradient(#0000008f, #0000004f); */
 | 
			
		||||
  background-color: #80808080;
 | 
			
		||||
  /* linear-gradient(#0000008f, #0000004f);*/
 | 
			
		||||
  /* margin-top: 16px; */
 | 
			
		||||
  text-shadow: 1px 1px 1px #0000004f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
header a {
 | 
			
		||||
  /* border: solid 1px black; */
 | 
			
		||||
  padding: 2px;
 | 
			
		||||
  margin: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
footer {
 | 
			
		||||
  padding: 8px 16px 4px 16px;
 | 
			
		||||
  /* width: 100%; */
 | 
			
		||||
  border-top: 1px solid black;
 | 
			
		||||
  /* background-color: #0000004f; */
 | 
			
		||||
  background-image: linear-gradient(#0000008f, #0000004f);
 | 
			
		||||
  /* margin-top: 16px; */
 | 
			
		||||
  margin-top: auto;
 | 
			
		||||
  text-shadow: 1px 1px 1px #0000004f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
footer h1,
 | 
			
		||||
footer h2,
 | 
			
		||||
footer h3,
 | 
			
		||||
footer p {
 | 
			
		||||
  display: inline;
 | 
			
		||||
  margin: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.float-right {
 | 
			
		||||
  float: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.text-red {
 | 
			
		||||
  color: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-red {
 | 
			
		||||
  background-color: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-black {
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html.theme-dark {
 | 
			
		||||
  color-scheme: dark;
 | 
			
		||||
  background-image: linear-gradient(-10deg, #1010206F 60%, #5050506F);
 | 
			
		||||
  color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.theme-dark>body>main {
 | 
			
		||||
  border: 1px solid darkgray;
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  box-shadow: 3px 3px 5px #101010C0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.theme-dark>body>main>h1 {
 | 
			
		||||
  text-shadow: 0px 0px 3px blue, 2px 2px 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								src/test/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/test/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>WTerminal test home</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <!-- <link rel="stylesheet" href="../css/wterminal.css" /> -->
 | 
			
		||||
 | 
			
		||||
  <!-- <script src="../wterminal.js"></script> -->
 | 
			
		||||
  <script src="../js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="/test/">WTerminal testing home</a>
 | 
			
		||||
    <!-- <a href="splitToArguments.html">splitToArguments</a> -->
 | 
			
		||||
    <!-- <a href="asserts.html">Asserts</a> -->
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>Tests:</h1>
 | 
			
		||||
    <div style="display: inline-block;">
 | 
			
		||||
      <a href="/test/test-all.html">Test All</a><br>
 | 
			
		||||
      <hr>
 | 
			
		||||
      <a href="/test/asserts.html">Test Asserts</a><br>
 | 
			
		||||
      <a href="/test/splitToArguments.html">Test WTerminal.splitToArguments</a><br>
 | 
			
		||||
    </div>
 | 
			
		||||
    <h2>Others:</h2>
 | 
			
		||||
    <a href="../index.html">WTerminal site home</a>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										74
									
								
								src/test/js/asserts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/test/js/asserts.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/* Author: Ward Truyen
 | 
			
		||||
* Version: 1.0.0
 | 
			
		||||
* About:   A tool for testing purposes
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class Asserts {
 | 
			
		||||
  static runTest(name, testFunction, term, pre = " ", printStacktraceAndStop = true) {
 | 
			
		||||
    term.print(pre+name);
 | 
			
		||||
    try {
 | 
			
		||||
      testFunction();
 | 
			
		||||
      term.printLn(WTerminal.createElement("span", {style:"color: green;"}, " OK"));
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      term.printError(" failed: " + e.toString());
 | 
			
		||||
      if(printStacktraceAndStop){
 | 
			
		||||
        term.printLn(WTerminal.createElement("span", {style:"color: blue;"}, e.stack));
 | 
			
		||||
        throw e;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Throws error when not true
 | 
			
		||||
   */
 | 
			
		||||
  static isTrue(value) {
 | 
			
		||||
    if (value === true) return;
 | 
			
		||||
    throw new Error('assert isTrue failed');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Throws error when not false
 | 
			
		||||
   */
 | 
			
		||||
  static isFalse(value) {
 | 
			
		||||
    if (value === false) return;
 | 
			
		||||
    throw new Error('assert isFalse failed');
 | 
			
		||||
  }
 | 
			
		||||
  /* Throws error when not equal
 | 
			
		||||
   */
 | 
			
		||||
  static isEqual(value1, value2) {
 | 
			
		||||
    if (Asserts._equals(value1, value2)) return;
 | 
			
		||||
    // if( typeof value1 === "object" || typeof value2 === "object") throw new Error('assert isEqual failed');
 | 
			
		||||
    throw new Error('assert isEqual failed\n' + value1 + " != " + value2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* returns true when values/objects v1 and v2 are equal
 | 
			
		||||
   */
 | 
			
		||||
  static _equals(v1, v2, _depth = 0) {
 | 
			
		||||
    if (v1 === v2) return true; // easy peasy
 | 
			
		||||
    let t = typeof v1
 | 
			
		||||
    if (t === "string" || v1 instanceof String && typeof v2 === "string" || v2 instanceof String) return v1.valueOf() === v2.valueOf(); // "Hello" equals to new String("Hello")
 | 
			
		||||
    if (t !== typeof v2 || v1.constructor.name !== v2.constructor.name) return false; // must be of identical type
 | 
			
		||||
    t += " " + v1.constructor.name;
 | 
			
		||||
    switch (t) {
 | 
			
		||||
      default: // Yet Unkown when i coded this?
 | 
			
		||||
        throw new Error("Todo: checking of type " + t);
 | 
			
		||||
      case 'boolean Boolean':
 | 
			
		||||
      case 'number Number':
 | 
			
		||||
      case 'object Date':
 | 
			
		||||
        return v1.valueOf() === v2.valueOf();
 | 
			
		||||
      case 'object Array':
 | 
			
		||||
        if (_depth > 4) throw Error("too deep");
 | 
			
		||||
        if (v1.length !== v2.length) return false;
 | 
			
		||||
        for (let i = 0; i < v1.length; i++) {
 | 
			
		||||
          if (Asserts._equals(v1[i], v2[i], _depth + 1) === false) return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
      case 'object Object':
 | 
			
		||||
        if (_depth > 4) throw Error("too deep");
 | 
			
		||||
        const keys = Object.keys(v1);
 | 
			
		||||
        if (keys.length != Object.keys(v2).length) return false;
 | 
			
		||||
        for (let k in keys) {
 | 
			
		||||
          if (Asserts._equals(v1[k], v2[k], _depth + 1) === false) return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }//-> switch (t)
 | 
			
		||||
  }//-> static equals(v1, v2)
 | 
			
		||||
}//-> class Asserts
 | 
			
		||||
							
								
								
									
										106
									
								
								src/test/js/test-asserts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/test/js/test-asserts.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
{
 | 
			
		||||
  const term = getWTerminal();
 | 
			
		||||
  term.printLn("Testing Asserts");
 | 
			
		||||
  //isTrue testing
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(true)`,
 | 
			
		||||
    () => {
 | 
			
		||||
      try {
 | 
			
		||||
        Asserts.isTrue(true);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        throw new Error("Assserts.isTrue(true) failed", e);
 | 
			
		||||
      }
 | 
			
		||||
    }, term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(false)`,
 | 
			
		||||
    () => {
 | 
			
		||||
      let throwsNoError = true;
 | 
			
		||||
      try {
 | 
			
		||||
        Asserts.isTrue(false);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        throwsNoError = false;
 | 
			
		||||
      }
 | 
			
		||||
      if (throwsNoError) throw new Error("Assert.isTrue(false) does not throw Error");
 | 
			
		||||
    }, term);
 | 
			
		||||
  // Asserts.runTest('This test should fail', ()=>{throw new Error("To fail test")}, term);
 | 
			
		||||
  //isFalse testing
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(false)`,
 | 
			
		||||
    () => {
 | 
			
		||||
      try {
 | 
			
		||||
        Asserts.isFalse(false);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        throw new Error("Assserts.isFalse(false) failed", e);
 | 
			
		||||
      }
 | 
			
		||||
    }, term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(true)`,
 | 
			
		||||
    () => {
 | 
			
		||||
      let throwsNoError = true;
 | 
			
		||||
      try {
 | 
			
		||||
        Asserts.isFalse(true);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        throwsNoError = false;
 | 
			
		||||
      }
 | 
			
		||||
      if (throwsNoError) throw new Error("Assert.isFalse(true) does not throw Error");
 | 
			
		||||
    }, term);
 | 
			
		||||
  //isEqual testing
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(true, true)`,
 | 
			
		||||
    () => {
 | 
			
		||||
      try {
 | 
			
		||||
        Asserts.isEqual(true, true);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        throw new Error("Assserts.isEqual(true, true) failed", e);
 | 
			
		||||
      }
 | 
			
		||||
    }, term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(true, false)`,
 | 
			
		||||
    () => {
 | 
			
		||||
      let throwsNoError = true;
 | 
			
		||||
      try {
 | 
			
		||||
        Asserts.isEqual(true, false);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        throwsNoError = false;
 | 
			
		||||
      }
 | 
			
		||||
      if (throwsNoError) throw new Error("Assert.isEqual(true, false) does not throw Error");
 | 
			
		||||
    }, term);
 | 
			
		||||
  //_equals testing
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(null, 0))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(null, 0)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(null, undefined))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(null, undefined)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(false, true))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(false, true)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(false, 0))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(false, 0)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals(true, true))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals(true, true)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(true, 1))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(true, 1)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(0, '0'))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(0, '0')), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(0, 1))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(0, 1)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals(1, 1))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals(1, 1)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(1, '1'))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(1, '1')), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals(Math.PI, Math.PI))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals(Math.PI, Math.PI)), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals("Hello", "Hello"))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals("Hello", "Hello")), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals("Hello", new String("Hello")))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals("Hello", new String("Hello"))), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals("Hello", "hello"))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals("Hello", "hello")), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals(["Hello", 1], ["Hello", 1]))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals(["Hello", 1], ["Hello", 1])), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals(["Hello", 1], [1, "Hello"]))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals(["Hello", 1], [1, "Hello"])), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals({}, {}))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals({}, {})), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals({ a: "Hello", b: 1 }, { a: "Hello", b: 1 }))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals({ a: "Hello", b: 1 }, { a: "Hello", b: 1 })), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isTrue(Asserts._equals({ a: "Hello", b: 1 }, { b: 1, a: "Hello" }))`,
 | 
			
		||||
    () => Asserts.isTrue(Asserts._equals({ a: "Hello", b: 1 }, { b: 1, a: "Hello" })), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals({ a: "Hello", b: 1 }, { b: 1, a: "Hello", c: undefined }))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals({ a: "Hello", b: 1 }, { b: 1, a: "Hello", c: undefined })), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isFalse(Asserts._equals({ a: "Hello", b: 1 }, { b: 1, a: "Hello", c: null }))`,
 | 
			
		||||
    () => Asserts.isFalse(Asserts._equals({ a: "Hello", b: 1 }, { b: 1, a: "Hello", c: null })), term);
 | 
			
		||||
  term.printLn("Asserts OK");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								src/test/js/test-splitToArguments.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/test/js/test-splitToArguments.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
  const term = getWTerminal();
 | 
			
		||||
  term.printLn("Testing WTerminal.splitToArguments");
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(WTerminal.splitToArguments("hello world"), ["hello", "world"]);`,
 | 
			
		||||
    () => Asserts.isEqual(WTerminal.splitToArguments("hello world"), ["hello", "world"]), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(WTerminal.splitToArguments("hello 1"), ["hello", "1"])`,
 | 
			
		||||
    () => Asserts.isEqual(WTerminal.splitToArguments("hello 1"), ["hello", "1"]), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(WTerminal.splitToArguments('"hello world" 1'), ["hello world", "1"])`,
 | 
			
		||||
    () => Asserts.isEqual(WTerminal.splitToArguments('"hello world" 1'), ["hello world", "1"]), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(WTerminal.splitToArguments("'hello world' 1"), ["hello world", "1"])`,
 | 
			
		||||
    () => Asserts.isEqual(WTerminal.splitToArguments("'hello world' 1"), ["hello world", "1"]), term);
 | 
			
		||||
  // Asserts.runTest('This test should fail', ()=>{throw new Error("To fail test")}, term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(WTerminal.splitToArguments("\`hello world\` 1"), ["hello world", "1"])`,
 | 
			
		||||
    () => Asserts.isEqual(WTerminal.splitToArguments("`hello world` 1"), ["hello world", "1"]), term);
 | 
			
		||||
  Asserts.runTest(`Asserts.isEqual(WTerminal.splitToArguments("-rf /css/test.css myKitty.js 'my name with spaces'"),
 | 
			
		||||
    ["-rf", "/css/test.css", "myKitty.js", "my name with spaces"])`,
 | 
			
		||||
    () => Asserts.isEqual(WTerminal.splitToArguments("-rf /css/test.css myKitty.js 'my name with spaces'"),
 | 
			
		||||
      ["-rf", "/css/test.css", "myKitty.js", "my name with spaces"]), term);
 | 
			
		||||
  term.printLn("WTerminal.splitToArguments OK");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								src/test/splitToArguments.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/test/splitToArguments.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>Test WTerminal.splitToArguements</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <link rel="stylesheet" href="../css/wterminal.css" />
 | 
			
		||||
 | 
			
		||||
  <script src="../js/wterminal.js"></script>
 | 
			
		||||
  <script src="../js/wterminal-autoextend.js"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="../js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="/test/">WTerminal testing home</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>Test WTerminal.splitToArguements:</h1>
 | 
			
		||||
    <div id="static-terminal"></div>
 | 
			
		||||
    <script>
 | 
			
		||||
      let term = new WTerminal("static", "static-terminal", null);
 | 
			
		||||
      term.terminalCommand("height 40em");
 | 
			
		||||
      term.clearOutput();
 | 
			
		||||
    </script>
 | 
			
		||||
    <script src="js/asserts.js"></script>
 | 
			
		||||
    <script src="js/test-splitToArguments.js"></script>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										39
									
								
								src/test/test-all.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/test/test-all.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <title>Test all</title>
 | 
			
		||||
  <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
  <link rel="stylesheet" href="../css/wterminal.css" />
 | 
			
		||||
 | 
			
		||||
  <script src="../js/wterminal.js"></script>
 | 
			
		||||
  <script src="../js/wterminal-autoextend.js"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="../js/theme.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <header>
 | 
			
		||||
    <button style="float: right;" title="Dark theme on/off" onclick="toggleTheme();">☀</button>
 | 
			
		||||
    <a href="/test/">WTerminal testing home</a>
 | 
			
		||||
  </header>
 | 
			
		||||
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>Test all:</h1>
 | 
			
		||||
    <div id="static-terminal"></div>
 | 
			
		||||
    <script>
 | 
			
		||||
      let term = new WTerminal("static", "static-terminal", null);
 | 
			
		||||
      term.terminalCommand("height 40em");
 | 
			
		||||
      term.clearOutput();
 | 
			
		||||
    </script>
 | 
			
		||||
    <script src="js/asserts.js"></script>
 | 
			
		||||
    <script src="js/test-asserts.js"></script>
 | 
			
		||||
    <script src="js/test-splitToArguments.js"></script>
 | 
			
		||||
  </main>
 | 
			
		||||
 | 
			
		||||
  <footer>
 | 
			
		||||
    <p class="float-right">Author: Ward Truyen</p>
 | 
			
		||||
  </footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user