fix: build inline script using Rollup (#761)

* fix: build inline script using Rollup

This reduces code duplication and allows the theme engine to work the
same without modifying the code in two places. It does extra extra deps,
but I tried to keep them to a minimum.

* change code comment

* remove unnecessary constant
This commit is contained in:
Nolan Lawson 2018-12-08 11:21:54 -08:00 committed by GitHub
parent 34cfaf27b3
commit 7876f82871
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 424 additions and 83 deletions

1
.gitignore vendored
View file

@ -8,3 +8,4 @@ assets/*.css
mastodon.log mastodon.log
assets/robots.txt assets/robots.txt
/inline-script-checksum.json /inline-script-checksum.json
/assets/inline-script.js.map

View file

@ -4,20 +4,41 @@ import crypto from 'crypto'
import fs from 'fs' import fs from 'fs'
import pify from 'pify' import pify from 'pify'
import path from 'path' import path from 'path'
import { themes } from '../routes/_static/themes.js' import { rollup } from 'rollup'
import { fromPairs } from 'lodash-es' import { terser } from 'rollup-plugin-terser'
import replace from 'rollup-plugin-replace'
import fromPairs from 'lodash-es/fromPairs'
import { themes } from '../routes/_static/themes'
const readFile = pify(fs.readFile.bind(fs)) const readFile = pify(fs.readFile.bind(fs))
const writeFile = pify(fs.writeFile.bind(fs)) const writeFile = pify(fs.writeFile.bind(fs))
const themeColors = fromPairs(themes.map(_ => ([_.name, _.color])))
async function main () { async function main () {
let inlineScriptPath = path.join(__dirname, '../inline-script.js') let inlineScriptPath = path.join(__dirname, '../inline-script.js')
let code = await readFile(inlineScriptPath, 'utf8')
code = code.replace('process.env.THEME_COLORS', JSON.stringify(fromPairs(themes.map(_ => ([_.name, _.color]))))) let bundle = await rollup({
code = `(function () {'use strict'\n${code}})()` input: inlineScriptPath,
plugins: [
replace({
'process.browser': true,
'process.env.THEME_COLORS': JSON.stringify(themeColors)
}),
terser({
mangle: true,
compress: true
})
]
})
let { code, map } = await bundle.generate({
format: 'iife',
sourcemap: true
})
let checksum = crypto.createHash('sha256').update(code).digest('base64') let fullCode = `${code}\n//# sourceMappingURL=inline-script.js.map`
let checksum = crypto.createHash('sha256').update(fullCode).digest('base64')
let checksumFilepath = path.join(__dirname, '../inline-script-checksum.json') let checksumFilepath = path.join(__dirname, '../inline-script-checksum.json')
await writeFile(checksumFilepath, JSON.stringify({ checksum }), 'utf8') await writeFile(checksumFilepath, JSON.stringify({ checksum }), 'utf8')
@ -26,9 +47,11 @@ async function main () {
let html2xxFile = await readFile(html2xxFilepath, 'utf8') let html2xxFile = await readFile(html2xxFilepath, 'utf8')
html2xxFile = html2xxFile.replace( html2xxFile = html2xxFile.replace(
/<!-- insert inline script here -->[\s\S]+<!-- end insert inline script here -->/, /<!-- insert inline script here -->[\s\S]+<!-- end insert inline script here -->/,
'<!-- insert inline script here --><script>' + code + '</script><!-- end insert inline script here -->' '<!-- insert inline script here --><script>' + fullCode + '</script><!-- end insert inline script here -->'
) )
await writeFile(html2xxFilepath, html2xxFile, 'utf8') await writeFile(html2xxFilepath, html2xxFile, 'utf8')
await writeFile(path.resolve(__dirname, '../assets/inline-script.js.map'), map.toString(), 'utf8')
} }
main().catch(err => { main().catch(err => {

View file

@ -1,30 +1,19 @@
// For perf reasons, this script is run inline to quickly set certain styles. // For perf reasons, this script is run inline to quickly set certain styles.
// To allow CSP to work correctly, we also calculate a sha256 hash during // To allow CSP to work correctly, we also calculate a sha256 hash during
// the build process and write it to inline-script-checksum.json. // the build process and write it to inline-script-checksum.json.
import { testHasLocalStorageOnce } from './routes/_utils/testStorage'
import { switchToTheme } from './routes/_utils/themeEngine'
window.__themeColors = process.env.THEME_COLORS window.__themeColors = process.env.THEME_COLORS
const hasLocalStorage = (() => { const hasLocalStorage = testHasLocalStorageOnce()
try {
// iOS safari throws here if cookies are disabled
let unused = localStorage.length // eslint-disable-line
return true
} catch (e) {
return false
}
})()
if (hasLocalStorage && localStorage.store_currentInstance && localStorage.store_instanceThemes) { if (hasLocalStorage && localStorage.store_currentInstance && localStorage.store_instanceThemes) {
let safeParse = (str) => str === 'undefined' ? undefined : JSON.parse(str) let safeParse = (str) => str === 'undefined' ? undefined : JSON.parse(str)
let theme = safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)] let theme = safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)]
if (theme && theme !== 'default') { if (theme && theme !== 'default') {
let link = document.createElement('link') switchToTheme(theme)
link.rel = 'stylesheet'
link.href = `/theme-${theme}.css`
// inserting before the offline <style> ensures that the offline style wins when offline
document.head.insertBefore(link, document.getElementById('theOfflineStyle'))
if (window.__themeColors[theme]) {
document.getElementById('theThemeColor').content = window.__themeColors[theme]
}
} }
} }

380
package-lock.json generated
View file

@ -4,6 +4,57 @@
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@babel/code-frame": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
"integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
"requires": {
"@babel/highlight": "^7.0.0"
}
},
"@babel/highlight": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
"integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
"requires": {
"chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^4.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"@gamestdio/websocket": { "@gamestdio/websocket": {
"version": "0.2.8", "version": "0.2.8",
"resolved": "https://registry.npmjs.org/@gamestdio/websocket/-/websocket-0.2.8.tgz", "resolved": "https://registry.npmjs.org/@gamestdio/websocket/-/websocket-0.2.8.tgz",
@ -15,6 +66,11 @@
"integrity": "sha1-4ByfjIXKg7YQMgxiJYsMkCat4Pc=", "integrity": "sha1-4ByfjIXKg7YQMgxiJYsMkCat4Pc=",
"dev": true "dev": true
}, },
"@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
},
"@types/lodash": { "@types/lodash": {
"version": "4.14.118", "version": "4.14.118",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.118.tgz", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.118.tgz",
@ -4230,11 +4286,15 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
}, },
"estree-walker": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz",
"integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig=="
},
"esutils": { "esutils": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
"dev": true
}, },
"etag": { "etag": {
"version": "1.8.1", "version": "1.8.1",
@ -4322,6 +4382,44 @@
} }
} }
}, },
"expand-range": {
"version": "1.8.2",
"resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
"requires": {
"fill-range": "^2.1.0"
},
"dependencies": {
"fill-range": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
"integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
"requires": {
"is-number": "^2.1.0",
"isobject": "^2.0.0",
"randomatic": "^3.0.0",
"repeat-element": "^1.1.2",
"repeat-string": "^1.5.2"
}
},
"is-number": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
"requires": {
"kind-of": "^3.0.2"
}
},
"isobject": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
"requires": {
"isarray": "1.0.0"
}
}
}
},
"expect-ct": { "expect-ct": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.1.1.tgz", "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.1.1.tgz",
@ -4561,6 +4659,11 @@
"resolved": "https://registry.npmjs.org/file-error/-/file-error-0.10.2.tgz", "resolved": "https://registry.npmjs.org/file-error/-/file-error-0.10.2.tgz",
"integrity": "sha1-ljtIuSc7PUuEtADuVxvHixc5cko=" "integrity": "sha1-ljtIuSc7PUuEtADuVxvHixc5cko="
}, },
"filename-regex": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="
},
"filereader": { "filereader": {
"version": "0.10.3", "version": "0.10.3",
"resolved": "https://registry.npmjs.org/filereader/-/filereader-0.10.3.tgz", "resolved": "https://registry.npmjs.org/filereader/-/filereader-0.10.3.tgz",
@ -4755,6 +4858,14 @@
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
}, },
"for-own": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
"integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
"requires": {
"for-in": "^1.0.1"
}
},
"foreach": { "foreach": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
@ -4947,6 +5058,38 @@
"path-is-absolute": "^1.0.0" "path-is-absolute": "^1.0.0"
} }
}, },
"glob-base": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
"integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
"requires": {
"glob-parent": "^2.0.0",
"is-glob": "^2.0.0"
},
"dependencies": {
"glob-parent": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
"integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
"requires": {
"is-glob": "^2.0.0"
}
},
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
"requires": {
"is-extglob": "^1.0.0"
}
}
}
},
"glob-parent": { "glob-parent": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@ -5725,6 +5868,19 @@
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
}, },
"is-dotfile": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
"integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="
},
"is-equal-shallow": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
"integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
"requires": {
"is-primitive": "^2.0.0"
}
},
"is-es2016-keyword": { "is-es2016-keyword": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz",
@ -5825,6 +5981,16 @@
"isobject": "^3.0.1" "isobject": "^3.0.1"
} }
}, },
"is-posix-bracket": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
"integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="
},
"is-primitive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
"integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
},
"is-promise": { "is-promise": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
@ -5898,6 +6064,14 @@
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
}, },
"jest-worker": {
"version": "23.2.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz",
"integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=",
"requires": {
"merge-stream": "^1.0.1"
}
},
"js-base64": { "js-base64": {
"version": "2.4.9", "version": "2.4.9",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz",
@ -6263,6 +6437,14 @@
"yallist": "^2.1.2" "yallist": "^2.1.2"
} }
}, },
"magic-string": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz",
"integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==",
"requires": {
"sourcemap-codec": "^1.4.1"
}
},
"make-dir": { "make-dir": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
@ -6311,6 +6493,11 @@
"escape-string-regexp": "^1.0.5" "escape-string-regexp": "^1.0.5"
} }
}, },
"math-random": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
"integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w="
},
"md5.js": { "md5.js": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
@ -6377,7 +6564,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
"integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
"dev": true,
"requires": { "requires": {
"readable-stream": "^2.0.1" "readable-stream": "^2.0.1"
} }
@ -7042,6 +7228,15 @@
"es-abstract": "^1.5.1" "es-abstract": "^1.5.1"
} }
}, },
"object.omit": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
"integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
"requires": {
"for-own": "^0.1.4",
"is-extendable": "^0.1.1"
}
},
"object.pick": { "object.pick": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@ -7252,6 +7447,32 @@
"pbkdf2": "^3.0.3" "pbkdf2": "^3.0.3"
} }
}, },
"parse-glob": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
"integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
"requires": {
"glob-base": "^0.3.0",
"is-dotfile": "^1.0.0",
"is-extglob": "^1.0.0",
"is-glob": "^2.0.0"
},
"dependencies": {
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
"requires": {
"is-extglob": "^1.0.0"
}
}
}
},
"parse-json": { "parse-json": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@ -8045,6 +8266,11 @@
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
"dev": true "dev": true
}, },
"preserve": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
},
"private": { "private": {
"version": "0.1.8", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@ -8196,6 +8422,28 @@
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-2.0.0.tgz", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-2.0.0.tgz",
"integrity": "sha512-DqOtZziv7lDjEyuqyVQacRciAwMCEjTNrLYCHYEIIgjcE/tLEpBF82hiDIwCjRnEL9/hY2GJxA0T8ZvYvVVSSA==" "integrity": "sha512-DqOtZziv7lDjEyuqyVQacRciAwMCEjTNrLYCHYEIIgjcE/tLEpBF82hiDIwCjRnEL9/hY2GJxA0T8ZvYvVVSSA=="
}, },
"randomatic": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
"integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
"requires": {
"is-number": "^4.0.0",
"kind-of": "^6.0.0",
"math-random": "^1.0.1"
},
"dependencies": {
"is-number": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
"integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ=="
},
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
}
}
},
"randombytes": { "randombytes": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
@ -8409,6 +8657,14 @@
"private": "^0.1.6" "private": "^0.1.6"
} }
}, },
"regex-cache": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
"integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
"requires": {
"is-equal-shallow": "^0.1.3"
}
},
"regex-not": { "regex-not": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
@ -8642,6 +8898,119 @@
"inherits": "^2.0.1" "inherits": "^2.0.1"
} }
}, },
"rollup": {
"version": "0.67.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-0.67.4.tgz",
"integrity": "sha512-AVuP73mkb4BBMUmksQ3Jw0jTrBTU1i7rLiUYjFxLZGb3xiFmtVEg40oByphkZAsiL0bJC3hRAJUQos/e5EBd+w==",
"requires": {
"@types/estree": "0.0.39",
"@types/node": "*"
}
},
"rollup-plugin-replace": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.1.0.tgz",
"integrity": "sha512-SxrAIgpH/B5/W4SeULgreOemxcpEgKs2gcD42zXw50bhqGWmcnlXneVInQpAqzA/cIly4bJrOpeelmB9p4YXSQ==",
"requires": {
"magic-string": "^0.25.1",
"minimatch": "^3.0.2",
"rollup-pluginutils": "^2.0.1"
}
},
"rollup-plugin-terser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-3.0.0.tgz",
"integrity": "sha512-Ed9zRD7OoCBnh0XGlEAJle5TCUsFXMLClwKzZWnS1zbNO4MelHjfCSdFZxCAdH70M40nhZ1nRrY2GZQJhSMcjA==",
"requires": {
"@babel/code-frame": "^7.0.0",
"jest-worker": "^23.2.0",
"serialize-javascript": "^1.5.0",
"terser": "^3.8.2"
}
},
"rollup-pluginutils": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz",
"integrity": "sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA==",
"requires": {
"estree-walker": "^0.5.2",
"micromatch": "^2.3.11"
},
"dependencies": {
"arr-diff": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
"integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
"requires": {
"arr-flatten": "^1.0.1"
}
},
"array-unique": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
},
"braces": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
"integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
"requires": {
"expand-range": "^1.8.1",
"preserve": "^0.2.0",
"repeat-element": "^1.1.2"
}
},
"expand-brackets": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
"integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
"requires": {
"is-posix-bracket": "^0.1.0"
}
},
"extglob": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
"integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
"requires": {
"is-extglob": "^1.0.0"
}
},
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
"requires": {
"is-extglob": "^1.0.0"
}
},
"micromatch": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
"integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
"requires": {
"arr-diff": "^2.0.0",
"array-unique": "^0.2.1",
"braces": "^1.8.2",
"expand-brackets": "^0.1.4",
"extglob": "^0.3.1",
"filename-regex": "^2.0.0",
"is-extglob": "^1.0.0",
"is-glob": "^2.0.1",
"kind-of": "^3.0.2",
"normalize-path": "^2.0.1",
"object.omit": "^2.0.0",
"parse-glob": "^3.0.4",
"regex-cache": "^0.4.2"
}
}
}
},
"run-async": { "run-async": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
@ -9082,6 +9451,11 @@
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
}, },
"sourcemap-codec": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz",
"integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg=="
},
"spawn-args": { "spawn-args": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/spawn-args/-/spawn-args-0.2.0.tgz", "resolved": "https://registry.npmjs.org/spawn-args/-/spawn-args-0.2.0.tgz",

View file

@ -87,6 +87,9 @@
"pify": "^4.0.1", "pify": "^4.0.1",
"quick-lru": "^2.0.0", "quick-lru": "^2.0.0",
"requestidlecallback": "^0.3.0", "requestidlecallback": "^0.3.0",
"rollup": "^0.67.4",
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-terser": "^3.0.0",
"sapper": "github:nolanlawson/sapper#for-pinafore-9", "sapper": "github:nolanlawson/sapper#for-pinafore-9",
"serve-static": "^1.13.2", "serve-static": "^1.13.2",
"stringz": "^1.0.0", "stringz": "^1.0.0",

View file

@ -5,7 +5,7 @@ import { thunk } from './thunk'
const testKey = '__test__' const testKey = '__test__'
export const testHasLocalStorage = thunk(() => { export const testHasLocalStorageOnce = () => {
try { try {
localStorage.setItem(testKey, testKey) localStorage.setItem(testKey, testKey)
if (!localStorage.length || localStorage.getItem(testKey) !== testKey) { if (!localStorage.length || localStorage.getItem(testKey) !== testKey) {
@ -16,7 +16,9 @@ export const testHasLocalStorage = thunk(() => {
return false return false
} }
return true return true
}) }
export const testHasLocalStorage = thunk(testHasLocalStorageOnce)
export const testHasIndexedDB = thunk(async () => { export const testHasIndexedDB = thunk(async () => {
if (typeof indexedDB === 'undefined') { if (typeof indexedDB === 'undefined') {

View file

@ -46,61 +46,9 @@ html{scrollbar-face-color:var(--scrollbar-face-color);scrollbar-track-color:var(
</head> </head>
<body> <body>
<!-- auto-generated w/ build-inline-script.js --> <!-- auto-generated w/ build-inline-script.js -->
<!-- insert inline script here --><script>(function () {'use strict' <!-- insert inline script here --><script>!function(){"use strict";let e=document.getElementById("theThemeColor"),t=document.getElementById("theOfflineStyle");function o(){return document.head.querySelector('link[rel=stylesheet][href^="/theme-"]')}window.__themeColors={default:"royalblue",scarlet:"#e04e41",seafoam:"#177380",hotpants:"hotpink",oaken:"saddlebrown",majesty:"blueviolet",gecko:"#4ab92f",ozark:"#5263af",cobalt:"#08439b",sorcery:"#ae91e8",punk:"#e04e41",riot:"hotpink",hacker:"#4ab92f",pitchblack:"#000"};const n=(()=>{try{if(localStorage.setItem("__test__","__test__"),!localStorage.length||"__test__"!==localStorage.getItem("__test__"))return!1;localStorage.removeItem("__test__")}catch(e){return!1}return!0})();if(n&&localStorage.store_currentInstance&&localStorage.store_instanceThemes){let n=e=>"undefined"===e?void 0:JSON.parse(e),r=n(localStorage.store_instanceThemes)[n(localStorage.store_currentInstance)];r&&"default"!==r&&function(n){let r=window.__themeColors[n];e.content=r||window.__themeColors.default,"default"!==n?function(e){let n=o(),r=document.createElement("link");r.rel="stylesheet",r.href=e,r.addEventListener("load",function e(){r.removeEventListener("load",e),n&&document.head.removeChild(n)}),document.head.insertBefore(r,t)}(`/theme-${n}.css`):function(){let e=o();e&&document.head.removeChild(e)}()}(r)}if(!n||!localStorage.store_currentInstance){let e=document.createElement("style");e.textContent=".hidden-from-ssr { opacity: 1 !important; }",document.head.appendChild(e)}if(n&&"true"===localStorage.store_disableCustomScrollbars){document.getElementById("theScrollbarStyle").setAttribute("media","only x")}/mac/i.test(navigator.platform)&&document.documentElement.style.setProperty("--scrollbar-border-radius","50px"),/iP(?:hone|ad|od)/.test(navigator.userAgent)&&document.head.removeChild(document.getElementById("theManifest"))}();
// For perf reasons, this script is run inline to quickly set certain styles.
// To allow CSP to work correctly, we also calculate a sha256 hash during
// the build process and write it to inline-script-checksum.json.
window.__themeColors = {"default":"royalblue","scarlet":"#e04e41","seafoam":"#177380","hotpants":"hotpink","oaken":"saddlebrown","majesty":"blueviolet","gecko":"#4ab92f","ozark":"#5263af","cobalt":"#08439b","sorcery":"#ae91e8","punk":"#e04e41","riot":"hotpink","hacker":"#4ab92f","pitchblack":"#000"}
const hasLocalStorage = (() => { //# sourceMappingURL=inline-script.js.map</script><!-- end insert inline script here -->
try {
// iOS safari throws here if cookies are disabled
let unused = localStorage.length // eslint-disable-line
return true
} catch (e) {
return false
}
})()
if (hasLocalStorage && localStorage.store_currentInstance && localStorage.store_instanceThemes) {
let safeParse = (str) => str === 'undefined' ? undefined : JSON.parse(str)
let theme = safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)]
if (theme && theme !== 'default') {
let link = document.createElement('link')
link.rel = 'stylesheet'
link.href = `/theme-${theme}.css`
// inserting before the offline <style> ensures that the offline style wins when offline
document.head.insertBefore(link, document.getElementById('theOfflineStyle'))
if (window.__themeColors[theme]) {
document.getElementById('theThemeColor').content = window.__themeColors[theme]
}
}
}
if (!hasLocalStorage || !localStorage.store_currentInstance) {
// if not logged in, show all these 'hidden-from-ssr' elements
let style = document.createElement('style')
style.textContent = '.hidden-from-ssr { opacity: 1 !important; }'
document.head.appendChild(style)
}
if (hasLocalStorage && localStorage.store_disableCustomScrollbars === 'true') {
// if user has disabled custom scrollbars, remove this style
let theScrollbarStyle = document.getElementById('theScrollbarStyle')
theScrollbarStyle.setAttribute('media', 'only x') // disables the style
}
// hack to make the scrollbars rounded only on macOS
if (/mac/i.test(navigator.platform)) {
document.documentElement.style.setProperty('--scrollbar-border-radius', '50px')
}
// TODO: remove this hack when Safari works with cross-origin window.open()
// in a PWA: https://github.com/nolanlawson/pinafore/issues/45
if (/iP(?:hone|ad|od)/.test(navigator.userAgent)) {
document.head.removeChild(document.getElementById('theManifest'))
}
})()</script><!-- end insert inline script here -->
<svg xmlns="http://www.w3.org/2000/svg" style="display:none;"> <svg xmlns="http://www.w3.org/2000/svg" style="display:none;">
<!-- auto-generated w/ build-svg.js --> <!-- auto-generated w/ build-svg.js -->
<!-- insert svg here --><svg xmlns="http://www.w3.org/2000/svg" style="display:none;"> <!-- insert svg here --><svg xmlns="http://www.w3.org/2000/svg" style="display:none;">

View file

@ -6,6 +6,7 @@ const WEBPACK_ASSETS = `webpack_assets_${timestamp}`
const assets = __assets__ const assets = __assets__
.map(file => file.startsWith('/') ? file : `/${file}`) .map(file => file.startsWith('/') ? file : `/${file}`)
.filter(filename => !filename.startsWith('/apple-icon')) .filter(filename => !filename.startsWith('/apple-icon'))
.filter(filename => !filename.endsWith('.map'))
.concat(['/index.html']) .concat(['/index.html'])
// `shell` is an array of all the files generated by webpack // `shell` is an array of all the files generated by webpack