janusweb 1.5.56 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.github/workflows/deploy.yml +71 -0
  2. package/Dockerfile +14 -0
  3. package/README.md +258 -19
  4. package/janusxr.com/.args +2 -0
  5. package/janusxr.com/.init.lua +30 -0
  6. package/media/assets/webui/apps/comms/voip.js +27 -25
  7. package/media/assets/webui/apps/editor/editor.js +16 -0
  8. package/media/assets/webui/apps/locomotion/locomotion-assets.json +3 -0
  9. package/media/assets/webui/apps/locomotion/teleport.mp3 +0 -0
  10. package/media/assets/webui/apps/locomotion/teleporter.js +75 -43
  11. package/media/assets/webui/apps/navigation/navigation.js +6 -1
  12. package/media/assets/webui/apps/xrfragment/level0-sidecarfile.js +308 -0
  13. package/media/assets/webui/apps/xrfragment/level2-hyperlink.js +265 -0
  14. package/media/assets/webui/apps/xrfragment/level7-engine-prefixes.export.js +93 -0
  15. package/media/assets/webui/apps/xrfragment/level7-engine-prefixes.import.js +229 -0
  16. package/media/assets/webui/apps/xrfragment/patch/metaquest-fix-flickering.js +15 -0
  17. package/media/assets/webui/apps/xrfragment/xrfragment.json +14 -0
  18. package/media/assets/webui/apps/xrmenu/images/teleport.png +0 -0
  19. package/media/assets/webui/apps/xrmenu/xrmenu-assets.json +2 -1
  20. package/media/assets/webui/apps/xrmenu/xrmenu.js +39 -15
  21. package/media/assets/webui/default.json +1 -0
  22. package/media/images/portal.svg +130 -0
  23. package/media/index.html +48 -1
  24. package/package.json +1 -1
  25. package/scripts/client.js +24 -0
  26. package/scripts/config.js +12 -1
  27. package/scripts/janusbase.js +14 -22
  28. package/scripts/janusghost.js +2 -2
  29. package/scripts/janusparagraph.js +195 -12
  30. package/scripts/janusplayer.js +9 -6
  31. package/scripts/room.js +91 -44
  32. package/scripts/sound.js +1 -1
  33. package/scripts/text.js +2 -1
  34. package/scripts/translators/paragraph/html-xml-rss.js +47 -0
  35. package/scripts/translators/peertube.js +89 -0
  36. package/scripts/translators/xrfragments.js +93 -0
  37. package/tests/room/paragraph.xml +47 -0
  38. package/utils/build.sh +1 -0
  39. package/utils/clean-build.sh +5 -0
  40. package/utils/dev-link.sh +75 -0
  41. package/utils/release.binary.sh +36 -0
  42. package/utils/release.docker.sh +11 -0
@@ -0,0 +1,89 @@
1
+ elation.require([], function() {
2
+ elation.component.add('janusweb.translators.peertube', function() {
3
+ this.init = function() {
4
+ this.description = "peertube website to 3D translator"
5
+ }
6
+ this.exec = function(args) {
7
+ return new Promise(elation.bind(this, function(resolve, reject) {
8
+
9
+ var room = this.room = args.room;
10
+
11
+ reject() // for now
12
+
13
+ this.setupEvents()
14
+ var datapath = elation.config.get('janusweb.datapath', '/media/janusweb');
15
+
16
+ var roomdata = {
17
+ assets: {
18
+ assetlist: [
19
+ // {assettype: 'model', name: 'scene', src: args.url},
20
+ ]
21
+ },
22
+ room: {
23
+ pos: [0,0,0],
24
+ xdir: "1 0 0",
25
+ zdir: "0 0 1",
26
+ },
27
+ object: [
28
+ // {id: 'scene', js_id: 0, pos: "0 0 0", xdir: "-1 0 0", zdir: "0 0 -1", lighting: "false"}
29
+ ],
30
+ link: []
31
+ };
32
+ resolve(roomdata);
33
+ }));
34
+ }
35
+
36
+ // translate XR Fragments microformat into JML
37
+ this.parseSource = async function(sourcecode, room){
38
+ this.room = room
39
+ const isJML = /<fireboxroom>[\s\S]*?<\/fireboxroom>/si;
40
+ const isPeertube = /<meta\s+[^>]*property=['"]og:platform['"]\s+[^>]*content=['"]peertube['"][^>]*\/?>/si;
41
+ const isPeertubeVideo = /<meta\s+[^>]*property=['"]og:type['"]\s+[^>]*content=['"]video['"][^>]*\/?>/si;
42
+ const isPeertubeInstance = /<meta\s+[^>]*property=['"]og:type['"]\s+[^>]*content=['"]website['"][^>]*\/?>/si;
43
+ const is = {
44
+ JML: sourcecode.match(isJML),
45
+ peertube: sourcecode.match(isPeertube),
46
+ peertubeVideo: sourcecode.match(isPeertubeVideo),
47
+ peertubeInstance: sourcecode.match(isPeertubeInstance),
48
+ }
49
+ if( is.JML || !is.peertube ) return // JML takes precedence over microformats
50
+ if( !is.peertubeVideo && !is.peertubeInstance ) return
51
+
52
+ // ok..peertube time: get domtree
53
+ let el = document.createElement("div")
54
+ el.innerHTML = sourcecode
55
+
56
+ // try to fetch title + cover
57
+ const title = el.querySelector("title")
58
+ let logo = el.querySelector("meta[property='og:image']")?.getAttribute("content")
59
+ logo = logo ? logo : el.querySelector("meta[property='og:image:url']")?.getAttribute("content")
60
+
61
+ let url = new URL( String(room.url) )
62
+ let instance = url?.origin
63
+ let search = url?.search ? new URLSearchParams(url.search).get("search") : ""
64
+
65
+ // return JML
66
+ return room.parseSource(`
67
+ <title>${ title ? title.innerText.replace(/\n.*/g,'') : room.baseurl.split("/").pop() }</title>
68
+ <FireBoxRoom>
69
+ <Assets>
70
+ ${ logo ? `<assetimage src="${logo}" id="logo"/>` : ''}
71
+ <assetscript src="https://codeberg.org/coderofsalvation/janus-script-peertube/raw/branch/master/build/janus-script-peertube.js"/>
72
+ <assetobject src="https://codeberg.org/coderofsalvation/janus-script-peertube/raw/branch/master/build/asset/button.glb" id="button"/>
73
+ <assetobject src="https://codeberg.org/coderofsalvation/janus-script-peertube/raw/branch/master/build/asset/button.icon.glb" id="icon"/>
74
+ <assetsound src="https://codeberg.org/coderofsalvation/janus-script-peertube/raw/branch/master/build/asset/button.click.mp3" id="button-click"/>
75
+ <assetsound src="https://codeberg.org/coderofsalvation/janus-script-peertube/raw/branch/master/build/asset/button.hover.mp3" id="button-hover"/>
76
+ </Assets>
77
+ <Room use_local_asset="room_2pedestal" pos="1.15 0 -5" rotation="0 1.5708 0" fwd="1 0 0">
78
+ ${ is.peertubeInstance ? `<peertube-app pos="4.55 2.71 -4.7" scale="2 2 1" rotation="0 90 0" js_id="mypeertube-app" instance="${instance}" ${search?`search="${search}"`:``} autoload="true"/>`
79
+ : `<peertube pos="4.55 2.71 -4.7" scale="2 2 1" rotation="0 90 0" js_id="peertube" src="${room.url}" auto_play="true"/>`
80
+ }
81
+ ${ logo ? `<image id="logo"/>` : ''}
82
+ </Room>
83
+ </FireBoxRoom>
84
+ `)
85
+ }
86
+ // peertube microformat heuristic: <meta property="og:platform" content="PeerTube">
87
+ this.parseSource.regex = /<meta\s+[^>]*property=['"]og:platform['"]\s+[^>]*content=['"]peertube['"][^>]*\/?>/si;
88
+ });
89
+ });
@@ -0,0 +1,93 @@
1
+ elation.require([], function() {
2
+ elation.component.add('janusweb.translators.xrfragments', function() {
3
+ this.init = function() {
4
+ this.description = "this implements the https://xrfragment.org standard for immersive 3d file browsing"
5
+ }
6
+ this.exec = function(args) {
7
+ return new Promise(elation.bind(this, function(resolve, reject) {
8
+
9
+ var room = this.room = args.room;
10
+ this.setupEvents()
11
+
12
+ var datapath = elation.config.get('janusweb.datapath', '/media/janusweb');
13
+
14
+ var roomdata = {
15
+ assets: {
16
+ assetlist: [
17
+ {assettype: 'model', name: 'scene', src: args.url},
18
+ ]
19
+ },
20
+ room: {
21
+ gravity: 0,
22
+ pos: [0,0,0],
23
+ xdir: "1 0 0",
24
+ zdir: "0 0 1",
25
+ },
26
+ object: [
27
+ {id: 'scene', js_id: "scene", pos: "0 0 0", xdir: "-1 0 0", zdir: "0 0 -1"}
28
+ ],
29
+ link: []
30
+ };
31
+ resolve(roomdata);
32
+ }));
33
+ }
34
+
35
+ this.spawnUserAtFragment = function(source) {
36
+ // XR Fragments deeplink spec: explicit or default spawn
37
+ // https://xrfragment.org/#teleport%20camera
38
+ if( ! room.urlhash ) room.urlhash = 'spawn'
39
+ room.setPlayerPosition.apply(room)
40
+ console.log("[xrfragment] camera teleport")
41
+ }
42
+
43
+ this.setupEvents = function(){
44
+ elation.events.add(room._room, 'room_load_complete', this.spawnUserAtFragment.bind(this) )
45
+ }
46
+
47
+ // translate XR Fragments microformat into JML
48
+ this.parseSource = async function(sourcecode, room){
49
+ this.room = room
50
+ const isJML = /<fireboxroom>[\s\S]*?<\/fireboxroom>/si;
51
+ if( sourcecode.match(isJML) ) return // JML takes precedence over microformats
52
+
53
+ // extract href/title value
54
+ let el = document.createElement("div")
55
+ el.innerHTML = sourcecode
56
+ const link = el.querySelector("link[as=spatial-entrypoint]")
57
+ if( !link ) return
58
+ const title = el.querySelector("title")
59
+ const href = link.getAttribute("href")
60
+ if( !href ) return
61
+ console.log("[xrfragment] detected XRF microformat")
62
+ const hrefNoHash = href.replace(/#.*/,'')
63
+
64
+ // if microformat has xr fragment in URI, use it if room-url has no xr fragment
65
+ if( href.match(/#/) && !room.urlhash ){
66
+ room.urlhash = href.replace(/.*#/,'')
67
+ }
68
+ // check if link exists
69
+ const hrefFull = hrefNoHash.match('://') ? hrefNoHash : String(room.baseurl+hrefNoHash)
70
+ const exist = await fetch( hrefFull ,{method:'HEAD'})
71
+ if( !exist.ok ) return console.warn(`[xrfragment] ${link.outerHTML} resolves to invalid url ${hrefFull}`)
72
+
73
+ // setup events
74
+ this.setupEvents()
75
+ // return JML
76
+ return room.parseSource(`
77
+ <title>${ title ? title.innerText.replace(/\n.*/g,'') : room.baseurl.split("/").pop() }</title>
78
+ <FireBoxRoom>
79
+ <Assets>
80
+ <assetobject id="scene" src="${hrefNoHash}"/>
81
+ </Assets>
82
+ <Room gravity="0">
83
+ <object pos="0 0 0" collision_id="scene" id="scene" />
84
+ </Room>
85
+ </FireBoxRoom>
86
+ `)
87
+ }
88
+ // microformat heuristic (https://xrfragment.org/#XRF%20microformat)
89
+ // example: <link rel="alternate" as="spatial-entrypoint" src="https://foo.org/bar.glb">
90
+ this.parseSource.regex = /<link\s+[^>]*rel=['"]spatial-entrypoint['"][^>]*\/?>/si;
91
+
92
+ });
93
+ });
@@ -0,0 +1,47 @@
1
+ <html>
2
+ <body>
3
+ <style type="text/css">
4
+ body > div,
5
+ .paragraphcontainer {
6
+ background: linear-gradient(45deg,#73F7,#F377);
7
+ color: #FFF;
8
+ border:3px solid #73F;
9
+ border-radius:12px;
10
+ padding:7px;
11
+ }
12
+ </style>
13
+ <div class="section">
14
+ <b>hello from JML container document</b>
15
+ <br/>
16
+ This content is from the document<br/>
17
+ which embeds this Janus room JML.<br/>
18
+ <img src="https://janusxr.org/images/janusxr-logo.png" width="70"/>
19
+ </div>
20
+ <div class="section">
21
+ <b>container: Foo bar</b>
22
+ <br/>
23
+ So you're looking at an multidimensional<br/>
24
+ hypertext document 💪<br/>
25
+ <img src="https://janusxr.org/images/team/team_bai.jpg" width="70"/>
26
+ </div>
27
+ </body>
28
+ <fireboxroom>
29
+ <assets>
30
+ </assets>
31
+ <room pos="0 -1 -2">
32
+ <paragraph js_id="p1" lighting="false" scale="0.4 0.2 1" width="400" height="200" url="https://janusxr.org" selector=".infoText" rotation="0 180 0" position="-1 0 0"/>
33
+ <paragraph js_id="p2" lighting="false" scale="0.4 0.2 1" width="400" height="200" url="https://mastodon.online/@lvk.rss" selector="item description" rotation="0 180 0" pos="0 0 0"/>
34
+ <paragraph js_id="p3" lighting="false" scale="0.4 0.2 1" width="400" height="200" selector=".section" rotation="0 180 0" pos="1 0 0"/>
35
+ <paragraph js_id="p4" lighting="false" scale="0.4 0.2 1" width="400" height="200" selector=".info" rotation="0 180 0" pos="2 0 0" css=".paragraphcontainer{background:black;color:#A5F; border-radius:10px}" indexrotate="1700">
36
+ <![CDATA[
37
+ <div class="info">Clicking this &lt;div&gt; will cycle</div>
38
+ <div class="info">through all divs</div>
39
+ <div class="info">with class="info"</div>
40
+ <div class="info">this also works with RSS urls</div>
41
+ <div class="info">when you set the selector</div>
42
+ <div class="info">to selector="item description"</div>
43
+ ]]>
44
+ </paragraph>
45
+ </room>
46
+ </fireboxroom>
47
+ </html>
package/utils/build.sh CHANGED
@@ -9,6 +9,7 @@ if [ -z "$NODEJS" ]; then
9
9
  exit
10
10
  fi
11
11
 
12
+ export PATH=$PATH:$(pwd)/node_modules/.bin # uglifyjs fix
12
13
 
13
14
  VERSION=$("$NODEJS" -pe "require('./package.json').version")
14
15
  BUILDROOT=$(pwd)/build
@@ -2,3 +2,8 @@
2
2
 
3
3
  [ -e elation ] && rm -r elation
4
4
  [ -e node_modules ] && rm -r node_modules
5
+ [ -d build ] && rm -r build
6
+ read -p "[?] bleeding-edge dependencies? (y/n) " ok
7
+ test "$ok" = y && rm package-lock.json
8
+ npm install
9
+ utils/build.sh
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env bash
2
+ # Manage local npm links for janusweb's elation-family dependencies.
3
+ #
4
+ # Default workflow: `npm install` pulls published versions of these
5
+ # packages into node_modules. Use this script to swap any of them for
6
+ # a local checkout while developing, and swap back when done.
7
+ #
8
+ # Usage:
9
+ # utils/dev-link.sh link <pkg> <path> point node_modules/<pkg> at <path>
10
+ # utils/dev-link.sh unlink <pkg> remove the link and reinstall <pkg>
11
+ # utils/dev-link.sh status show link state for tracked packages
12
+
13
+ set -e
14
+
15
+ # Packages this script knows about, for the `status` listing. Linking
16
+ # isn't restricted to these — `link <name> <path>` works for any name.
17
+ TRACKED=(elation elation-engine cyclone-physics elation-share)
18
+
19
+ JANUSWEB_DIR="$(cd "$(dirname "$0")/.." && pwd)"
20
+
21
+ usage() {
22
+ sed -n '2,12p' "$0" | sed 's/^# \?//'
23
+ exit 1
24
+ }
25
+
26
+ cmd_link() {
27
+ local name="$1" path="$2"
28
+ if [ -z "$name" ] || [ -z "$path" ]; then
29
+ echo "link requires <pkg> and <path>" >&2; usage
30
+ fi
31
+ if [ ! -d "$path" ]; then
32
+ echo "Source path not found: $path" >&2; exit 1
33
+ fi
34
+ path="$(cd "$path" && pwd)"
35
+ echo "==> Linking $name from $path"
36
+ (cd "$path" && npm link >/dev/null)
37
+ (cd "$JANUSWEB_DIR" && npm link "$name" >/dev/null)
38
+ }
39
+
40
+ cmd_unlink() {
41
+ local name="$1"
42
+ if [ -z "$name" ]; then
43
+ echo "unlink requires <pkg>" >&2; usage
44
+ fi
45
+ local target="$JANUSWEB_DIR/node_modules/$name"
46
+ if [ ! -L "$target" ]; then
47
+ echo "$name is not linked"; exit 0
48
+ fi
49
+ echo "==> Unlinking $name and reinstalling from registry"
50
+ (cd "$JANUSWEB_DIR" && npm unlink "$name" --no-save >/dev/null) || true
51
+ (cd "$JANUSWEB_DIR" && npm install "$name" --no-save >/dev/null)
52
+ }
53
+
54
+ cmd_status() {
55
+ for name in "${TRACKED[@]}"; do
56
+ local target="$JANUSWEB_DIR/node_modules/$name"
57
+ if [ -L "$target" ]; then
58
+ printf " %-22s linked -> %s\n" "$name" "$(readlink "$target")"
59
+ elif [ -d "$target" ]; then
60
+ local v
61
+ v=$(node -p "require('$target/package.json').version" 2>/dev/null || echo "?")
62
+ printf " %-22s installed (%s)\n" "$name" "$v"
63
+ else
64
+ printf " %-22s not installed\n" "$name"
65
+ fi
66
+ done
67
+ }
68
+
69
+ case "${1:-}" in
70
+ link) shift; cmd_link "$@" ;;
71
+ unlink) shift; cmd_unlink "$@" ;;
72
+ status) cmd_status ;;
73
+ -h|--help|help|'') usage ;;
74
+ *) echo "Unknown command: $1" >&2; echo; usage ;;
75
+ esac
@@ -0,0 +1,36 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ VERSION=$( $(which node) -pe "require('./package.json').version")
5
+ BUILD=build/$VERSION
6
+
7
+ test -f "$BUILD/index.html" || { echo "[x] could not find $BUILD/index.html (run 'npm run build' first)"; exit 1;}
8
+
9
+ download(){
10
+ rm $BUILD/*.com || true # delete old
11
+ url="https://redbean.dev/redbean-3.0.0.com"
12
+ checksum="382f1288bb96ace4bab5145e7df236846c33cc4f1be69233710682a9e71e7467 $BUILD/janusxr.com"
13
+ verify(){
14
+ echo "$checksum" > /tmp/checksum
15
+ sha256sum -c /tmp/checksum || { echo "psuedosecurity checksum failed"; exit 1; }
16
+ chmod +x $BUILD/janusxr.com
17
+ }
18
+ test -f $BUILD/janusxr.com || {
19
+ wget "$url" -O $BUILD/janusxr.com
20
+ verify
21
+ }
22
+ }
23
+
24
+ configure(){
25
+ cd $BUILD
26
+ ln -fs media/images/icons/janusweb-256x256.ico favicon.ico
27
+ sed -i 's|<janus-viewer src.*|<janus-viewer src="./index.html"></janus-viewer>|g' index.html
28
+ zip -r janusxr.com * -x janusweb.min.js
29
+ set -e
30
+ set -x
31
+ cd ../../janusxr.com
32
+ zip -r ../$BUILD/janusxr.com .args .init.lua *
33
+ }
34
+
35
+ download
36
+ configure
@@ -0,0 +1,11 @@
1
+ #!/bin/sh
2
+ VERSION=$( $(which node) -pe "require('./package.json').version")
3
+
4
+ set -xe
5
+ docker build -t janusxr --build-arg JANUSXR_VERSION=$VERSION .
6
+
7
+ # push to registry
8
+ docker login codeberg.org
9
+ docker tag janusxr:latest codeberg.org/coderofsalvation/janusxr:$VERSION
10
+ docker push codeberg.org/coderofsalvation/janusxr:$VERSION
11
+