Compare commits
130 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0407a23747 | |||
| cbc9daa8cd | |||
| 92590d6ecc | |||
| e486111105 | |||
| 11674a1509 | |||
| 06ea1c56c8 | |||
|
|
6b2b9834ac | ||
| 468cee87af | |||
| 8ac69c4aed | |||
| f2d0c36f09 | |||
| a38fe0a16d | |||
| a74e1dd60d | |||
| 628357019c | |||
| 2cf3cb6808 | |||
| 310d7304a4 | |||
| 6f8dfc7bc3 | |||
| c17c2e4808 | |||
| 277bc79e78 | |||
| d2698c5e8e | |||
| 95c91c72d8 | |||
| d424328c9a | |||
| aca83f7235 | |||
| bd9de85ffc | |||
| ab5efe4a33 | |||
| 9a9994a105 | |||
| e72d296726 | |||
| 139f12031f | |||
| 05a2858ef7 | |||
| 14bdd5fff3 | |||
| b48f9f47cc | |||
| 5a35281c33 | |||
| 5a3de2604d | |||
| f9ca00efb8 | |||
| 4cc11e282a | |||
| 2565aa3a70 | |||
| 0ab3eadcf0 | |||
| ebd1895271 | |||
| afc2aa5373 | |||
| 5d791ff0f4 | |||
| 4337681504 | |||
| 1db899d837 | |||
| 5709e557a8 | |||
| 819240c1b1 | |||
| b7bdbd74bc | |||
| 3662b84d8c | |||
| ec1da5d108 | |||
| 653cecd599 | |||
| f8bc04d057 | |||
| 9bdac406ca | |||
| 9886f03082 | |||
| 2000557ef5 | |||
| 5a3c4ecc13 | |||
| 770c70f250 | |||
| 6eb4feb04d | |||
| 288ea3e5ec | |||
| c8478ae010 | |||
| 59e2282ce7 | |||
| 15d2d54f0d | |||
| 89807ef7e5 | |||
| 5a01767628 | |||
| df59d14947 | |||
| de69069222 | |||
| 16ebd1785d | |||
| 1a6053e7e8 | |||
| 58b100c0b2 | |||
| e894052988 | |||
| d598c74dbc | |||
| ff8e61ff8a | |||
| 5576340c4a | |||
| f0c80645db | |||
| 481c2e7516 | |||
| 445d5f138c | |||
| 06660eb19b | |||
| 83c1cd510d | |||
| f9f2454e0c | |||
| c15c5a591c | |||
| 940272cccc | |||
| ca2793b81c | |||
| 59e84ea962 | |||
| 353c8a0a74 | |||
| a413dc047e | |||
| 7b28c0ef1b | |||
| 5d6e9f4615 | |||
| 435ac2fc51 | |||
| 20e0854c5a | |||
| abe4fc33b1 | |||
| d6bb3eabfa | |||
| 368daefbe6 | |||
| 5139be3965 | |||
| 47f319b29b | |||
| b6283b75ae | |||
| 8584b0f784 | |||
| e3903e3beb | |||
| 2991f0b73e | |||
| 5b1b6df448 | |||
| 33c2a6cf92 | |||
| 946d091385 | |||
| 4a395a2d06 | |||
| d3f9c4df56 | |||
| 6548accd48 | |||
| b352c95b57 | |||
| 1ef3cf5c3a | |||
| fc2e42c714 | |||
| 5bf33dedcd | |||
| 80c5301e29 | |||
| fa3422723c | |||
| 330fe0eff2 | |||
| 6cf4bd0d31 | |||
| ea70f8f775 | |||
| b5d4f6c4bc | |||
| bee2fe0968 | |||
| 8a9b58bb5e | |||
| fece3b8032 | |||
| bd57a09923 | |||
| 4cf80a6164 | |||
| 8b78dfe9ed | |||
| deeb3176e3 | |||
| ed15da5f71 | |||
| af0d710f2d | |||
| 09611c8569 | |||
| b49835ffd6 | |||
| 5a116394d3 | |||
| 39e0a1356f | |||
| 5f3622e2bb | |||
| 3cca7f2d69 | |||
| 851a589471 | |||
| 3989ca1bbf | |||
| 0a85da40ef | |||
| 12f84e4cf7 | |||
| 19b326c524 |
44 changed files with 13423 additions and 106929 deletions
2
.env
2
.env
|
|
@ -21,5 +21,5 @@ which nix-shell && test -z "$NIX_SHELL_XRSH" && {
|
|||
|
||||
test "$GITEA_ROOT_URL" = "https://forgejo.isvery.ninja/" && {
|
||||
# on the website xrsh.isvery.ninja
|
||||
echo hello deployment
|
||||
echo hello website deployment
|
||||
}
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,5 +2,6 @@ xrsh-media
|
|||
XRSH milestones.odt
|
||||
aframe/CHANGELOG.md aframe/codecov.yml aframe/CODE_OF_CONDUCT.md aframe/CONTRIBUTING.md aframe/dist aframe/docs aframe/examples aframe/index.html aframe/LICENSE aframe/ORGANIZATION.md aframe/package.json aframe/README.md aframe/ROADMAP.md aframe/scripts aframe/src aframe/tests aframe/vendor aframe/webpack.config.js aframe/webpack.prod.config.js
|
||||
result
|
||||
src/aframe
|
||||
tags
|
||||
|
||||
|
|
|
|||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -1,5 +1,5 @@
|
|||
[submodule "src/xrsh-com"]
|
||||
path = src/xrsh-com
|
||||
url = https://forgejo.isvery.ninja/xrsh/xrsh-com.git
|
||||
url = ./../xrsh-com
|
||||
#url = ssh://git@forgejo.isvery.ninja:8222/xrsh/xrsh-com.git
|
||||
|
||||
|
|
|
|||
19
Dockerfile
Normal file
19
Dockerfile
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
FROM alpine:latest as build
|
||||
|
||||
RUN apk add --update zip bash file curl
|
||||
|
||||
ADD xrsh.com /
|
||||
|
||||
RUN curl -o assimilate https://cosmo.zip/pub/cosmos/bin/assimilate && \
|
||||
chmod +x assimilate && \
|
||||
./assimilate /xrsh.com && \
|
||||
file /xrsh.com
|
||||
|
||||
|
||||
# normalize the binary to ELF
|
||||
#RUN sh /xrsh.com --assimilate && file /xrsh.com
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=build /xrsh.com /
|
||||
CMD ["/xrsh.com"]
|
||||
1
LICENSE
1
LICENSE
|
|
@ -672,3 +672,4 @@ may consider it more useful to permit linking proprietary applications with
|
|||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
||||
|
|
|
|||
208
README.md
208
README.md
|
|
@ -18,17 +18,19 @@ See [the wiki here](https://forgejo.isvery.ninja/xrsh/xrsh/wiki/Home#milestones)
|
|||
|
||||
> NOTE: installation is optional: just surf to the public version [here](https://xrsh.isvery.ninja)
|
||||
|
||||
<details>
|
||||
<summary>install using nix</summary>
|
||||
For local use: download the crossplatform <a href="/xrsh.com" target="_blank">xrsh.com</a> executable [<a href="/xrsh.com.txt" target="_blank">checksum</a>]:<br>
|
||||
|
||||
[NIX](https://nixos.org/) is a convenient way to install or develop xrsh:
|
||||
1. [linux/mac only] run `chmod +x xrsh.com` in the console
|
||||
2. run `./xrsh.com` in the console
|
||||
3. xrsh opens in your browser at `https://127.0.0.1:8080`
|
||||
4. profit!
|
||||
|
||||
1. run `nix-run -p xrsh --run "xrsh.com"` (pass `-p XXXX` to specify non-default 8080 port )
|
||||
2. build it when package does not exist: `nix-build -E "with import <nixpkgs> { }; callPackage ./xrsh.nix"`
|
||||
</details>
|
||||
> pass `-p XXXX` to specify port (default:8080)
|
||||
|
||||
### Installation guides
|
||||
|
||||
<details>
|
||||
<summary>install without nix</summary>
|
||||
<summary>run standalone binary</summary>
|
||||
|
||||
1. Download [xrsh.com](https://forgejo.isvery.ninja/xrsh/xrsh/raw/branch/main/xrsh.com)
|
||||
2. optional: run `unzip xrsh.com` to verify repository contents
|
||||
|
|
@ -37,6 +39,124 @@ See [the wiki here](https://forgejo.isvery.ninja/xrsh/xrsh/wiki/Home#milestones)
|
|||
5. Profit! ✔
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>install using nixos</summary>
|
||||
|
||||
[NIX](https://nixos.org/) is a convenient way to install or develop xrsh:
|
||||
|
||||
1. `nix-shell -p xrsh thttpd`
|
||||
2. run it (`thttpd -p 8080 -d /nix/store/5q4vd50gmh52jh48z62ln1j05xzfh1fz-xrsh-0.142` e.g.)
|
||||
3. point your browser to `localhost:8080`
|
||||
4. profit!
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>run OCI container [podman/docker]</summary>
|
||||
|
||||
1. `$(which podman || which docker) run -p 8080:8080 docker.io/coderofsalvation/xrsh`
|
||||
2. point your browser to `localhost:8080`
|
||||
3. profit!
|
||||
|
||||
> NOTE 1: to add files use the `-D <dir>` overlay webroot parameter.
|
||||
|
||||
> NOTE 2: to enable SSL and add (iso)file try something like this:
|
||||
|
||||
```
|
||||
$ mkdir data
|
||||
$ cp ../xrsh.iso data/. # copy custom iso
|
||||
$ $(which podman || which docker) run -p 8080:8080 -v data/cert:etc/cert -v data:/data docker.io/coderofsalvation/xrsh /xrsh.com -D /data -c 0 -C /etc/cert/cert.pem -K /etc/cert/key.pem
|
||||
```
|
||||
|
||||
> or as an exercise in constructive laziness setup a reverse proxy like [zoraxy](https://github.com/tobychui/zoraxy), [go-proxy](https://github.com/yusing/go-proxy), [droxy], caddy or nginx-reverse-proxymanager.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>run from codeberg.org</summary>
|
||||
|
||||
(codeberg.org is a nonprofit-backed forgejo instance)
|
||||
|
||||
1. create a repository on codeberg.org
|
||||
2. `git push` the [xrsh repository](https://forgejo.isvery.ninja/xrsh/xrsh) to it
|
||||
1. create a `pages` branchclone
|
||||
2. push it to the codeberg repository
|
||||
3. profit! it is now live
|
||||
|
||||
> more info: https://docs.codeberg.org/codeberg-pages/
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>run from selfhosted forgejo/gitea instance</summary>
|
||||
|
||||
1. clone the xrsh [xrsh repository](https://forgejo.isvery.ninja/xrsh/xrsh) locally
|
||||
2. create a repo on your [forgejo](https://forgejo.org) instance
|
||||
3. `git push` the xrsh to it
|
||||
4. in your forgejo (docker/nix)-instance symlink it to the public folder (*)
|
||||
5. point your browser to `https://yourforgejo.org/assets/xrsh`
|
||||
|
||||
> \* = for example: `ln -f git/repositories/yourusername/xrsh gitea/public/assets/.`
|
||||
|
||||
> optionally customize the [xrsh yunohost package](https://forgejo.isvery.ninja/xrsh/xrsh_ynh) with your own ISO
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>install in yunohost</summary>
|
||||
|
||||
1. search for xrsh in the [yunohost](https://yunohost.org) application catalog
|
||||
2. click install
|
||||
3. profit!
|
||||
|
||||
> optionally customize the [xrsh yunohost package](https://forgejo.isvery.ninja/xrsh/xrsh_ynh) with your own ISO
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>install with systemd</summary>
|
||||
|
||||
1. Create a new systemd service file (`sudo nano /etc/systemd/system/xrsh.service` e.g.)
|
||||
2. Specify the `ExecStart` directive to run the xrsh (`[Service]\ExecStart=/path/to/xrsh.com -p 8080` e.g.).
|
||||
3. Enable the service (`sudo systemctl enable xrsh.service` e.g.)
|
||||
4. Start the service (`sudo systemctl start xrsh.service`).
|
||||
4. Verify the service: `sudo systemctl status xrsh.service` or `netstat -tuln`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>run from github</summary>
|
||||
Sigh..good old github times (RIP)..<br>
|
||||
It used to be a simple webinterface around git in 2008.<br>
|
||||
These days running a forgejo/gitea instance + CI is literally one cmd away (or hosted by codeberg.org.<br>
|
||||
|
||||
</details>
|
||||
|
||||
## Developers
|
||||
|
||||
Make sure to clone the repo including submodules (the [xrsh-com](https://forgejo.isvery.ninja/xrsh/xrsh-com) repo)
|
||||
|
||||
```
|
||||
$ git clone --recurse-submodules https://forgejo.isvery.ninja/xrsh/xrsh
|
||||
$ cd xrsh
|
||||
$ nix-shell # optional but adviced (to get up and running instantly)
|
||||
```
|
||||
|
||||
> Now serve the repo from a HTTPS webserver (for example run `./make dev`)
|
||||
|
||||
Eventhough a custom ISO-image can be **built**, XRSH is **buildless** software.<br>
|
||||
The crossplatform binary is just a zip-file with the source (using https://redbean.dev):
|
||||
|
||||
<details>
|
||||
<summary>build using shellscript</summary>
|
||||
|
||||
1. Run `./make standalone` to package everything into `xrsh.com`
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>build using nix</summary>
|
||||
|
||||
1. `nix-build -E "with import <nixpkgs> { }; callPackage ./nix/xrsh-package.nix"`
|
||||
2. optionally see the other nix-files in `nix`-folder
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>launch different .iso / modify files</summary>
|
||||
|
||||
|
|
@ -50,27 +170,65 @@ You can specify a different `.iso` file in various ways:
|
|||
|
||||
</details>
|
||||
|
||||
The browser auto-launches `https://localhost:8080` on most platforms
|
||||
|
||||
> pass `-p XXXX` to specify port (default:8080)
|
||||
|
||||
## Developers
|
||||
|
||||
Make sure to clone the repo including submodules (the [xrsh-com](https://forgejo.isvery.ninja/xrsh/xrsh-com) repo)
|
||||
|
||||
```
|
||||
$ git clone --recurse-submodules https://forgejo.isvery.ninja/xrsh/xrsh
|
||||
$ cd xrsh
|
||||
$ nix-shell # optional but adviced (to get up and running instantly)
|
||||
```
|
||||
|
||||
> Now serve the repo from a HTTPS webserver (for example run `./make dev`)
|
||||
|
||||
Run `./make standalone` to package everything into `xrsh.com`
|
||||
|
||||
* development of components (`src/com`) takes places [in this git submodule](https://forgejo.isvery.ninja/xrsh/xrsh-com)
|
||||
* development of `xrsh.iso` takes places [in this gitsubmodule](https://forgejo.isvery.ninja/xrsh/xrsh-buildroot)
|
||||
|
||||
> IMPORTANT: existing AFRAME apps can embed a barebones XR terminal / REPL like this:
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
|
||||
<script src="https://xrsh.isvery.ninja/xrsh.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a-scene>
|
||||
<a-entity isoterminal position="0 1.6 -0.3"></a-entity>
|
||||
</a-scene>
|
||||
<script>
|
||||
document.querySelector('a-scene').addEventListener('isoterminal_init', function(e){
|
||||
|
||||
// (OPTIONAL) override/extend bootmenu-array with your own REPL(s)
|
||||
// see com/isoterminal/feat/boot.REPL.*.js for examples
|
||||
ISOTerminal.prototype.boot.menu.push({
|
||||
key: "f",
|
||||
title: (opts) => `other awesome NLnet FOSS projects ❤️`,
|
||||
init: function( mainmenu ){
|
||||
window.open('https://nlnet.nl/project/current.html','_blank')
|
||||
// return to main menu
|
||||
mainmenu()
|
||||
},
|
||||
keyHandler: function(ch){
|
||||
this.send("\n\ryou typed:"+ch) // write to term
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
// AFRAME exposes THREE too
|
||||
console.log(THREE)
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
> this portable version runs without the ISO (which requires wasm-files, longer loadingtimes e.g.)
|
||||
|
||||
```
|
||||
|
||||
## Building your own ISO
|
||||
|
||||
As described in the [website documentation](https://xrsh.isvery.ninja/#Booting%20an%20ISO%20image) you could boot your own ISO distribution (TIP: a [filesystem overlay](https://xrsh.isvery.ninja/#Filesystem%20overlay) is easier):
|
||||
|
||||
```
|
||||
$ git clone --recurse-submodules ssh://git@forgejo.isvery.ninja:8222/xrsh/xrsh.git
|
||||
$ git clone ssh://git@forgejo.isvery.ninja:8222/xrsh/xrsh-buildroot
|
||||
$ cd xrsh
|
||||
$ rm xrsh.iso && ln -fs ../xrsh-buildroot/dist/v86-linux.iso xrsh.iso
|
||||
$ ./make dev
|
||||
```
|
||||
|
||||
You can read the [repo-README](https://forgejo.isvery.ninja/xrsh/xrsh-buildroot) about (re)building/modifying the iso
|
||||
|
||||
## Funding
|
||||
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
{ lib
|
||||
, stdenv
|
||||
, fetchFromGitHub
|
||||
, bintools-unwrapped
|
||||
, callPackage
|
||||
, coreutils
|
||||
, substituteAll
|
||||
, unzip
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "cosmopolitan";
|
||||
version = "2.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jart";
|
||||
repo = "cosmopolitan";
|
||||
rev = finalAttrs.version;
|
||||
hash = "sha256-DTL1dXH+LhaxWpiCrsNjV74Bw5+kPbhEAA2Z1NKiPDk=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# make sure tests set PATH correctly
|
||||
(substituteAll {
|
||||
src = ./fix-paths.patch;
|
||||
inherit coreutils;
|
||||
})
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
bintools-unwrapped
|
||||
unzip
|
||||
];
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
outputs = [ "out" "dist" ];
|
||||
|
||||
# slashes are significant because upstream uses o/$(MODE)/foo.o
|
||||
buildFlags = [
|
||||
"o/cosmopolitan.h"
|
||||
"o//cosmopolitan.a"
|
||||
"o//libc/crt/crt.o"
|
||||
"o//ape/ape.o"
|
||||
"o//ape/ape.lds"
|
||||
"o//tool/net/redbean.com"
|
||||
];
|
||||
|
||||
checkTarget = "o//test";
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
doCheck = false;
|
||||
dontConfigure = true;
|
||||
dontFixup = true;
|
||||
|
||||
preCheck = let
|
||||
failingTests = [
|
||||
# some syscall tests fail because we're in a sandbox
|
||||
"test/libc/calls/sched_setscheduler_test.c"
|
||||
"test/libc/thread/pthread_create_test.c"
|
||||
"test/libc/calls/getgroups_test.c"
|
||||
# fails
|
||||
"test/libc/stdio/posix_spawn_test.c"
|
||||
];
|
||||
in lib.concatStringsSep ";\n" (map (t: "rm -v ${t}") failingTests);
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/{include,lib,bin}
|
||||
install o/cosmopolitan.h $out/include
|
||||
install o/cosmopolitan.a o/libc/crt/crt.o o/ape/ape.{o,lds} o/ape/ape-no-modify-self.o $out/lib
|
||||
install o/tool/net/redbean.com $out/bin/xrsh.com
|
||||
cp -RT . "$dist"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
cosmocc = callPackage ./cosmocc.nix {
|
||||
cosmopolitan = finalAttrs.finalPackage;
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
homepage = "https://xrsh.isvery.ninja/";
|
||||
description = "XR shell runs a linux ISO in WebXR";
|
||||
license = lib.licenses.isc;
|
||||
maintainers = lib.teams.cosmopolitan.members;
|
||||
platforms = lib.platforms.x86_64;
|
||||
};
|
||||
})
|
||||
210
index.html
210
index.html
File diff suppressed because one or more lines are too long
77
make
77
make
|
|
@ -15,25 +15,76 @@ deps(){ # check dependencies
|
|||
}
|
||||
|
||||
standalone(){ # build standalone xrsh.com binary
|
||||
FILE=${APP}.com
|
||||
test -z "$1" && {
|
||||
rm ${APP}.com || true
|
||||
deps
|
||||
|
||||
exec(){
|
||||
FILE=${APP}.com
|
||||
test -z "$1" && {
|
||||
rm ${APP}.com || true
|
||||
deps
|
||||
}
|
||||
test -n "$1" && FILE="$1"
|
||||
#cp index.html /tmp/index.html
|
||||
#sed -i 's|isoterminal=".*"|isoterminal="iso: ./../xrsh.iso"|g' index.html
|
||||
zip -x "*.git*" -r "$FILE" index.html xrsh.iso .args LICENSE src/index.{html,css} src/assets src/com/*.js src/com/lib src/com/isoterminal/{libv86.js,bios,v86.wasm,feat,PromiseWorker.js,ISOTerminal.js,localforage.js,term.js,assets,worker.js}
|
||||
#cp /tmp/index.html index.html
|
||||
sha256sum "$FILE" > "$FILE".txt
|
||||
ls -lah "$FILE"
|
||||
}
|
||||
test -n "$1" && FILE="$1"
|
||||
#cp index.html /tmp/index.html
|
||||
#sed -i 's|isoterminal=".*"|isoterminal="iso: ./../xrsh.iso"|g' index.html
|
||||
zip -x "*.git*" -r "$FILE" index.html xrsh.iso .args LICENSE src/index.{html,css} src/assets src/com/*.js src/com/lib src/com/isoterminal/{libv86.js,bios,v86.wasm,feat,PromiseWorker.js,ISOTerminal.js,localforage.js,term.js,assets,worker.js}
|
||||
#cp /tmp/index.html index.html
|
||||
sha256sum "$FILE" > "$FILE".txt
|
||||
ls -lah "$FILE"
|
||||
|
||||
jslib(){
|
||||
{
|
||||
echo ""
|
||||
echo "/* xrsh.js AFRAME component "
|
||||
echo " * https://xrsh.isvery.ninja "
|
||||
echo " * SPDX: AGPL-3.0-or-later "
|
||||
echo " */"
|
||||
echo "document.head.innerHTML += \`<style type='text/css'>"
|
||||
cat src/index.css
|
||||
echo -e "</style>\`;\n"
|
||||
cat src/assets/winbox* src/com/{isoterminal,data2event,dom,html-as-texture-in-xr,pastedrop,require,window}.js src/com/lib/*.js src/com/isoterminal/{ISOTerminal.js,term.js,feat/boot.js,feat/jsconsole.js,feat/term.js,feat/remotekeyboard.js}
|
||||
echo "// mark above libs as pre-required in require.js, to prevent 'component already registered' errors "
|
||||
echo "AFRAME.utils.require.required = {";
|
||||
echo " window: true,"
|
||||
echo " winboxjs: true,"
|
||||
echo " com: true,"
|
||||
echo " dom: true,"
|
||||
echo " xhook: true,"
|
||||
echo " pastedrop: true,"
|
||||
echo " selfcontain: true,"
|
||||
echo " v86: true,"
|
||||
echo " htmlinxr: true,"
|
||||
echo " html: true,"
|
||||
echo " PromiseWorker: true,"
|
||||
echo " ISOTerminal: true,"
|
||||
echo " localforage: true,"
|
||||
echo " boot: true,"
|
||||
echo " javascript: true,"
|
||||
echo " jsconsole: true,"
|
||||
echo " indexhtml: true,"
|
||||
echo " indexjs: true,"
|
||||
echo " autorestore: true,"
|
||||
echo " pastedropFeat: true,"
|
||||
echo " httpfs: true,"
|
||||
echo " fbterm: true,"
|
||||
echo " fbtermjs: true,"
|
||||
echo " remotekeyboard: true"
|
||||
echo " remotestorage: true"
|
||||
echo " };"
|
||||
} > xrsh.js
|
||||
ls -lh xrsh.js
|
||||
}
|
||||
|
||||
test -z "$1" && { jslib; exec; }
|
||||
test -n "$1" && "$@"
|
||||
}
|
||||
|
||||
dev(){ # start dev http server
|
||||
set -x
|
||||
cd "$DIR"
|
||||
test -f xrsh.com || standalone
|
||||
wget "$REDBEAN_VERSION" -O /tmp/server.com
|
||||
chmod +x /tmp/server.com
|
||||
test -f /tmp/cert.pem || openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout /tmp/key.pem -out /tmp/cert.pem
|
||||
./xrsh.com -c 0 -C /tmp/cert.pem -K /tmp/key.pem -D . "$@"
|
||||
/tmp/server.com -c 0 -C /tmp/cert.pem -K /tmp/key.pem -D . "$@"
|
||||
}
|
||||
|
||||
shell(){ # run xrsh shell via docker
|
||||
|
|
|
|||
29
nix/xrsh-package.nix
Normal file
29
nix/xrsh-package.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{ stdenv, fetchgit, lib }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "xrsh";
|
||||
version = "0.142";
|
||||
|
||||
src = fetchgit {
|
||||
fetchSubmodules = true;
|
||||
url = "https://codeberg.org/xrsh/xrsh.git";
|
||||
rev = "12f84e4cf72bf1e1268a6a4120594a825a8f66a7";
|
||||
sha256 = "sha256-0MBBlqL2TWgN94ErI2Joub0Aub5XBxGWXILPDAfiNpc=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
cp -r $src/{index.html,src,xrsh.ico,xrsh.svg} $out/.
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "XR shell which runs a linux ISO in WebXR";
|
||||
license = "GPL3";
|
||||
homepage = "https://xrsh.isvery.ninja";
|
||||
maintainers = with maintainers; [ coderofsalvation ];
|
||||
platforms = [ "i686-linux" "x86_64-linux" "x86_64-windows" "i686-windows" "x86_64-darwin" ];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
{ stdenv, fetchurl }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "xrsh";
|
||||
version = "0.1";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://codeberg.org/xrsh/xrsh/archive/24e117f5125e4b2ecd7432baf6fdd5f60e6b3a70.tar.gz";
|
||||
sha256 = "11v22pijnjm3mb3n8dki4m95rc73azschfwvh2c1pc3bxrfsk0k8";
|
||||
};
|
||||
|
||||
#cosmopolitan = pkgs.callPackage pkgs.cosmopolitan { };
|
||||
|
||||
## Override derivation to modify buildFlags
|
||||
#redbean = cosmopolitan.overrideDerivation (oldAttrs: {
|
||||
# buildFlags = oldAttrs.buildFlags ++ ["--enable-feature-x"];
|
||||
#});
|
||||
|
||||
buildInputs = [];
|
||||
|
||||
buildFlags = [];
|
||||
|
||||
# Define phases if needed, e.g., build, install, etc.
|
||||
# phases = [ "buildPhase" "installPhase" ];
|
||||
}
|
||||
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
../../../aframe
|
||||
416
src/assets/aframe-remotestorage.min.js
vendored
Normal file
416
src/assets/aframe-remotestorage.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
46403
src/assets/aframe.min.js
vendored
46403
src/assets/aframe.min.js
vendored
File diff suppressed because one or more lines are too long
34
src/assets/winbox.bundle.min.js
vendored
Normal file
34
src/assets/winbox.bundle.min.js
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* WinBox.js v0.2.82 (Bundle)
|
||||
* Author and Copyright: Thomas Wilkerling
|
||||
* Licence: Apache-2.0
|
||||
* Hosted by Nextapps GmbH
|
||||
* https://github.com/nextapps-de/winbox
|
||||
*/
|
||||
(function(){'use strict';var e,aa=document.createElement("style");aa.innerHTML="@keyframes wb-fade-in{0%{opacity:0}to{opacity:.85}}.winbox{position:fixed;left:0;top:0;background:#0050ff;box-shadow:0 14px 28px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.22);transition:width .3s,height .3s,left .3s,top .3s;transition-timing-function:cubic-bezier(.3,1,.3,1);contain:layout size;text-align:left;touch-action:none}.wb-body,.wb-header{position:absolute;left:0}.wb-header{top:0;width:100%;height:35px;line-height:35px;color:#fff;overflow:hidden;z-index:1}.wb-body{top:35px;right:0;bottom:0;overflow:auto;-webkit-overflow-scrolling:touch;overflow-scrolling:touch;will-change:contents;background:#fff;margin-top:0!important;contain:strict;z-index:0}.wb-control *,.wb-icon{background-repeat:no-repeat}.wb-drag{height:100%;padding-left:10px;cursor:move}.wb-title{font-family:Arial,sans-serif;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wb-icon{display:none;width:20px;height:100%;margin:-1px 8px 0-3px;float:left;background-size:100%;background-position:center}.wb-e,.wb-w{width:10px;top:0}.wb-n,.wb-s{left:0;height:10px;position:absolute}.wb-n{top:-5px;right:0;cursor:n-resize;z-index:2}.wb-e{position:absolute;right:-5px;bottom:0;cursor:w-resize;z-index:2}.wb-s{bottom:-5px;right:0;cursor:n-resize;z-index:2}.wb-nw,.wb-sw,.wb-w{left:-5px}.wb-w{position:absolute;bottom:0;cursor:w-resize;z-index:2}.wb-ne,.wb-nw,.wb-sw{width:15px;height:15px;z-index:2;position:absolute}.wb-nw{top:-5px;cursor:nw-resize}.wb-ne,.wb-sw{cursor:ne-resize}.wb-ne{top:-5px;right:-5px}.wb-se,.wb-sw{bottom:-5px}.wb-se{position:absolute;right:-5px;width:15px;height:15px;cursor:nw-resize;z-index:2}.wb-control{float:right;height:100%;max-width:100%;text-align:center}.wb-control *{display:inline-block;width:30px;height:100%;max-width:100%;background-position:center;cursor:pointer}.no-close .wb-close,.no-full .wb-full,.no-header .wb-header,.no-max .wb-max,.no-min .wb-min,.no-resize .wb-body~div,.wb-body .wb-hide,.wb-show,.winbox.hide,.winbox.min .wb-body>*,.winbox.min .wb-full,.winbox.min .wb-min,.winbox.modal .wb-full,.winbox.modal .wb-max,.winbox.modal .wb-min{display:none}.winbox.max .wb-drag,.winbox.min .wb-drag{cursor:default}.wb-min{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAyIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNOCAwaDdhMSAxIDAgMCAxIDAgMkgxYTEgMSAwIDAgMSAwLTJoN3oiLz48L3N2Zz4=);background-size:14px auto;background-position:center calc(50% + 6px)}.wb-max{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA5NiA5NiI+PHBhdGggZD0iTTIwIDcxLjMxMUMxNS4zNCA2OS42NyAxMiA2NS4yMyAxMiA2MFYyMGMwLTYuNjMgNS4zNy0xMiAxMi0xMmg0MGM1LjIzIDAgOS42NyAzLjM0IDExLjMxMSA4SDI0Yy0yLjIxIDAtNCAxLjc5LTQgNHY1MS4zMTF6Ii8+PHBhdGggZD0iTTkyIDc2VjM2YzAtNi42My01LjM3LTEyLTEyLTEySDQwYy02LjYzIDAtMTIgNS4zNy0xMiAxMnY0MGMwIDYuNjMgNS4zNyAxMiAxMiAxMmg0MGM2LjYzIDAgMTItNS4zNyAxMi0xMnptLTUyIDRjLTIuMjEgMC00LTEuNzktNC00VjM2YzAtMi4yMSAxLjc5LTQgNC00aDQwYzIuMjEgMCA0IDEuNzkgNCA0djQwYzAgMi4yMS0xLjc5IDQtNCA0SDQweiIvPjwvc3ZnPg==);background-size:17px auto}.wb-close{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xIC0xIDE4IDE4Ij48cGF0aCBmaWxsPSIjZmZmIiBkPSJtMS42MTMuMjEuMDk0LjA4M0w4IDYuNTg1IDE0LjI5My4yOTNsLjA5NC0uMDgzYTEgMSAwIDAgMSAxLjQwMyAxLjQwM2wtLjA4My4wOTRMOS40MTUgOGw2LjI5MiA2LjI5M2ExIDEgMCAwIDEtMS4zMiAxLjQ5N2wtLjA5NC0uMDgzTDggOS40MTVsLTYuMjkzIDYuMjkyLS4wOTQuMDgzQTEgMSAwIDAgMSAuMjEgMTQuMzg3bC4wODMtLjA5NEw2LjU4NSA4IC4yOTMgMS43MDdBMSAxIDAgMCAxIDEuNjEzLjIxeiIvPjwvc3ZnPg==);background-size:15px auto;background-position:5px center}.wb-full{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjIuNSIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNOCAzSDVhMiAyIDAgMCAwLTIgMnYzbTE4IDBWNWEyIDIgMCAwIDAtMi0yaC0zbTAgMThoM2EyIDIgMCAwIDAgMi0ydi0zTTMgMTZ2M2EyIDIgMCAwIDAgMiAyaDMiLz48L3N2Zz4=);background-size:16px auto}.winbox.max .wb-body~div,.winbox.min .wb-body~div,.winbox.modal .wb-body~div,.winbox.modal .wb-drag,body.wb-lock iframe{pointer-events:none}.winbox.max{box-shadow:none}.winbox.max .wb-body{margin:0!important}.winbox iframe{position:absolute;width:100%;height:100%;border:0}body.wb-lock .winbox{will-change:left,top,width,height;transition:none}.winbox.modal:before{content:'';position:absolute;top:0;left:0;right:0;bottom:0;background:inherit;border-radius:inherit}.winbox.modal:after{content:'';position:absolute;top:-50vh;left:-50vw;right:-50vw;bottom:-50vh;background:#0d1117;animation:wb-fade-in .2s ease-out forwards;z-index:-1}.no-animation{transition:none}.no-shadow{box-shadow:none}.no-header .wb-body{top:0}.no-move:not(.min) .wb-title{pointer-events:none}.wb-body .wb-show{display:revert}";
|
||||
var h=document.getElementsByTagName("head")[0];h.firstChild?h.insertBefore(aa,h.firstChild):h.appendChild(aa);var ba=document.createElement("div");ba.innerHTML="<div class=wb-header><div class=wb-control><span class=wb-min></span><span class=wb-max></span><span class=wb-full></span><span class=wb-close></span></div><div class=wb-drag><div class=wb-icon></div><div class=wb-title></div></div></div><div class=wb-body></div><div class=wb-n></div><div class=wb-s></div><div class=wb-w></div><div class=wb-e></div><div class=wb-nw></div><div class=wb-ne></div><div class=wb-se></div><div class=wb-sw></div>";function k(a,b,c,f){a&&a.addEventListener(b,c,f||!1)}function l(a,b){var c=window,f=m;c&&c.removeEventListener(a,b,f||!1)}function t(a,b){a.stopPropagation();b&&a.preventDefault()}function u(a,b,c){c=""+c;a["_s_"+b]!==c&&(a.style.setProperty(b,c),a["_s_"+b]=c)};/*
|
||||
self.max &&*/
|
||||
var x=[],A=[],ca={capture:!0,passive:!1},m={capture:!0,passive:!0},B,da=0,E=10,F,J,ha,K,P,ia;
|
||||
function U(a,b){if(!(this instanceof U))return new U(a);B||ja();if(a){if(b){var c=a;a=b}if("string"===typeof a)c=a;else{var f=a.id;var d=a.index;var n=a.root;var p=a.template;c=c||a.title;var v=a.icon;var L=a.mount;var Q=a.html;var g=a.url;var q=a.width;var r=a.height;var w=a.minwidth;var C=a.minheight;var y=a.maxwidth;var z=a.maxheight;var ea=a.autosize;var D=a.overflow;var G=a.min;var H=a.max;var I=a.hidden;var fa=a.modal;var X=a.x||(fa?"center":0);var Y=a.y||(fa?"center":0);var M=a.top;var N=a.left;
|
||||
var R=a.bottom;var S=a.right;var la=a.background;var O=a.border;var T=a.header;var Z=a["class"];var ma=a.oncreate;var ra=a.onclose;var sa=a.onfocus;var ta=a.onblur;var ua=a.onmove;var va=a.onresize;var wa=a.onfullscreen;var xa=a.onmaximize;var ya=a.onminimize;var za=a.onrestore;var Aa=a.onhide;var Ba=a.onshow;var Ca=a.onload}}this.g=(p||ba).cloneNode(!0);this.g.id=this.id=f||"winbox-"+ ++da;this.g.className="winbox"+(Z?" "+("string"===typeof Z?Z:Z.join(" ")):"")+(fa?" modal":"");this.g.winbox=this;
|
||||
this.window=this.g;this.body=this.g.getElementsByClassName("wb-body")[0];this.h=T||35;A.push(this);la&&this.setBackground(la);O?u(this.body,"margin",O+(isNaN(O)?"":"px")):O=0;T&&(b=this.g.getElementsByClassName("wb-header")[0],u(b,"height",T+"px"),u(b,"line-height",T+"px"),u(this.body,"top",T+"px"));c&&this.setTitle(c);v&&this.setIcon(v);L?this.mount(L):Q?this.body.innerHTML=Q:g&&this.setUrl(g,Ca);M=M?V(M,P):0;R=R?V(R,P):0;N=N?V(N,K):0;S=S?V(S,K):0;c=K-N-S;v=P-M-R;y=y?V(y,c):c;z=z?V(z,v):v;w=w?V(w,
|
||||
y):150;C=C?V(C,z):this.h;ea?((n||B).appendChild(this.body),q=Math.max(Math.min(this.body.clientWidth+2*O+1,y),w),r=Math.max(Math.min(this.body.clientHeight+this.h+O+1,z),C),this.g.appendChild(this.body)):(q=q?V(q,y):Math.max(y/2,w)|0,r=r?V(r,z):Math.max(z/2,C)|0);X=X?V(X,c,q):N;Y=Y?V(Y,v,r):M;this.x=X;this.y=Y;this.width=q;this.height=r;this.s=w;this.o=C;this.m=y;this.l=z;this.top=M;this.right=S;this.bottom=R;this.left=N;this.index=d;this.j=D;this.focused=this.hidden=this.full=this.max=this.min=!1;
|
||||
this.onclose=ra;this.onfocus=sa;this.onblur=ta;this.onmove=ua;this.onresize=va;this.onfullscreen=wa;this.onmaximize=xa;this.onminimize=ya;this.onrestore=za;this.onhide=Aa;this.onshow=Ba;I?this.hide():this.focus();if(d||0===d)this.index=d,u(this.g,"z-index",d),d>E&&(E=d);H?this.maximize():G?this.minimize():this.resize().move();ka(this);(n||B).appendChild(this.g);ma&&ma.call(this,a)}U["new"]=function(a){return new U(a)};U.stack=function(){return A};
|
||||
function V(a,b,c){"string"===typeof a&&("center"===a?a=(b-c)/2+.5|0:"right"===a||"bottom"===a?a=b-c:(c=parseFloat(a),a="%"===(""+c!==a&&a.substring((""+c).length))?b/100*c+.5|0:c));return a}
|
||||
function ja(){B=document.body;B[J="requestFullscreen"]||B[J="msRequestFullscreen"]||B[J="webkitRequestFullscreen"]||B[J="mozRequestFullscreen"]||(J="");ha=J&&J.replace("request","exit").replace("mozRequest","mozCancel").replace("Request","Exit");k(window,"resize",function(){na();oa()});k(B,"mousedown",function(){ia=!1},!0);k(B,"mousedown",function(){if(!ia){var a=A.length;if(a)for(--a;0<=a;a--){var b=A[a];if(b.focused){b.blur();break}}}});na()}
|
||||
function ka(a){W(a,"drag");W(a,"n");W(a,"s");W(a,"w");W(a,"e");W(a,"nw");W(a,"ne");W(a,"se");W(a,"sw");k(a.g.getElementsByClassName("wb-min")[0],"click",function(b){t(b);a.min?a.restore().focus():a.minimize()});k(a.g.getElementsByClassName("wb-max")[0],"click",function(b){t(b);a.max?a.restore().focus():a.maximize().focus()});J?k(a.g.getElementsByClassName("wb-full")[0],"click",function(b){t(b);a.fullscreen().focus()}):a.addClass("no-full");k(a.g.getElementsByClassName("wb-close")[0],"click",function(b){t(b);
|
||||
a.close()||(a=null)});k(a.g,"mousedown",function(){ia=!0},!0);k(a.body,"mousedown",function(){a.focus()},!0)}function pa(a){x.splice(x.indexOf(a),1);oa();a.removeClass("min");a.min=!1;a.g.title=""}function oa(){for(var a=x.length,b={},c={},f=0,d;f<a;f++)d=x[f],d=d.left+":"+d.top,c[d]?c[d]++:(b[d]=0,c[d]=1);f=0;for(var n,p;f<a;f++)d=x[f],n=d.left+":"+d.top,p=Math.min((K-d.left-d.right)/c[n],250),d.resize(p+1|0,d.h,!0).move(d.left+b[n]*p|0,P-d.bottom-d.h,!0),b[n]++}
|
||||
function W(a,b){function c(g){t(g,!0);a.focus();if("drag"===b){if(a.min){a.restore();return}if(!a.g.classList.contains("no-max")){var q=Date.now(),r=q-Q;Q=q;if(300>r){a.max?a.restore():a.maximize();return}}}a.min||(B.classList.add("wb-lock"),(p=g.touches)&&(p=p[0])?(g=p,k(window,"touchmove",f,m),k(window,"touchend",d,m)):(k(window,"mousemove",f,m),k(window,"mouseup",d,m)),v=g.pageX,L=g.pageY)}function f(g){t(g);p&&(g=g.touches[0]);var q=g.pageX;g=g.pageY;var r=q-v,w=g-L,C=a.width,y=a.height,z=a.x,
|
||||
ea=a.y,D;if("drag"===b){if(a.g.classList.contains("no-move"))return;a.x+=r;a.y+=w;var G=D=1}else{if("e"===b||"se"===b||"ne"===b){a.width+=r;var H=1}else if("w"===b||"sw"===b||"nw"===b)a.x+=r,a.width-=r,G=H=1;if("s"===b||"se"===b||"sw"===b){a.height+=w;var I=1}else if("n"===b||"ne"===b||"nw"===b)a.y+=w,a.height-=w,D=I=1}H&&(a.width=Math.max(Math.min(a.width,a.m,K-a.x-a.right),a.s),H=a.width!==C);I&&(a.height=Math.max(Math.min(a.height,a.l,P-a.y-a.bottom),a.o),I=a.height!==y);(H||I)&&a.resize();G&&
|
||||
(a.max&&(a.x=(q<K/3?a.left:q>K/3*2?K-a.width-a.right:K/2-a.width/2)+r),a.x=Math.max(Math.min(a.x,a.j?K-30:K-a.width-a.right),a.j?30-a.width:a.left),G=a.x!==z);D&&(a.max&&(a.y=a.top+w),a.y=Math.max(Math.min(a.y,a.j?P-a.h:P-a.height-a.bottom),a.top),D=a.y!==ea);if(G||D)a.max&&a.restore(),a.move();if(H||G)v=q;if(I||D)L=g}function d(g){t(g);B.classList.remove("wb-lock");p?(l("touchmove",f),l("touchend",d)):(l("mousemove",f),l("mouseup",d))}var n=a.g.getElementsByClassName("wb-"+b)[0];if(n){var p,v,L,
|
||||
Q=0;k(n,"mousedown",c,ca);k(n,"touchstart",c,ca)}}function na(){var a=document.documentElement;K=a.clientWidth;P=a.clientHeight}e=U.prototype;e.mount=function(a){this.unmount();a.i||(a.i=a.parentNode);this.body.textContent="";this.body.appendChild(a);return this};e.unmount=function(a){var b=this.body.firstChild;if(b){var c=a||b.i;c&&c.appendChild(b);b.i=a}return this};
|
||||
e.setTitle=function(a){var b=this.g.getElementsByClassName("wb-title")[0];a=this.title=a;var c=b.firstChild;c?c.nodeValue=a:b.textContent=a;return this};e.setIcon=function(a){var b=this.g.getElementsByClassName("wb-icon")[0];u(b,"background-image","url("+a+")");u(b,"display","inline-block");return this};e.setBackground=function(a){u(this.g,"background",a);return this};
|
||||
e.setUrl=function(a,b){var c=this.body.firstChild;c&&"iframe"===c.tagName.toLowerCase()?c.src=a:(this.body.innerHTML='<iframe src="'+a+'"></iframe>',b&&(this.body.firstChild.onload=b));return this};e.focus=function(a){if(!1===a)return this.blur();if(!this.focused){a=A.length;if(1<a)for(var b=1;b<=a;b++){var c=A[a-b];if(c.focused){c.blur();A.push(A.splice(A.indexOf(this),1)[0]);break}}u(this.g,"z-index",++E);this.index=E;this.addClass("focus");this.focused=!0;this.onfocus&&this.onfocus()}return this};
|
||||
e.blur=function(a){if(!1===a)return this.focus();this.focused&&(this.removeClass("focus"),this.focused=!1,this.onblur&&this.onblur());return this};e.hide=function(a){if(!1===a)return this.show();if(!this.hidden)return this.onhide&&this.onhide(),this.hidden=!0,this.addClass("hide")};e.show=function(a){if(!1===a)return this.hide();if(this.hidden)return this.onshow&&this.onshow(),this.hidden=!1,this.removeClass("hide")};
|
||||
e.minimize=function(a){if(!1===a)return this.restore();F&&qa();this.max&&(this.removeClass("max"),this.max=!1);this.min||(x.push(this),oa(),this.g.title=this.title,this.addClass("min"),this.min=!0,this.focused&&(this.blur(),Da()),this.onminimize&&this.onminimize());return this};function Da(){var a=A.length;if(a)for(--a;0<=a;a--){var b=A[a];if(!b.min){b.focus();break}}}
|
||||
e.restore=function(){F&&qa();this.min&&(pa(this),this.resize().move(),this.onrestore&&this.onrestore());this.max&&(this.max=!1,this.removeClass("max").resize().move(),this.onrestore&&this.onrestore());return this};e.maximize=function(a){if(!1===a)return this.restore();F&&qa();this.min&&pa(this);this.max||(this.addClass("max").resize(K-this.left-this.right,P-this.top-this.bottom,!0).move(this.left,this.top,!0),this.max=!0,this.onmaximize&&this.onmaximize());return this};
|
||||
e.fullscreen=function(a){this.min&&(pa(this),this.resize().move());if(!F||!qa())this.body[J](),F=this,this.full=!0,this.onfullscreen&&this.onfullscreen();else if(!1===a)return this.restore();return this};function qa(){F.full=!1;if(document.fullscreen||document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement)return document[ha](),!0}
|
||||
e.close=function(a){if(this.onclose&&this.onclose(a))return!0;this.min&&pa(this);A.splice(A.indexOf(this),1);this.unmount();this.g.remove();this.g.textContent="";this.g=this.body=this.g.winbox=null;this.focused&&Da()};e.move=function(a,b,c){a||0===a?c||(this.x=a?a=V(a,K-this.left-this.right,this.width):0,this.y=b?b=V(b,P-this.top-this.bottom,this.height):0):(a=this.x,b=this.y);u(this.g,"left",a+"px");u(this.g,"top",b+"px");this.onmove&&this.onmove(a,b);return this};
|
||||
e.resize=function(a,b,c){a||0===a?c||(this.width=a?a=V(a,this.m):0,this.height=b?b=V(b,this.l):0,a=Math.max(a,this.s),b=Math.max(b,this.o)):(a=this.width,b=this.height);u(this.g,"width",a+"px");u(this.g,"height",b+"px");this.onresize&&this.onresize(a,b);return this};
|
||||
e.addControl=function(a){var b=a["class"],c=a.image,f=a.click;a=a.index;var d=document.createElement("span"),n=this.g.getElementsByClassName("wb-control")[0],p=this;b&&(d.className=b);c&&u(d,"background-image","url("+c+")");f&&(d.onclick=function(v){f.call(this,v,p)});n.insertBefore(d,n.childNodes[a||0]);return this};e.removeControl=function(a){(a=this.g.getElementsByClassName(a)[0])&&a.remove();return this};e.addClass=function(a){this.g.classList.add(a);return this};
|
||||
e.removeClass=function(a){this.g.classList.remove(a);return this};e.toggleClass=function(a){return this.g.classList.contains(a)?this.removeClass(a):this.addClass(a)};window.WinBox=U;}).call(this);
|
||||
7696
src/assets/xrfragment.aframe.js
Normal file
7696
src/assets/xrfragment.aframe.js
Normal file
File diff suppressed because one or more lines are too long
51
src/browser-extension/content.js
Normal file
51
src/browser-extension/content.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
function waitForAScene(callback) {
|
||||
|
||||
let scene = document.querySelector("a-scene")
|
||||
if( scene ) return callback(scene)
|
||||
|
||||
// Create a MutationObserver to monitor the DOM for changes
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
// Check if new nodes are added
|
||||
if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
|
||||
for (const node of mutation.addedNodes) {
|
||||
// Check if the added node is <a-scene> or contains one
|
||||
if (node.nodeName === "A-SCENE" || node.querySelector?.("a-scene")) {
|
||||
observer.disconnect(); // Stop observing once found
|
||||
callback(node.nodeName === "A-SCENE" ? node : node.querySelector("a-scene"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Start observing the entire document for child node additions
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true, // Observe direct children changes
|
||||
subtree: true, // Observe all levels of the DOM
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Example usage
|
||||
waitForAScene((aScene) => {
|
||||
|
||||
if( aScene.innerHTML.match(/ isoterminal/) ) return; // prevent duplicates
|
||||
|
||||
// Inject the external script
|
||||
const xrshScript = document.createElement("script");
|
||||
xrshScript.src = chrome.runtime.getURL("xrsh.js");
|
||||
document.head.appendChild(xrshScript);
|
||||
|
||||
// Add the A-Frame entity after the script loads
|
||||
xrshScript.onload = () => {
|
||||
const scene = document.querySelector("a-scene");
|
||||
if (scene) {
|
||||
const entity = document.createElement("a-entity");
|
||||
entity.setAttribute("isoterminal", "");
|
||||
entity.setAttribute("position", "0 1.6 -0.3");
|
||||
scene.appendChild(entity);
|
||||
}
|
||||
};
|
||||
});
|
||||
BIN
src/browser-extension/icon.png
Normal file
BIN
src/browser-extension/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
24
src/browser-extension/manifest.json
Normal file
24
src/browser-extension/manifest.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "XRSH",
|
||||
"version": "1.0",
|
||||
"description": "Injects XRSH Terminal into WebXR [AFRAME] scenes.",
|
||||
"permissions": ["scripting", "activeTab"],
|
||||
"host_permissions": ["<all_urls>"],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["content.js"],
|
||||
"run_at": "document_end"
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": ["xrsh.js"],
|
||||
"matches": ["<all_urls>"]
|
||||
}
|
||||
],
|
||||
"icons": {
|
||||
"128": "icon.png"
|
||||
}
|
||||
}
|
||||
1
src/browser-extension/xrsh.js
Symbolic link
1
src/browser-extension/xrsh.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../xrsh.js
|
||||
BIN
src/engine.glb
BIN
src/engine.glb
Binary file not shown.
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
:root {
|
||||
--xrsh-primary: #3a51ff;
|
||||
--xrsh-primary: #00AA;
|
||||
--xrsh-primary-fg: #FFF;
|
||||
--xrsh-light-primary: #00a3Ff;
|
||||
--xrsh-secondary: #872eff;
|
||||
|
|
@ -17,9 +17,11 @@
|
|||
--xrsh-dark-gray: #343334;
|
||||
--xrsh-gray: #424280;
|
||||
--xrsh-white: #fdfdfd;
|
||||
--xrsh-black: #001c;
|
||||
--xrsh-light-gray: #efefef;
|
||||
--xrsh-lighter-gray: #e4e2fb96;
|
||||
--xrsh-window-radius: 10px;
|
||||
--xrsh-control-radius: 7px;
|
||||
--xrsh-font-sans-serif: system-ui, -apple-system, segoe ui, roboto, ubuntu, helvetica, cantarell, noto sans, sans-serif;
|
||||
--xrsh-font-monospace: menlo, monaco, lucida console, liberation mono, dejavu sans mono, bitstream vera sans mono, courier new, monospace, serif;
|
||||
--xrsh-font-size-0: 12px;
|
||||
|
|
@ -54,7 +56,7 @@ a,a:visited,a:active{
|
|||
*/
|
||||
|
||||
button,.btn,input[type=submit]{
|
||||
border-radius:7px;
|
||||
border-radius: var(--xrsh-control-radius);
|
||||
background: var(--xrsh-primary);
|
||||
color: var(--xrsh-primary-fg);
|
||||
transition:0.3s;
|
||||
|
|
@ -98,31 +100,55 @@ button,input,.btn{
|
|||
*/
|
||||
.winbox {
|
||||
box-shadow:none !important;
|
||||
background:transparent !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.winbox .wb-body{
|
||||
background: var(--xrsh-dark-gray);
|
||||
margin-top: -6px !important;
|
||||
/*margin-top: -6px !important;*/
|
||||
z-index: 100;
|
||||
border: 1px solid #FFF3;
|
||||
border-radius:7px;
|
||||
border-radius:0px 0px var(--xrsh-window-radius) var(--xrsh-window-radius);
|
||||
}
|
||||
.winbox .wb-header{
|
||||
background:transparent !important;
|
||||
background: var(--xrsh-dark-gray);
|
||||
z-index:1000;
|
||||
font-weight: bold;
|
||||
border-radius: var(--xrsh-window-radius) var(--xrsh-window-radius) 0px 0px;
|
||||
line-height:36px;
|
||||
|
||||
}
|
||||
.winbox.max .wb-header{
|
||||
border-radius:0px;
|
||||
}
|
||||
|
||||
.XR .winbox .wb-header{
|
||||
border-radius:0px !important;
|
||||
margin-top:0px;
|
||||
}
|
||||
|
||||
.XR .winbox .wb-control .xr {
|
||||
display:block;
|
||||
}
|
||||
.winbox .wb-control .xr {
|
||||
display:none;
|
||||
background:transparent !important;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
cursor:pointer;
|
||||
}
|
||||
.winbox .wb-control .xr.xr-wb-close,
|
||||
.winbox .wb-control .xr.xr-wb-min{
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
.winbox .wb-body{
|
||||
top:0px;
|
||||
top: 35 !important;
|
||||
padding-top:35px;
|
||||
}
|
||||
.winbox .wb-control{
|
||||
padding-right:5px;
|
||||
height:29px;
|
||||
color:#FFF;
|
||||
z-index:1001;
|
||||
}
|
||||
.winbox .wb-drag{
|
||||
padding-left:19px;
|
||||
|
|
@ -160,7 +186,6 @@ button,input,.btn{
|
|||
background: var(--xrsh-white);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* icons for non-XR (please source from https://css.gg
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>xrsh v0.142</title>
|
||||
<title>xrsh v0.143</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<link rel="stylesheet" href="./index.css"></link>
|
||||
<script src="./assets/aframe.min.js"></script>
|
||||
<script src="./assets/xrfragment.aframe.js"></script>
|
||||
|
||||
<script src="com/require.js"></script>
|
||||
<script src="com/isoterminal.js"></script>
|
||||
|
||||
<!-- todo fix lazy initialisation of require.js -->
|
||||
<script src="com/launcher.js"></script>
|
||||
<script src="com/helloworld-window.js"></script>
|
||||
<script src="com/pressable.js"></script>
|
||||
|
||||
</head>
|
||||
<body style="background:linear-gradient( 45deg, #324, #8c74ff)">
|
||||
|
|
@ -18,42 +24,60 @@
|
|||
renderer="colorManagement: false; stencil: true; antialias:true; highRefreshRate:true; foveationLevel: 0.5;"
|
||||
xr-mode-ui="XRMode: xr"
|
||||
obb-collider="showColliders:false"
|
||||
raycaster="objects: [html]; interval:100;">
|
||||
raycaster="objects: [html]; interval:100;"
|
||||
>
|
||||
|
||||
<!--
|
||||
<a-assets timeout="1000">
|
||||
<a-asset-item id="environment" src="https://coderofsalvation.github.io/xrsh-media/assets/background.glb"></a-asset-item>
|
||||
<a-mixin id="menuitem" geometry="primitive: plane; width: 0.15; height: 0.15; depth: 0.02" obb-collider="size: 0.03 0.03 0.03" ></a-mixin>
|
||||
<a-mixin id="menubutton" geometry="primitive: circle; radius: 0.025" material="side: double; color:#4C73FE"
|
||||
obb-collider="size: 0.03 0.03 0.03" position="-0.003 -0.027 -0.077" rotation="94.53 -6.35 -59.0"></a-mixin>
|
||||
</a-assets>
|
||||
<a-entity isoterminal="iso: ./../xrsh.iso; overlayfs: /package.overlayfs.zip; bootMenuURL: 1" position="0 1.6 -0.3">
|
||||
<a-entity launcher pressable position="0 -0.315 0"></a-entity>
|
||||
</a-entity>
|
||||
|
||||
<a-entity helloworld></a-entity>
|
||||
<a-entity helloworld-window></a-entity>
|
||||
<a-entity save></a-entity>
|
||||
|
||||
<a-entity launcher="attach: #left-hand; fingerTip: #right-hand;" dom position="-0.017 -0.094 -0.085" rotation="133.19 -24.75 -203.1"></a-entity>
|
||||
<a-entity launcher-optional="comps: cast,aframestats,paste,save,xrfragments,example/helloworld-iframe,example/helloworld-htmlform,example/helloworld-window,look-controls-toggle,wasd-controls-toggle"></a-entity>
|
||||
<a-entity noxrf gltf-model="#environment" hide-on-enter-ar></a-entity>
|
||||
-->
|
||||
<a-entity isoterminal="iso: ./../xrsh.iso" position="0 1.6 -0.3"></a-entity>
|
||||
<a-entity helloworld-window pressable position="0 1.6 0"></a-entity>
|
||||
|
||||
<a-entity id="player" >
|
||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera" wasd-controls com="uri: com/control/gaze-touch-to-click.js"></a-entity>
|
||||
<a-entity id="left-hand" hand-tracking-grab-controls="hand: left; modelColor: #cccccc; hoverEnabled:true" laser-controls="hand: left" raycaster="objects:.ray,[html]" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor">
|
||||
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">
|
||||
<a-entity id="back" xrf-button="label: <; width:0.05; action: history.back()" position="-0.025 0 0" class="ray"></a-entity>
|
||||
<a-entity id="next" xrf-button="label: >; width:0.05; action: history.forward()" position=" 0.025 0 0" class="ray"></a-entity>
|
||||
</a-entity>
|
||||
<a-entity id="player">
|
||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera" wasd-controls gaze-touch-to-click></a-entity>
|
||||
<a-entity id="left-hand" hand-tracking-grab-controls="hand: left; modelColor: #EEEEEE; hoverEnabled:true"
|
||||
laser-controls="hand: left"
|
||||
raycaster="far:0.04"
|
||||
blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"
|
||||
>
|
||||
</a-entity>
|
||||
<a-entity id="right-hand" hand-tracking-grab-controls="hand: right; modelColor: #EEEEEE; hoverEnabled:true"
|
||||
laser-controls="hand: right"
|
||||
raycaster="objects:.ray,[html]"
|
||||
raycaster="far:0.04"
|
||||
blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"
|
||||
com="uri: com/control/pinch-to-teleport.js; rig: #player"></a-entity>
|
||||
____pinch-to-teleport="rig: #player"></a-entity>
|
||||
</a-entity>
|
||||
|
||||
</a-scene>
|
||||
|
||||
</body>
|
||||
|
||||
<script>
|
||||
|
||||
// HOWDY DEVELOPER!
|
||||
// for a REPL boilerplate see this codepen instead: https://codepen.io/coderofsalvation/pen/wBwRpew
|
||||
|
||||
document.querySelector('a-scene').addEventListener('isoterminal_init', function(e){
|
||||
// example custom REPL (https://xrsh.isvery.ninja/#Custom%20REPLs)
|
||||
const myREPL = {
|
||||
key: "f",
|
||||
prompt: "\r\nmyrepl> ",
|
||||
title: (opts) => `other awesome NLnet FOSS projects ❤️`,
|
||||
init: function( mainmenu ){
|
||||
window.open('https://nlnet.nl/project/current.html','_blank')
|
||||
this.send("\n\rreturning to mainmenu")
|
||||
mainmenu()
|
||||
},
|
||||
keyHandler: function(ch){
|
||||
this.send(ch) // echo keys to user
|
||||
},
|
||||
cmdHandler: function(cmd){
|
||||
this.send("\r\n"+cmd) // only works after commenting mainmenu()\n")
|
||||
this.send(myREPL.prompt)
|
||||
}
|
||||
}
|
||||
ISOTerminal.prototype.boot.menu.push(myREPL)
|
||||
})
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="./index.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Welcome to XRSHell</h1>
|
||||
<br>
|
||||
<img src="https://i.imgur.com/BW22wrb.png"/>
|
||||
<br><br>
|
||||
The <b>xrsh</b> (xrshell) brings the <a href="https://en.wikipedia.org/wiki/Free_and_open-source_software" target="_blank">FOSS</a>- and <a href="https://en.wikipedia.org/wiki/Linux" target="_blank">Linux</a>-soul to <a href="https://en.wikipedia.org/wiki/WebXR" target="_blank">WebXR</a>, promoting the use of (interactive text) terminal and user-provided operating systems inside WebXR.
|
||||
<br><br>Technically, <b>xrsh</b> is a bundle of freshly created re-usable FOSS WebXR components.<br>These provide a common filesystem interface for interacting with WebXR, offering the well-known linux/unix toolchain including a commandline to invoke, store, edit and run WebXR utilities - regardless of their implementation.
|
||||
<br><br>Think of it as termux for the VR/AR headset browser, which can be used to e.g. livecode (using terminal auto-completion!) for XR component (registries).
|
||||
|
||||
<br>
|
||||
<ul>
|
||||
<li><a href="https://forgejo.isvery.ninja/xrsh" target="_blank">source xrsh</a></li>
|
||||
<li><a href="https://forgejo.isvery.ninja/xrsh-apps" target="_blank">source xrsh apps</a></li>
|
||||
<li><a href="https://forgejo.isvery.ninja/xrsh-media" target="_blank">roadmap meeting recordings</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
1
src/tags
1
src/tags
|
|
@ -1 +0,0 @@
|
|||
/home/leon/.ctags.js
|
||||
|
|
@ -1,37 +1,56 @@
|
|||
term = document.querySelector('[isoterminal]').components.isoterminal.term
|
||||
convert = ISOTerminal.prototype.convert
|
||||
isoterminal = document.querySelector("[isoterminal]")
|
||||
|
||||
console.test("com/isoterminal/ISOTerminal.js", async () => {
|
||||
isoterminal.addEventListener("ready", function(){
|
||||
|
||||
term = isoterminal.components.isoterminal.term
|
||||
convert = ISOTerminal.prototype.convert
|
||||
|
||||
console.test.tests = {} // empty previous tests
|
||||
|
||||
console.test("com/isoterminal/ISOTerminal.js", async () => {
|
||||
|
||||
term.worker.create_file("foo", convert.toUint8Array("hello") )
|
||||
.then( (res) => {
|
||||
term.worker.read_file("foo")
|
||||
.then( (res) => {
|
||||
try{
|
||||
let data = convert.Uint8ArrayToString( res )
|
||||
console.assert( data == "hello", "worker.create_file")
|
||||
}catch(e){
|
||||
console.assert( false, "worker.create_file")
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(console.error)
|
||||
.finally(console.dir)
|
||||
|
||||
term.worker.read_file("root/.profile")
|
||||
.then( (res) => {
|
||||
try{
|
||||
let data = convert.Uint8ArrayToString( res )
|
||||
console.assert( data.length, "worker.postMessage.promise()")
|
||||
}catch(e){
|
||||
console.assert( false, "worker.postMessage.promise()")
|
||||
}
|
||||
})
|
||||
.catch(console.error)
|
||||
.finally(console.dir)
|
||||
|
||||
})
|
||||
console.test("com/isoterminal/ISOTerminal.js", async () => {
|
||||
|
||||
console.test("com/isoterminal/ISOTerminal.js", async () => {
|
||||
|
||||
term.worker.create_file("foo", convert.toUint8Array("hello") )
|
||||
.then( (res) => {
|
||||
term.worker.read_file("foo")
|
||||
.then( (res) => {
|
||||
try{
|
||||
let data = convert.Uint8ArrayToString( res )
|
||||
console.assert( data == "hello", "worker.create_file")
|
||||
console.assert( data.length && data == "hello", "worker.postMessage.promise()")
|
||||
}catch(e){
|
||||
console.assert( false, "worker.create_file")
|
||||
console.assert( false, "worker.postMessage.promise()")
|
||||
}
|
||||
})
|
||||
.catch(console.error)
|
||||
.finally(console.dir)
|
||||
|
||||
})
|
||||
.catch(console.error)
|
||||
.finally(console.dir)
|
||||
|
||||
|
||||
console.test.run()
|
||||
|
||||
})
|
||||
|
||||
console.test("com/isoterminal.js", async () => {
|
||||
console.assert( AFRAME.components.isoterminal != undefined, "AFRAME.components.isoterminal")
|
||||
})
|
||||
|
||||
console.test("xrsh.iso", async () => {
|
||||
console.assert( false, "create testsuite.zip package which tests iso")
|
||||
})
|
||||
|
|
|
|||
10
src/tests/index.js
Normal file
10
src/tests/index.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
const run = async function(){
|
||||
await AFRAME.utils.require({
|
||||
"test_util": "tests/util.js",
|
||||
"test_isoterminal":"tests/ISOTerminal.js"
|
||||
})
|
||||
console.test.run()
|
||||
}
|
||||
|
||||
run()
|
||||
|
|
@ -1,20 +1,23 @@
|
|||
|
||||
// minimalistc testrunner
|
||||
console.test = async (name,cb) => {
|
||||
window.console.test = async (name,cb) => {
|
||||
let tests = console.test.tests = console.test.tests || {}
|
||||
tests[name] = tests[name] || []
|
||||
tests[name].push(cb)
|
||||
console.test.run = async () => {
|
||||
for( let name in tests ){
|
||||
console.log("\x1b[34m\x1b[36;49m"+name+"\x1B[m")
|
||||
for( let test in tests[name] ){
|
||||
await tests[name][test]()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.assert = ((assert) => (a,reason,data) => {
|
||||
window.console.test.run = async (cb) => {
|
||||
const tests = window.console.test.tests
|
||||
for( let name in tests ){
|
||||
console.log("\x1b[34m\x1b[36;49m"+name+"\x1B[m")
|
||||
for( let test in tests[name] ){
|
||||
await tests[name][test]()
|
||||
}
|
||||
}
|
||||
if( cb ) cb()
|
||||
}
|
||||
|
||||
window.console.assert = ((assert) => (a,reason,data) => {
|
||||
console.log("\x1b[34m\x1b[36;49m♥ \x1B[m"+reason)
|
||||
assert.call( console, a, {reason} )
|
||||
if( !a ){
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 1b5cf3febbb0f451003c56d4579294ca57e447f0
|
||||
Subproject commit 10bbfd27e21a1b7368c38432178309263662aef6
|
||||
60139
src/xrsh.html
60139
src/xrsh.html
File diff suppressed because one or more lines are too long
60
xrsh
Executable file
60
xrsh
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
#!/bin/sh
|
||||
PORT=9090
|
||||
PROCFILE=/tmp/.xrsh
|
||||
|
||||
usage(){ echo "Usage: xrsh [--keyboard] [--kill]"; exit; }
|
||||
|
||||
assert_cmds(){
|
||||
for cmd in $1; do
|
||||
command -v $cmd &>/dev/null || { echo "error: please install $cmd (not found)"; exit 1; }
|
||||
done
|
||||
}
|
||||
|
||||
showip(){
|
||||
{ # naive way of getting network ip
|
||||
command -v ip &>/dev/null && ip addr show
|
||||
command -v ifconfig &>/dev/null && ifconfig
|
||||
} | grep 'inet ' | grep -v ' 127' | awk '! /addr:/ { gsub(/\/.*/,"",$2); if( !SEEN[$2] ) print $2; SEEN[$2]=1 }'
|
||||
|
||||
}
|
||||
|
||||
setupcerts(){
|
||||
test -f ~/.websocat/cert.pem && return 0
|
||||
mkdir ~/.websocat 2>/dev/null || true
|
||||
echo "--- generating temporary SSL certs (press enter to all questions) ---"
|
||||
#openssl req -x509 -newkey rsa:4096 -keyout ~/.websocat/key.pem -out ~/.websocat/cert.pem -days 365
|
||||
openssl req -x509 -newkey rsa:2048 -new -nodes -keyout ~/.websocat/key.pem -out ~/.websocat/cert.pem -days 3650
|
||||
openssl pkcs12 -export -out ~/.websocat/q.pkcs12 -inkey ~/.websocat/key.pem -in ~/.websocat/cert.pem
|
||||
wget "https://curl.haxx.se/ca/cacert.pem" -O ~/.websocat/cacert.pem
|
||||
}
|
||||
|
||||
keyboard(){
|
||||
assert_cmds websocat pkill
|
||||
trap "stty sane; trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT # cleanup processes when exit
|
||||
echo $$ > $PROCFILE
|
||||
echo ""
|
||||
echo " 1. type 'k' (remote keyboard) in xrsh"
|
||||
echo " 2. enter ipaddress: $(showip)"
|
||||
echo ""
|
||||
echo "warn: CTRL-C is forwarded too"
|
||||
echo "warn: to exit this app run: $0 --kill"
|
||||
echo "warn: this terminal is now in raw sendmode, expect weird characters!"
|
||||
stty raw
|
||||
if test -n "$SSL"; then
|
||||
setupcerts
|
||||
websocat -E -b -s --pkcs12-der ~/.websocat/q.pkcs12 0.0.0.0:$PORT 2>&1
|
||||
else
|
||||
websocat -E -b -s 0.0.0.0:$PORT 2>&1 # http-only
|
||||
fi
|
||||
}
|
||||
|
||||
# launch!
|
||||
test -n "$1" || { echo "usage: xrsh [--ssl] [--keyboard] [--kill]"; exit; }
|
||||
for arg in $*; do
|
||||
case $arg in
|
||||
--kill) pkill -P $(cat $PROCFILE); exit ;;
|
||||
--ssl) export SSL=1; ;;
|
||||
--keyboard) keyboard "$@"; ;;
|
||||
esac
|
||||
done
|
||||
|
||||
BIN
xrsh.com
BIN
xrsh.com
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
56341bacae1c5574767d2488c8fb33633bbfca06082943403f06b5ebebf6ecfd xrsh.com
|
||||
e791dba58adf568d34648eeed71e047d60b126b3dd5a6d81306a4307c5b7c3ad xrsh.com
|
||||
|
|
|
|||
36
xrsh.html
Normal file
36
xrsh.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
|
||||
<script src="https://xrsh.isvery.ninja/xrsh.js"></script>
|
||||
|
||||
<a-scene>
|
||||
<a-entity isoterminal position="0 1.6 -0.3"></a-entity>
|
||||
|
||||
<a-entity id="left-hand" hand-tracking-grab-controls="hand: left; modelColor: #EEEEEE; hoverEnabled:true"
|
||||
laser-controls="hand: left" raycaster="objects:.ray,[html]"></a-entity>
|
||||
<a-entity id="right-hand" hand-tracking-grab-controls="hand: right; modelColor: #EEEEEE; hoverEnabled:true"
|
||||
laser-controls="hand: right"
|
||||
raycaster="objects:.ray,[html]"></a-entity>
|
||||
</a-scene>
|
||||
|
||||
<script>
|
||||
document.querySelector('a-scene').addEventListener('isoterminal_init', function(e){
|
||||
// override/extend bootmenu-array with your own REPL(s)
|
||||
// see com/isoterminal/feat/boot.REPL.*.js for examples
|
||||
ISOTerminal.prototype.boot.menu.push({
|
||||
key: "f",
|
||||
title: (opts) => `other awesome NLnet FOSS projects ❤️`,
|
||||
init: function( mainmenu ){
|
||||
window.open('https://nlnet.nl/project/current.html','_blank')
|
||||
// return to main menu
|
||||
mainmenu()
|
||||
},
|
||||
keyHandler: function(ch){
|
||||
this.send("\n\ryou typed:"+ch) // write to term
|
||||
}
|
||||
})
|
||||
|
||||
// AFRAME exposes THREE by default
|
||||
console.log( THREE )
|
||||
})
|
||||
</script>
|
||||
|
||||
2
xrsh.iso
2
xrsh.iso
|
|
@ -1 +1 @@
|
|||
src/xrsh-buildroot/xrsh.iso
|
||||
xrsh.iso.buildroot
|
||||
1
xrsh.iso.buildroot
Symbolic link
1
xrsh.iso.buildroot
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../xrsh-buildroot/dist/v86-linux.iso
|
||||
1
xrsh.iso.repository
Symbolic link
1
xrsh.iso.repository
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
src/xrsh-buildroot/xrsh.iso
|
||||
1
xrsh.iso.wtux
Symbolic link
1
xrsh.iso.wtux
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../wtux/output/wtux.iso
|
||||
4503
xrsh.js
Normal file
4503
xrsh.js
Normal file
File diff suppressed because one or more lines are too long
9
xrsh.nix.log
Normal file
9
xrsh.nix.log
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
env-vars:
|
||||
CHANNEL=nixpkgs
|
||||
CMD=nix-build
|
||||
channels:
|
||||
nixos https://nixos.org/channels/nixos-24.05
|
||||
nixos-22.11 https://nixos.org/channels/nixos-22.11
|
||||
nixos-24.05 https://nixos.org/channels/nixos-24.05
|
||||
nixos-unstable https://nixos.org/channels/nixos-unstable
|
||||
/nix/store/p3314mbnga40x8sdmfx1xzc0cdbqvf50-xrsh-0.221
|
||||
Loading…
Add table
Reference in a new issue