Merge pull request 'Bundle with browserify' (#19) from browserify into princess
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #19
This commit is contained in:
cadence 2020-10-26 09:33:51 +00:00
commit 5ab182e615
22 changed files with 1848 additions and 169 deletions

View file

@ -1,6 +1,6 @@
const pug = require("pug") const pug = require("pug")
const sass = require("sass") const sass = require("sass")
const fs = require("fs").promises const fs = require("fs")
const os = require("os") const os = require("os")
const crypto = require("crypto") const crypto = require("crypto")
const path = require("path") const path = require("path")
@ -9,6 +9,8 @@ const babel = require("@babel/core")
const fetch = require("node-fetch") const fetch = require("node-fetch")
const chalk = require("chalk") const chalk = require("chalk")
const hint = require("jshint").JSHINT const hint = require("jshint").JSHINT
const browserify = require("browserify")
const {Transform} = require("stream")
process.chdir(pj(__dirname, "src")) process.chdir(pj(__dirname, "src"))
@ -16,10 +18,10 @@ const buildDir = "../build"
const validationQueue = [] const validationQueue = []
const validationHost = os.hostname() === "future" ? "http://localhost:8888/" : "http://validator.w3.org/nu/" const validationHost = os.hostname() === "future" ? "http://localhost:8888/" : "http://validator.w3.org/nu/"
const static = new Map() const staticFiles = new Map()
const links = new Map() const links = new Map()
const sources = new Map() const sources = new Map()
const pugLocals = {static, links} const pugLocals = {static: staticFiles, links}
const spec = require("./spec.js") const spec = require("./spec.js")
@ -94,6 +96,7 @@ function runHint(filename, source) {
globals: ["console", "URLSearchParams", "staticFiles"], globals: ["console", "URLSearchParams", "staticFiles"],
browser: true, browser: true,
asi: true, asi: true,
node: true
}) })
const result = hint.data() const result = hint.data()
let problems = 0 let problems = 0
@ -125,26 +128,53 @@ function runHint(filename, source) {
} }
async function addFile(sourcePath, targetPath) { async function addFile(sourcePath, targetPath) {
const contents = await fs.readFile(pj(".", sourcePath), {encoding: null}) const contents = await fs.promises.readFile(pj(".", sourcePath), {encoding: null});
static.set(sourcePath, `${targetPath}?static=${hash(contents)}`) staticFiles.set(sourcePath, `${targetPath}?static=${hash(contents)}`)
fs.writeFile(pj(buildDir, targetPath), contents) await fs.promises.writeFile(pj(buildDir, targetPath), contents)
} }
async function loadJS(sourcePath, targetPath) { async function loadJS(sourcePath, targetPath) {
let content = await fs.readFile(pj(".", sourcePath), {encoding: "utf8"}) let content = await fs.promises.readFile(pj(".", sourcePath), {encoding: "utf8"})
sources.set(sourcePath, content) sources.set(sourcePath, content)
static.set(sourcePath, `${targetPath}?static=${hash(content)}`) staticFiles.set(sourcePath, `${targetPath}?static=${hash(content)}`)
} }
async function addJS(sourcePath, targetPath) { async function addJS(sourcePath, targetPath) {
let content = sources.get(sourcePath) 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) runHint(sourcePath, content)
fs.writeFile(pj(buildDir, targetPath), content) await fs.promises.writeFile(pj(buildDir, targetPath), content)
}
async function addBundle(sourcePath, targetPath) {
const content = await new Promise(resolve => {
browserify()
.add(pj(".", sourcePath))
.transform(file => {
let content = ""
const transform = new Transform({
transform(chunk, encoding, callback) {
content += chunk.toString()
callback(null, chunk)
}
})
transform.on("finish", () => {
const relativePath = path.relative(process.cwd(), file).replace(/^\/*/, "/")
runHint(relativePath, content)
})
return transform
})
.bundle((err, res) => {
if (err) {
delete err.stream
throw err // Quit; problem parsing file to bundle
}
resolve(res)
})
})
const writer = fs.promises.writeFile(pj(buildDir, targetPath), content)
staticFiles.set(sourcePath, `${targetPath}?static=${hash(content)}`)
runHint(sourcePath, content)
await writer
} }
async function addSass(sourcePath, targetPath) { async function addSass(sourcePath, targetPath) {
@ -158,7 +188,7 @@ async function addSass(sourcePath, targetPath) {
if (!(name instanceof sass.types.String)) { if (!(name instanceof sass.types.String)) {
throw "$name: expected a string" throw "$name: expected a string"
} }
const result = getRelative(targetPath, static.get(name.getValue())) const result = getRelative(targetPath, staticFiles.get(name.getValue()))
if (typeof result === "string") { if (typeof result === "string") {
return new sass.types.String(result) return new sass.types.String(result)
} else { } else {
@ -166,10 +196,10 @@ async function addSass(sourcePath, targetPath) {
} }
} }
} }
}).css }).css;
static.set(sourcePath, `${targetPath}?static=${hash(renderedCSS)}`) staticFiles.set(sourcePath, `${targetPath}?static=${hash(renderedCSS)}`)
validate(sourcePath, renderedCSS, "css") validate(sourcePath, renderedCSS, "css")
await fs.writeFile(pj(buildDir, targetPath), renderedCSS) await fs.promises.writeFile(pj(buildDir, targetPath), renderedCSS)
} }
async function addPug(sourcePath, targetPath) { async function addPug(sourcePath, targetPath) {
@ -177,10 +207,10 @@ async function addPug(sourcePath, targetPath) {
return getRelative(targetPath, staticTarget) return getRelative(targetPath, staticTarget)
} }
function getStatic(target) { function getStatic(target) {
return getRelativeHere(static.get(target)) return getRelativeHere(staticFiles.get(target))
} }
function getStaticName(target) { function getStaticName(target) {
return getRelativeHere(static.get(target)).replace(/\?.*$/, "") return getRelativeHere(staticFiles.get(target)).replace(/\?.*$/, "")
} }
function getLink(target) { function getLink(target) {
return getRelativeHere(links.get(target)) return getRelativeHere(links.get(target))
@ -188,11 +218,11 @@ async function addPug(sourcePath, targetPath) {
const renderedHTML = pug.compileFile(pj(".", sourcePath), {pretty: true})({getStatic, getStaticName, getLink, ...pugLocals}) const renderedHTML = pug.compileFile(pj(".", sourcePath), {pretty: true})({getStatic, getStaticName, getLink, ...pugLocals})
let renderedWithoutPHP = renderedHTML.replace(/<\?(?:php|=).*?\?>/gsm, "") let renderedWithoutPHP = renderedHTML.replace(/<\?(?:php|=).*?\?>/gsm, "")
validate(sourcePath, renderedWithoutPHP, "html") validate(sourcePath, renderedWithoutPHP, "html")
await fs.writeFile(pj(buildDir, targetPath), renderedHTML) await fs.promises.writeFile(pj(buildDir, targetPath), renderedHTML)
} }
async function addBabel(sourcePath, targetPath) { async function addBabel(sourcePath, targetPath) {
const originalCode = await fs.readFile(pj(".", sourcePath), "utf8") const originalCode = await fs.promises.readFile(pj(".", sourcePath), "utf8")
const compiled = babel.transformSync(originalCode, { const compiled = babel.transformSync(originalCode, {
sourceMaps: false, sourceMaps: false,
@ -213,14 +243,14 @@ async function addBabel(sourcePath, targetPath) {
} }
}) })
const filenameWithQuery = `${targetPath}?static=${hash(compiled.code)}` const filenameWithQuery = `${targetPath}?static=${hash(compiled.code)}`;
static.set(sourcePath, filenameWithQuery) staticFiles.set(sourcePath, filenameWithQuery)
await Promise.all([ await Promise.all([
fs.writeFile(pj(buildDir, targetPath), originalCode), fs.promises.writeFile(pj(buildDir, targetPath), originalCode),
fs.writeFile(pj(buildDir, minFilename), compiled.code), fs.promises.writeFile(pj(buildDir, minFilename), compiled.code),
fs.writeFile(pj(buildDir, mapFilename), JSON.stringify(compiled.map)) fs.promises.writeFile(pj(buildDir, mapFilename), JSON.stringify(compiled.map))
]) ])
} }
@ -241,7 +271,7 @@ async function addBabel(sourcePath, targetPath) {
// Stage 3: Create dirs // Stage 3: Create dirs
const dirs = [...new Set(spec.map(item => path.dirname(item.target))).values()] 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}))) await Promise.all(dirs.map(d => fs.promises.mkdir(pj(buildDir, d), {recursive: true})))
// Stage 4: Build // Stage 4: Build
for (const item of spec) { for (const item of spec) {
@ -255,6 +285,8 @@ async function addBabel(sourcePath, targetPath) {
await addBabel(item.source, item.target) await addBabel(item.source, item.target)
} else if (item.type === "pug") { } else if (item.type === "pug") {
await addPug(item.source, item.target) await addPug(item.source, item.target)
} else if (item.type === "bundle") {
await addBundle(item.source, item.target)
} else { } else {
throw new Error("Unknown item type: "+item.type) throw new Error("Unknown item type: "+item.type)
} }

1733
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,7 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.11.1", "@babel/core": "^7.11.1",
"@babel/preset-env": "^7.11.0", "@babel/preset-env": "^7.11.0",
"browserify": "^17.0.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"http-server": "^0.12.3", "http-server": "^0.12.3",
"jshint": "^2.12.0", "jshint": "^2.12.0",

87
spec.js
View file

@ -10,90 +10,15 @@ module.exports = [
target: "/static/whitney-400.woff", target: "/static/whitney-400.woff",
}, },
{ {
type: "js", type: "bundle",
source: "/js/main.js",
target: "/static/main.js",
},
{
type: "js",
source: "/js/basic.js",
target: "/static/basic.js",
},
{
type: "js",
source: "/js/groups.js",
target: "/static/groups.js",
},
{
type: "js",
source: "/js/chat-input.js",
target: "/static/chat-input.js",
},
{
type: "js",
source: "/js/room-picker.js",
target: "/static/room-picker.js",
},
{
type: "js",
source: "/js/store/store.js",
target: "/static/store/store.js",
},
{
type: "js",
source: "/js/store/Subscribable.js",
target: "/static/store/Subscribable.js",
},
{
type: "js",
source: "/js/store/SubscribeValue.js",
target: "/static/store/SubscribeValue.js",
},
{
type: "js",
source: "/js/store/SubscribeMapList.js",
target: "/static/store/SubscribeMapList.js",
},
{
type: "js",
source: "/js/store/SubscribeSet.js",
target: "/static/store/SubscribeSet.js",
},
{
type: "js",
source: "/js/sync/sync.js",
target: "/static/sync/sync.js",
},
{
type: "js",
source: "/js/lsm.js",
target: "/static/lsm.js",
},
{
type: "js",
source: "/js/Timeline.js",
target: "/static/Timeline.js",
},
{
type: "js",
source: "/js/Anchor.js",
target: "/static/Anchor.js",
},
{
type: "js",
source: "/js/chat.js",
target: "/static/chat.js",
},
{
type: "js",
source: "/js/functions.js",
target: "/static/functions.js",
},
{
type: "js",
source: "/js/login.js", source: "/js/login.js",
target: "/static/login.js", target: "/static/login.js",
}, },
{
type: "bundle",
source: "/js/main.js",
target: "/static/bundle.js"
},
{ {
type: "file", type: "file",
source: "/assets/fonts/whitney-500.woff", source: "/assets/fonts/whitney-500.woff",

View file

@ -1,4 +1,4 @@
import {ElemJS} from $to_relative "/js/basic.js" const {ElemJS} = require("./basic.js")
class Anchor extends ElemJS { class Anchor extends ElemJS {
constructor() { constructor() {
@ -12,4 +12,4 @@ class Anchor extends ElemJS {
} }
} }
export {Anchor} module.exports = {Anchor}

View file

@ -157,4 +157,4 @@ function ejs(tag) {
return new ElemJS(tag); return new ElemJS(tag);
} }
export {q, qa, ElemJS, ejs} module.exports = {q, qa, ElemJS, ejs}

View file

@ -1,7 +1,7 @@
import {q} from $to_relative "/js/basic.js" const {q} = require("./basic.js")
import {store} from $to_relative "/js/store/store.js" const {store} = require("./store/store.js")
import * as lsm from $to_relative "/js/lsm.js" const lsm = require("./lsm.js")
import {chat} from $to_relative "/js/chat.js" const {chat} = require("./chat.js")
const input = q("#c-chat-textarea") const input = q("#c-chat-textarea")

View file

@ -1,5 +1,5 @@
import {ElemJS, q, ejs} from $to_relative "/js/basic.js" const {ElemJS, q, ejs} = require("./basic.js")
import {store} from $to_relative "/js/store/store.js" const {store} = require("./store/store.js")
const chatMessages = q("#c-chat-messages") const chatMessages = q("#c-chat-messages")
@ -62,4 +62,4 @@ class Chat extends ElemJS {
const chat = new Chat() const chat = new Chat()
export {chat} module.exports = {chat}

View file

@ -1,4 +1,4 @@
import * as lsm from $to_relative "/js/lsm.js" const lsm = require("./lsm.js")
function resolveMxc(url, size, method) { function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1) const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
@ -9,4 +9,4 @@ function resolveMxc(url, size, method) {
} }
} }
export {resolveMxc} module.exports = {resolveMxc}

View file

@ -1,4 +1,4 @@
import {q} from $to_relative "/js/basic.js" const {q} = require("./basic.js")
let state = "CLOSED" let state = "CLOSED"

View file

@ -1,4 +1,4 @@
import {q, ElemJS, ejs} from $to_relative "/js/basic.js" const {q, ElemJS, ejs} = require("./basic.js")
const password = q("#password") const password = q("#password")
const homeserver = q("#homeserver") const homeserver = q("#homeserver")

View file

@ -8,4 +8,4 @@ function set(name, value) {
window.lsm = {get, set} window.lsm = {get, set}
export {get, set} module.exports = {get, set}

View file

@ -1,8 +1,8 @@
import $to_relative "/js/groups.js" const groups = require("./groups.js")
import $to_relative "/js/chat-input.js" const chat_input = require("./chat-input.js")
import $to_relative "/js/room-picker.js" const room_picker = require("./room-picker.js")
import $to_relative "/js/sync/sync.js" const sync = require("./sync/sync.js")
import $to_relative "/js/chat.js" const chat = require("./chat.js")
if (!localStorage.getItem("access_token")) { if (!localStorage.getItem("access_token")) {
location.assign("./login/") location.assign("./login/")

View file

@ -1,10 +1,10 @@
import {q, ElemJS, ejs} from $to_relative "/js/basic.js" const {q, ElemJS, ejs} = require("./basic.js")
import {store} from $to_relative "/js/store/store.js" const {store} = require("./store/store.js")
import {SubscribeMapList} from $to_relative "/js/store/SubscribeMapList.js" const {SubscribeMapList} = require("./store/subscribe_map_list.js")
import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js" const {SubscribeValue} = require("./store/subscribe_value.js")
import {Timeline} from $to_relative "/js/Timeline.js" const {Timeline} = require("./timeline.js")
import * as lsm from $to_relative "/js/lsm.js" const lsm = require("./lsm.js")
import {resolveMxc} from $to_relative "/js/functions.js" const {resolveMxc} = require("./functions.js")
class ActiveGroupMarker extends ElemJS { class ActiveGroupMarker extends ElemJS {
constructor() { constructor() {

View file

@ -1,7 +1,7 @@
import {Subscribable} from $to_relative "/js/store/Subscribable.js" const {Subscribable} = require("./subscribable.js")
import {SubscribeMapList} from $to_relative "/js/store/SubscribeMapList.js" const {SubscribeMapList} = require("./subscribe_map_list.js")
import {SubscribeSet} from $to_relative "/js/store/SubscribeSet.js" const {SubscribeSet} = require("./subscribe_set.js")
import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js" const {SubscribeValue} = require("./subscribe_value.js")
const store = { const store = {
groups: new SubscribeMapList(SubscribeValue), groups: new SubscribeMapList(SubscribeValue),
@ -14,4 +14,4 @@ const store = {
window.store = store window.store = store
export {store} module.exports = {store}

View file

@ -35,4 +35,4 @@ class Subscribable {
} }
} }
export {Subscribable} module.exports = {Subscribable}

View file

@ -1,5 +1,5 @@
import {Subscribable} from $to_relative "/js/store/Subscribable.js" const {Subscribable} = require("./subscribable.js")
import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js" const {SubscribeValue} = require("./subscribe_value.js")
class SubscribeMap extends Subscribable { class SubscribeMap extends Subscribable {
constructor() { constructor() {
@ -38,4 +38,4 @@ class SubscribeMap extends Subscribable {
} }
} }
export {SubscribeMap} module.exports = {SubscribeMap}

View file

@ -1,5 +1,5 @@
import {Subscribable} from $to_relative "/js/store/Subscribable.js" const {Subscribable} = require("./subscribable.js")
import {SubscribeValue} from $to_relative "/js/store/SubscribeValue.js" const {SubscribeValue} = require("./subscribe_value.js")
class SubscribeMapList extends Subscribable { class SubscribeMapList extends Subscribable {
constructor(inner) { constructor(inner) {
@ -83,4 +83,4 @@ class SubscribeMapList extends Subscribable {
} }
} }
export {SubscribeMapList} module.exports = {SubscribeMapList}

View file

@ -1,4 +1,4 @@
import {Subscribable} from $to_relative "/js/store/Subscribable.js" const {Subscribable} = require("./subscribable.js")
class SubscribeSet extends Subscribable { class SubscribeSet extends Subscribable {
constructor() { constructor() {
@ -47,4 +47,4 @@ class SubscribeSet extends Subscribable {
} }
} }
export {SubscribeSet} module.exports = {SubscribeSet}

View file

@ -1,4 +1,4 @@
import {Subscribable} from $to_relative "/js/store/Subscribable.js" const {Subscribable} = require("./subscribable.js")
class SubscribeValue extends Subscribable { class SubscribeValue extends Subscribable {
constructor() { constructor() {
@ -44,4 +44,4 @@ class SubscribeValue extends Subscribable {
} }
} }
export {SubscribeValue} module.exports = {SubscribeValue}

View file

@ -1,6 +1,6 @@
import {store} from $to_relative "/js/store/store.js" const {store} = require("../store/store.js")
import * as lsm from $to_relative "/js/lsm.js" const lsm = require("../lsm.js")
import {resolveMxc} from $to_relative "/js/functions.js" const {resolveMxc} = require("../functions.js")
let lastBatch = null let lastBatch = null

View file

@ -1,9 +1,9 @@
import {ElemJS, ejs} from $to_relative "/js/basic.js" const {ElemJS, ejs} = require("./basic.js")
import {Subscribable} from $to_relative "/js/store/Subscribable.js" const {Subscribable} = require("./store/subscribable.js")
import {store} from $to_relative "/js/store/store.js" const {store} = require("./store/store.js")
import {Anchor} from $to_relative "/js/Anchor.js" const {Anchor} = require("./anchor.js")
import * as lsm from $to_relative "/js/lsm.js" const lsm = require("./lsm.js")
import {resolveMxc} from $to_relative "/js/functions.js" const {resolveMxc} = require("./functions.js")
let debug = false let debug = false
@ -413,4 +413,4 @@ class Timeline extends Subscribable {
*/ */
} }
export {Timeline} module.exports = {Timeline}