diff --git a/build.js b/build.js
index 128cc83..dc1c6da 100644
--- a/build.js
+++ b/build.js
@@ -18,6 +18,7 @@ const validationQueue = []
const validationHost = os.hostname() === "future" ? "http://localhost:8888/" : "http://validator.w3.org/nu/"
const static = new Map()
const links = new Map()
+const sources = new Map()
const pugLocals = {static, links}
const spec = require("./spec.js")
@@ -26,6 +27,14 @@ function hash(buffer) {
return crypto.createHash("sha256").update(buffer).digest("hex").slice(0, 10)
}
+function getRelative(targetPath, staticTarget) {
+ const pathLayer = (path.dirname(targetPath).replace(/\/$/, "").match(/\//g) || []).length
+ const prefix = Array(pathLayer).fill("../").join("")
+ const result = prefix + staticTarget.replace(/^\//, "")
+ if (result) return result
+ else return "./"
+}
+
function validate(filename, body, type) {
const promise = fetch(validationHost+"?out=json", {
method: "POST",
@@ -82,7 +91,7 @@ function runHint(filename, source) {
undef: true,
// unused: true,
loopfunc: true,
- globals: ["console", "URLSearchParams"],
+ globals: ["console", "URLSearchParams", "staticFiles"],
browser: true,
asi: true,
})
@@ -121,11 +130,21 @@ async function addFile(sourcePath, targetPath) {
fs.writeFile(pj(buildDir, targetPath), contents)
}
+async function loadJS(sourcePath, targetPath) {
+ let content = await fs.readFile(pj(".", sourcePath), {encoding: "utf8"})
+ sources.set(sourcePath, content)
+ static.set(sourcePath, `${targetPath}?static=${hash(content)}`)
+}
+
async function addJS(sourcePath, targetPath) {
- const source = await fs.readFile(pj(".", sourcePath), {encoding: "utf8"})
- static.set(sourcePath, `${targetPath}?static=${hash(source)}`)
- runHint(sourcePath, source);
- fs.writeFile(pj(buildDir, targetPath), source)
+ let content = sources.get(sourcePath)
+ // resolve imports to hashed paths
+ content = content.replace(/\$to_relative "([^"]+)"/g, function(_, file) {
+ if (!static.get(file)) throw new Error(`Tried to relative import ${file} from ${sourcePath}, but import not found`)
+ return '"' + getRelative(targetPath, static.get(file)) + '"'
+ })
+ runHint(sourcePath, content)
+ fs.writeFile(pj(buildDir, targetPath), content)
}
async function addSass(sourcePath, targetPath) {
@@ -154,21 +173,17 @@ async function addSass(sourcePath, targetPath) {
}
async function addPug(sourcePath, targetPath) {
- function getRelative(staticTarget) {
- const pathLayer = (path.dirname(targetPath).replace(/\/$/, "").match(/\//g) || []).length
- const prefix = Array(pathLayer).fill("../").join("")
- const result = prefix + staticTarget.replace(/^\//, "")
- if (result) return result
- else return "./"
+ function getRelativeHere(staticTarget) {
+ return getRelative(targetPath, staticTarget)
}
function getStatic(target) {
- return getRelative(static.get(target))
+ return getRelativeHere(static.get(target))
}
function getStaticName(target) {
- return getRelative(static.get(target)).replace(/\?.*$/, "")
+ return getRelativeHere(static.get(target)).replace(/\?.*$/, "")
}
function getLink(target) {
- return getRelative(links.get(target))
+ return getRelativeHere(links.get(target))
}
const renderedHTML = pug.compileFile(pj(".", sourcePath), {pretty: true})({getStatic, getStaticName, getLink, ...pugLocals})
let renderedWithoutPHP = renderedHTML.replace(/<\?(?:php|=).*?\?>/gsm, "")
@@ -217,10 +232,18 @@ async function addBabel(sourcePath, targetPath) {
}
}
+ // Stage 2: Load JS
+ await Promise.all(spec.filter(item => {
+ return item.type === "js"
+ }).map(item => {
+ return loadJS(item.source, item.target)
+ }))
+
+ // Stage 3: Create dirs
const dirs = [...new Set(spec.map(item => path.dirname(item.target))).values()]
await Promise.all(dirs.map(d => fs.mkdir(pj(buildDir, d), {recursive: true})))
- // Stage 2: Build
+ // Stage 4: Build
for (const item of spec) {
if (item.type === "file") {
await addFile(item.source, item.target)
diff --git a/build/index.html b/build/index.html
index fa53161..29b927a 100644
--- a/build/index.html
+++ b/build/index.html
@@ -2,12 +2,15 @@
+
+
-
-
-
-
-
+
+
+
+
+
Carbon
diff --git a/build/static/Anchor.js b/build/static/Anchor.js
index c887510..d07e239 100644
--- a/build/static/Anchor.js
+++ b/build/static/Anchor.js
@@ -1,4 +1,4 @@
-import {ElemJS} from "./basic.js"
+import {ElemJS} from "../static/basic.js?static=4212436742"
class Anchor extends ElemJS {
constructor() {
diff --git a/build/static/Timeline.js b/build/static/Timeline.js
index 9917522..9383763 100644
--- a/build/static/Timeline.js
+++ b/build/static/Timeline.js
@@ -1,9 +1,9 @@
-import {ElemJS, ejs} from "./basic.js"
-import {Subscribable} from "./store/Subscribable.js"
-import {store} from "./store/store.js"
-import {Anchor} from "./Anchor.js"
-import * as lsm from "./lsm.js"
-import {resolveMxc} from "./functions.js"
+import {ElemJS, ejs} from "../static/basic.js?static=4212436742"
+import {Subscribable} from "../static/store/Subscribable.js?static=19b7e44aa6"
+import {store} from "../static/store/store.js?static=ce3066287b"
+import {Anchor} from "../static/Anchor.js?static=85efd1a836"
+import * as lsm from "../static/lsm.js?static=aed2c7ca35"
+import {resolveMxc} from "../static/functions.js?static=e3784c70ce"
const dateFormatter = Intl.DateTimeFormat("default", {hour: "numeric", minute: "numeric", day: "numeric", month: "short", year: "numeric"})
diff --git a/build/static/chat-input.js b/build/static/chat-input.js
index 08ee236..ca01cc1 100644
--- a/build/static/chat-input.js
+++ b/build/static/chat-input.js
@@ -1,7 +1,7 @@
-import {q} from "./basic.js"
-import {store} from "./store/store.js"
-import * as lsm from "./lsm.js"
-import {chat} from "./chat.js"
+import {q} from "../static/basic.js?static=4212436742"
+import {store} from "../static/store/store.js?static=ce3066287b"
+import * as lsm from "../static/lsm.js?static=aed2c7ca35"
+import {chat} from "../static/chat.js?static=b01b3716ff"
const input = q("#c-chat-textarea")
diff --git a/build/static/chat.js b/build/static/chat.js
index 9958dc3..8bb324d 100644
--- a/build/static/chat.js
+++ b/build/static/chat.js
@@ -1,5 +1,5 @@
-import {ElemJS, q, ejs} from "./basic.js"
-import {store} from "./store/store.js"
+import {ElemJS, q, ejs} from "../static/basic.js?static=4212436742"
+import {store} from "../static/store/store.js?static=ce3066287b"
const chatMessages = q("#c-chat-messages")
diff --git a/build/static/groups.js b/build/static/groups.js
index 0f209a9..3500e27 100644
--- a/build/static/groups.js
+++ b/build/static/groups.js
@@ -1,4 +1,4 @@
-import {q} from "./basic.js"
+import {q} from "../static/basic.js?static=4212436742"
let state = "CLOSED"
diff --git a/build/static/room-picker.js b/build/static/room-picker.js
index e93f72d..75e6c0b 100644
--- a/build/static/room-picker.js
+++ b/build/static/room-picker.js
@@ -1,10 +1,10 @@
-import {q, ElemJS, ejs} from "./basic.js"
-import {store} from "./store/store.js"
-import {SubscribeMapList} from "./store/SubscribeMapList.js"
-import {SubscribeValue} from "./store/SubscribeValue.js"
-import {Timeline} from "./Timeline.js"
-import * as lsm from "./lsm.js"
-import {resolveMxc} from "./functions.js"
+import {q, ElemJS, ejs} from "../static/basic.js?static=4212436742"
+import {store} from "../static/store/store.js?static=ce3066287b"
+import {SubscribeMapList} from "../static/store/SubscribeMapList.js?static=b2732c5460"
+import {SubscribeValue} from "../static/store/SubscribeValue.js?static=215b6a5099"
+import {Timeline} from "../static/Timeline.js?static=1393b78916"
+import * as lsm from "../static/lsm.js?static=aed2c7ca35"
+import {resolveMxc} from "../static/functions.js?static=e3784c70ce"
class ActiveGroupMarker extends ElemJS {
constructor() {
diff --git a/build/static/store/SubscribeMapList.js b/build/static/store/SubscribeMapList.js
index b26d58c..189119c 100644
--- a/build/static/store/SubscribeMapList.js
+++ b/build/static/store/SubscribeMapList.js
@@ -1,5 +1,5 @@
-import {Subscribable} from "./Subscribable.js"
-import {SubscribeValue} from "./SubscribeValue.js"
+import {Subscribable} from "../../static/store/Subscribable.js?static=19b7e44aa6"
+import {SubscribeValue} from "../../static/store/SubscribeValue.js?static=215b6a5099"
class SubscribeMapList extends Subscribable {
constructor(inner) {
diff --git a/build/static/store/SubscribeSet.js b/build/static/store/SubscribeSet.js
index 2cbdaa3..e43128f 100644
--- a/build/static/store/SubscribeSet.js
+++ b/build/static/store/SubscribeSet.js
@@ -1,4 +1,4 @@
-import {Subscribable} from "./Subscribable.js"
+import {Subscribable} from "../../static/store/Subscribable.js?static=19b7e44aa6"
class SubscribeSet extends Subscribable {
constructor() {
diff --git a/build/static/store/SubscribeValue.js b/build/static/store/SubscribeValue.js
index 16e5b88..e8dceb6 100644
--- a/build/static/store/SubscribeValue.js
+++ b/build/static/store/SubscribeValue.js
@@ -1,4 +1,4 @@
-import {Subscribable} from "./Subscribable.js"
+import {Subscribable} from "../../static/store/Subscribable.js?static=19b7e44aa6"
class SubscribeValue extends Subscribable {
constructor() {
diff --git a/build/static/store/store.js b/build/static/store/store.js
index 716f23a..1450a68 100644
--- a/build/static/store/store.js
+++ b/build/static/store/store.js
@@ -1,7 +1,7 @@
-import {Subscribable} from "./Subscribable.js"
-import {SubscribeMapList} from "./SubscribeMapList.js"
-import {SubscribeSet} from "./SubscribeSet.js"
-import {SubscribeValue} from "./SubscribeValue.js"
+import {Subscribable} from "../../static/store/Subscribable.js?static=19b7e44aa6"
+import {SubscribeMapList} from "../../static/store/SubscribeMapList.js?static=b2732c5460"
+import {SubscribeSet} from "../../static/store/SubscribeSet.js?static=39a1c0a2a4"
+import {SubscribeValue} from "../../static/store/SubscribeValue.js?static=215b6a5099"
const store = {
groups: new SubscribeMapList(SubscribeValue),
diff --git a/build/static/sync/sync.js b/build/static/sync/sync.js
index 54c2652..3b6fc34 100644
--- a/build/static/sync/sync.js
+++ b/build/static/sync/sync.js
@@ -1,6 +1,6 @@
-import {store} from "../store/store.js"
-import * as lsm from "../lsm.js"
-import {resolveMxc} from "../functions.js"
+import {store} from "../../static/store/store.js?static=ce3066287b"
+import * as lsm from "../../static/lsm.js?static=aed2c7ca35"
+import {resolveMxc} from "../../static/functions.js?static=e3784c70ce"
let lastBatch = null
@@ -111,13 +111,13 @@ function syncLoop() {
{
id: "directs",
name: "Directs",
- icon: "/static/directs.svg",
+ icon: staticFiles.get("/assets/icons/directs.svg"),
order: -2
},
{
id: "channels",
name: "Channels",
- icon: "/static/channels.svg",
+ icon: staticFiles.get("/assets/icons/channels.svg"),
order: -1
}
].forEach(data => store.groups.askAdd(data.id, data))
diff --git a/src/home.pug b/src/home.pug
index ea11138..68bbd21 100644
--- a/src/home.pug
+++ b/src/home.pug
@@ -33,6 +33,11 @@ doctype html
html
head
meta(charset="utf-8")
+ // var static = !{JSON.stringify([...static.entries()].reduce((a, c) => (a[c[0]] = getRelative(c[1]), a), {}))}
+ script
+ | var staticFiles = new Map(
+ != JSON.stringify([...static.keys()].map(k => [k, getStatic(k)]))
+ | )
link(rel="stylesheet" type="text/css" href=getStatic("/sass/main.sass"))
script(type="module" src=getStatic("/js/groups.js"))
script(type="module" src=getStatic("/js/chat-input.js"))
diff --git a/src/js/Anchor.js b/src/js/Anchor.js
index c887510..2adbe5f 100644
--- a/src/js/Anchor.js
+++ b/src/js/Anchor.js
@@ -1,4 +1,4 @@
-import {ElemJS} from "./basic.js"
+import {ElemJS} from $to_relative "/js/basic.js"
class Anchor extends ElemJS {
constructor() {
diff --git a/src/js/Timeline.js b/src/js/Timeline.js
index 9917522..f6d7b3e 100644
--- a/src/js/Timeline.js
+++ b/src/js/Timeline.js
@@ -1,9 +1,9 @@
-import {ElemJS, ejs} from "./basic.js"
-import {Subscribable} from "./store/Subscribable.js"
-import {store} from "./store/store.js"
-import {Anchor} from "./Anchor.js"
-import * as lsm from "./lsm.js"
-import {resolveMxc} from "./functions.js"
+import {ElemJS, ejs} from $to_relative "/js/basic.js"
+import {Subscribable} from $to_relative "/js/store/Subscribable.js"
+import {store} from $to_relative "/js/store/store.js"
+import {Anchor} from $to_relative "/js/Anchor.js"
+import * as lsm from $to_relative "/js/lsm.js"
+import {resolveMxc} from $to_relative "/js/functions.js"
const dateFormatter = Intl.DateTimeFormat("default", {hour: "numeric", minute: "numeric", day: "numeric", month: "short", year: "numeric"})
diff --git a/src/js/chat-input.js b/src/js/chat-input.js
index 08ee236..de0eec7 100644
--- a/src/js/chat-input.js
+++ b/src/js/chat-input.js
@@ -1,7 +1,7 @@
-import {q} from "./basic.js"
-import {store} from "./store/store.js"
-import * as lsm from "./lsm.js"
-import {chat} from "./chat.js"
+import {q} from $to_relative "/js/basic.js"
+import {store} from $to_relative "/js/store/store.js"
+import * as lsm from $to_relative "/js/lsm.js"
+import {chat} from $to_relative "/js/chat.js"
const input = q("#c-chat-textarea")
diff --git a/src/js/chat.js b/src/js/chat.js
index 9958dc3..e3df0eb 100644
--- a/src/js/chat.js
+++ b/src/js/chat.js
@@ -1,5 +1,5 @@
-import {ElemJS, q, ejs} from "./basic.js"
-import {store} from "./store/store.js"
+import {ElemJS, q, ejs} from $to_relative "/js/basic.js"
+import {store} from $to_relative "/js/store/store.js"
const chatMessages = q("#c-chat-messages")
diff --git a/src/js/functions.js b/src/js/functions.js
index da5da62..299d8a9 100644
--- a/src/js/functions.js
+++ b/src/js/functions.js
@@ -1,4 +1,4 @@
-import * as lsm from "./lsm.js"
+import * as lsm from $to_relative "/js/lsm.js"
function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
diff --git a/src/js/groups.js b/src/js/groups.js
index 0f209a9..e49ade4 100644
--- a/src/js/groups.js
+++ b/src/js/groups.js
@@ -1,4 +1,4 @@
-import {q} from "./basic.js"
+import {q} from $to_relative "/js/basic.js"
let state = "CLOSED"
diff --git a/src/js/room-picker.js b/src/js/room-picker.js
index e93f72d..87e9320 100644
--- a/src/js/room-picker.js
+++ b/src/js/room-picker.js
@@ -1,10 +1,10 @@
-import {q, ElemJS, ejs} from "./basic.js"
-import {store} from "./store/store.js"
-import {SubscribeMapList} from "./store/SubscribeMapList.js"
-import {SubscribeValue} from "./store/SubscribeValue.js"
-import {Timeline} from "./Timeline.js"
-import * as lsm from "./lsm.js"
-import {resolveMxc} from "./functions.js"
+import {q, ElemJS, ejs} from $to_relative "/js/basic.js"
+import {store} from $to_relative "/js/store/store.js"
+import {SubscribeMapList} from $to_relative "/js/store/SubscribeMapList.js"
+import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js"
+import {Timeline} from $to_relative "/js/Timeline.js"
+import * as lsm from $to_relative "/js/lsm.js"
+import {resolveMxc} from $to_relative "/js/functions.js"
class ActiveGroupMarker extends ElemJS {
constructor() {
diff --git a/src/js/store/SubscribeMap.js b/src/js/store/SubscribeMap.js
index 562d70f..8b0dc0c 100644
--- a/src/js/store/SubscribeMap.js
+++ b/src/js/store/SubscribeMap.js
@@ -1,5 +1,5 @@
-import {Subscribable} from "./Subscribable.js"
-import {SubscribeValue} from "./SubscribeValue.js"
+import {Subscribable} from $to_relative "/js/store/Subscribable.js"
+import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js"
class SubscribeMap extends Subscribable {
constructor() {
diff --git a/src/js/store/SubscribeMapList.js b/src/js/store/SubscribeMapList.js
index b26d58c..1883303 100644
--- a/src/js/store/SubscribeMapList.js
+++ b/src/js/store/SubscribeMapList.js
@@ -1,5 +1,5 @@
-import {Subscribable} from "./Subscribable.js"
-import {SubscribeValue} from "./SubscribeValue.js"
+import {Subscribable} from $to_relative "/js/store/Subscribable.js"
+import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js"
class SubscribeMapList extends Subscribable {
constructor(inner) {
diff --git a/src/js/store/SubscribeSet.js b/src/js/store/SubscribeSet.js
index 2cbdaa3..789aaaf 100644
--- a/src/js/store/SubscribeSet.js
+++ b/src/js/store/SubscribeSet.js
@@ -1,4 +1,4 @@
-import {Subscribable} from "./Subscribable.js"
+import {Subscribable} from $to_relative "/js/store/Subscribable.js"
class SubscribeSet extends Subscribable {
constructor() {
diff --git a/src/js/store/SubscribeValue.js b/src/js/store/SubscribeValue.js
index 16e5b88..6657e27 100644
--- a/src/js/store/SubscribeValue.js
+++ b/src/js/store/SubscribeValue.js
@@ -1,4 +1,4 @@
-import {Subscribable} from "./Subscribable.js"
+import {Subscribable} from $to_relative "/js/store/Subscribable.js"
class SubscribeValue extends Subscribable {
constructor() {
diff --git a/src/js/store/store.js b/src/js/store/store.js
index 716f23a..1c0552d 100644
--- a/src/js/store/store.js
+++ b/src/js/store/store.js
@@ -1,7 +1,7 @@
-import {Subscribable} from "./Subscribable.js"
-import {SubscribeMapList} from "./SubscribeMapList.js"
-import {SubscribeSet} from "./SubscribeSet.js"
-import {SubscribeValue} from "./SubscribeValue.js"
+import {Subscribable} from $to_relative "/js/store/Subscribable.js"
+import {SubscribeMapList} from $to_relative "/js/store/SubscribeMapList.js"
+import {SubscribeSet} from $to_relative "/js/store/SubscribeSet.js"
+import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js"
const store = {
groups: new SubscribeMapList(SubscribeValue),
diff --git a/src/js/sync/sync.js b/src/js/sync/sync.js
index 54c2652..b374d62 100644
--- a/src/js/sync/sync.js
+++ b/src/js/sync/sync.js
@@ -1,6 +1,6 @@
-import {store} from "../store/store.js"
-import * as lsm from "../lsm.js"
-import {resolveMxc} from "../functions.js"
+import {store} from $to_relative "/js/store/store.js"
+import * as lsm from $to_relative "/js/lsm.js"
+import {resolveMxc} from $to_relative "/js/functions.js"
let lastBatch = null
@@ -111,13 +111,13 @@ function syncLoop() {
{
id: "directs",
name: "Directs",
- icon: "/static/directs.svg",
+ icon: staticFiles.get("/assets/icons/directs.svg"),
order: -2
},
{
id: "channels",
name: "Channels",
- icon: "/static/channels.svg",
+ icon: staticFiles.get("/assets/icons/channels.svg"),
order: -1
}
].forEach(data => store.groups.askAdd(data.id, data))