fix: update Sapper to latest (#775)

* fix: update to latest sapper

fixes #416

* fix error and debug pages

* requestIdleCallback makes column switching feel way nicer than double rAF

* add export feature

* add better csp info

* workaround for sapper sub-page issue

* clarify in readme about exporting

* fix now config

* switch from rIC to triple raf

* style-loader is no longer used

* update theming guide
pull/778/head
Nolan Lawson 2018-12-11 07:31:48 -08:00 zatwierdzone przez GitHub
rodzic 4d3a2ded2a
commit 4bd181d3cc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
415 zmienionych plików z 697 dodań i 1325 usunięć

9
.gitignore vendored
Wyświetl plik

@ -1,11 +1,14 @@
.DS_Store
node_modules
.sapper
__sapper__
yarn.lock
templates/.*
assets/*.css
static/*.css
/mastodon
mastodon.log
assets/robots.txt
static/robots.txt
/inline-script-checksum.json
/assets/inline-script.js.map
/static/inline-script.js.map
/templates/.*
/src/manifest/

Wyświetl plik

@ -76,6 +76,16 @@ To keep your version of Pinafore up to date, you can use `git` to check out the
git checkout $(git tag -l | sort -Vr | head -n 1)
### Exporting
You can export Pinafore as a static site. Run:
npm run export
Static files will be written to `__sapper__/export`.
Be sure to add the [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) header printed out in the console to
your server config!
## Developing and testing
See [CONTRIBUTING.md](https://github.com/nolanlawson/pinafore/blob/master/CONTRIBUTING.md) for

Wyświetl plik

@ -8,7 +8,7 @@ import { rollup } from 'rollup'
import { terser } from 'rollup-plugin-terser'
import replace from 'rollup-plugin-replace'
import fromPairs from 'lodash-es/fromPairs'
import { themes } from '../routes/_static/themes'
import { themes } from '../src/routes/_static/themes'
const readFile = pify(fs.readFile.bind(fs))
const writeFile = pify(fs.writeFile.bind(fs))
@ -36,22 +36,22 @@ async function main () {
sourcemap: true
})
let fullCode = `${code}\n//# sourceMappingURL=inline-script.js.map`
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')
await writeFile(checksumFilepath, JSON.stringify({ checksum }), 'utf8')
let html2xxFilepath = path.join(__dirname, '../templates/2xx.html')
let html2xxFile = await readFile(html2xxFilepath, 'utf8')
html2xxFile = html2xxFile.replace(
let htmlTemplateFilepath = path.join(__dirname, '../src/template.html')
let htmlTemplateFile = await readFile(htmlTemplateFilepath, 'utf8')
htmlTemplateFile = htmlTemplateFile.replace(
/<!-- insert inline script here -->[\s\S]+<!-- end insert inline script here -->/,
'<!-- insert inline script here --><script>' + fullCode + '</script><!-- end insert inline script here -->'
)
await writeFile(html2xxFilepath, html2xxFile, 'utf8')
await writeFile(htmlTemplateFilepath, htmlTemplateFile, 'utf8')
await writeFile(path.resolve(__dirname, '../assets/inline-script.js.map'), map.toString(), 'utf8')
await writeFile(path.resolve(__dirname, '../static/inline-script.js.map'), map.toString(), 'utf8')
}
main().catch(err => {

Wyświetl plik

@ -16,10 +16,10 @@ const globalScss = path.join(__dirname, '../scss/global.scss')
const defaultThemeScss = path.join(__dirname, '../scss/themes/_default.scss')
const offlineThemeScss = path.join(__dirname, '../scss/themes/_offline.scss')
const customScrollbarScss = path.join(__dirname, '../scss/custom-scrollbars.scss')
const html2xxFile = path.join(__dirname, '../templates/2xx.html')
const htmlTemplateFile = path.join(__dirname, '../src/template.html')
const scssDir = path.join(__dirname, '../scss')
const themesScssDir = path.join(__dirname, '../scss/themes')
const assetsDir = path.join(__dirname, '../assets')
const assetsDir = path.join(__dirname, '../static')
function doWatch () {
let start = now()
@ -44,7 +44,7 @@ async function compileGlobalSass () {
let offlineStyle = (await renderCss(offlineThemeScss))
let scrollbarStyle = (await renderCss(customScrollbarScss))
let html = await readFile(html2xxFile, 'utf8')
let html = await readFile(htmlTemplateFile, 'utf8')
html = html.replace(/<!-- begin inline CSS -->[\s\S]+<!-- end inline CSS -->/,
`<!-- begin inline CSS -->\n` +
`<style>\n${mainStyle}</style>\n` +
@ -53,7 +53,7 @@ async function compileGlobalSass () {
`<!-- end inline CSS -->`
)
await writeFile(html2xxFile, html, 'utf8')
await writeFile(htmlTemplateFile, html, 'utf8')
}
async function compileThemesSass () {

Wyświetl plik

@ -28,13 +28,13 @@ async function main () {
result = `<svg xmlns="http://www.w3.org/2000/svg" style="display:none;">\n${result}\n</svg>`
let html2xxFilepath = path.join(__dirname, '../templates/2xx.html')
let html2xxFile = await readFile(html2xxFilepath, 'utf8')
html2xxFile = html2xxFile.replace(
let htmlTemplateFilepath = path.join(__dirname, '../src/template.html')
let htmlTemplateFile = await readFile(htmlTemplateFilepath, 'utf8')
htmlTemplateFile = htmlTemplateFile.replace(
/<!-- insert svg here -->[\s\S]+<!-- end insert svg here -->/,
'<!-- insert svg here -->' + result + '<!-- end insert svg here -->'
)
await writeFile(html2xxFilepath, html2xxFile, 'utf8')
await writeFile(htmlTemplateFilepath, htmlTemplateFile, 'utf8')
}
main().catch(err => {

Wyświetl plik

@ -7,9 +7,9 @@ PATH="$PATH:./node_modules/.bin"
# set up robots.txt
if [[ "$DEPLOY_TYPE" == "dev" ]]; then
printf 'User-agent: *\nDisallow: /' > assets/robots.txt
printf 'User-agent: *\nDisallow: /' > static/robots.txt
else
rm -f assets/robots.txt
rm -f static/robots.txt
fi
# if in travis, use the $NOW_TOKEN

Wyświetl plik

@ -0,0 +1,48 @@
const fs = require('fs')
const path = require('path')
const checksum = require('../inline-script-checksum').checksum
const html = fs.readFileSync(path.join(__dirname, '../__sapper__/export/index.html'), 'utf8')
const nonce = html.match(/<script nonce=([^>]+)>/)[1]
const csp = `add_header Content-Security-Policy "script-src 'self' 'sha256-${checksum}' 'nonce-${nonce}'; ` +
`worker-src 'self'; style-src 'self' 'unsafe-inline'; frame-src 'none'; object-src 'none'; manifest-src 'self';`
fs.writeFileSync(path.join(__dirname, '../__sapper__/export/.csp.nginx'), csp, 'utf8')
console.log(`
,((*
,((* (,
,((* (((*
,((* (((((.
* ,((* ((((((*
.(/ ,((* (((((((/
.((/ ,((* ((((((((/
,(((/ ,((* (((((((((*
.(((((/ ,((* ((((((((((
,((*
//////////((((/////////////
/((((((((((((((((((((((((((
/((((((((((((((((((((((((,
*(((((((((((((((((((((/.
./((((((((((((((((.
P I N A F O R E
Export successful! Static files are in:
__sapper__/export/
Be sure to add the CSP header to your nginx config:
server {
include ${path.resolve(__dirname, '..')}/__sapper__/export/.csp.nginx;
}
This file will be updated whenever you do \`npm run export\`.
Enjoy Pinafore!
`)

Wyświetl plik

@ -1,12 +1,12 @@
import { actions } from './mastodon-data'
import { users } from '../tests/users'
import { postStatus } from '../routes/_api/statuses'
import { followAccount } from '../routes/_api/follow'
import { favoriteStatus } from '../routes/_api/favorite'
import { reblogStatus } from '../routes/_api/reblog'
import { postStatus } from '../src/routes/_api/statuses'
import { followAccount } from '../src/routes/_api/follow'
import { favoriteStatus } from '../src/routes/_api/favorite'
import { reblogStatus } from '../src/routes/_api/reblog'
import fetch from 'node-fetch'
import FileApi from 'file-api'
import { pinStatus } from '../routes/_api/pin'
import { pinStatus } from '../src/routes/_api/pin'
import { submitMedia } from '../tests/submitMedia'
global.File = FileApi.File

Wyświetl plik

@ -1,5 +1,5 @@
module.exports = [
{ id: 'pinafore-logo', src: 'original-assets/sailboat.svg', title: 'Home' },
{ id: 'pinafore-logo', src: 'original-static/sailboat.svg', title: 'Home' },
{ id: 'fa-bell', src: 'node_modules/font-awesome-svg-png/white/svg/bell.svg', title: 'Notifications' },
{ id: 'fa-users', src: 'node_modules/font-awesome-svg-png/white/svg/users.svg', title: 'Local' },
{ id: 'fa-globe', src: 'node_modules/font-awesome-svg-png/white/svg/globe.svg', title: 'Federated' },

Wyświetl plik

@ -1,6 +1,9 @@
## Theming
Create a file `scss/themes/foobar.scss`, write some SCSS inside and add the following at the bottom of `scss/themes/foobar.scss`.
This document describes how to write your own theme for Pinafore.
First, create a file `scss/themes/foobar.scss`, write some SCSS inside and add
the following at the bottom of `scss/themes/foobar.scss`.
```scss
@import "_base.scss";
@ -9,9 +12,10 @@ body.theme-foobar {
}
```
> Note: You can find all the SCSS variables available in `scss/themes/_default.scss` while the all CSS Custom Properties available are listed in `scss/themes/_base.scss`.
> Note: You can find all the SCSS variables available in `scss/themes/_default.scss`
> while the all CSS Custom Properties available are listed in `scss/themes/_base.scss`.
Add your theme to `routes/_static/themes.js`
Then, Add your theme to `src/routes/_static/themes.js`
```js
const themes = [
...
@ -24,4 +28,7 @@ const themes = [
]
```
Start the development server (`npm run dev`), go to `http://localhost:4002/settings/instances/your-instance-name` and select your newly created theme. Once you've done that, you can update your theme, and refresh the page to see the change (you don't have to restart the server).
Start the development server (`npm run dev`), go to
`http://localhost:4002/settings/instances/your-instance-name` and select your
newly-created theme. Once you've done that, you can update your theme, and refresh
the page to see the change (you don't have to restart the server).

Wyświetl plik

@ -2,8 +2,8 @@
// To allow CSP to work correctly, we also calculate a sha256 hash during
// the build process and write it to inline-script-checksum.json.
import { testHasLocalStorageOnce } from './routes/_utils/testStorage'
import { switchToTheme } from './routes/_utils/themeEngine'
import { testHasLocalStorageOnce } from './src/routes/_utils/testStorage'
import { switchToTheme } from './src/routes/_utils/themeEngine'
window.__themeColors = process.env.THEME_COLORS

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 708 B

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 708 B

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 403 B

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 403 B

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 326 B

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 326 B

929
package-lock.json wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -3,15 +3,16 @@
"description": "Alternative web client for Mastodon",
"version": "0.13.0",
"scripts": {
"lint": "standard && standard --plugin html 'routes/**/*.html'",
"lint-fix": "standard --fix && standard --fix --plugin html 'routes/**/*.html'",
"lint": "standard && standard --plugin html 'src/routes/**/*.html'",
"lint-fix": "standard --fix && standard --fix --plugin html 'src/routes/**/*.html'",
"dev": "run-s build-svg build-inline-script serve-dev",
"serve-dev": "run-p --race build-sass-watch serve",
"serve": "node server.js",
"serve-dev": "run-p --race build-sass-watch sapper-dev",
"sapper-dev": "cross-env PORT=4002 sapper dev",
"sapper-prod": "cross-env PORT=4002 node __sapper__/build",
"build": "cross-env NODE_ENV=production npm run build-steps",
"build-steps": "run-s globalize-css build-sass build-svg build-inline-script sapper-build deglobalize-css",
"sapper-build": "sapper build",
"start": "cross-env NODE_ENV=production npm run serve",
"start": "cross-env NODE_ENV=production npm run sapper-prod",
"build-and-start": "run-s build start",
"build-svg": "node ./bin/build-svg.js",
"build-inline-script": "node -r esm ./bin/build-inline-script.js",
@ -36,7 +37,10 @@
"deploy-prod": "DEPLOY_TYPE=prod ./bin/deploy.sh",
"deploy-dev": "DEPLOY_TYPE=dev ./bin/deploy.sh",
"deploy-all-travis": "./bin/deploy-all-travis.sh",
"backup-mastodon-data": "./bin/backup-mastodon-data.sh"
"backup-mastodon-data": "./bin/backup-mastodon-data.sh",
"sapper-export": "sapper export",
"print-export-info": "node ./bin/print-export-info.js",
"export": "run-s build sapper-export print-export-info"
},
"dependencies": {
"@gamestdio/websocket": "^0.2.8",
@ -48,6 +52,7 @@
"cross-env": "^5.2.0",
"css-loader": "^2.0.0",
"emoji-regex": "^7.0.1",
"encoding": "^0.1.12",
"escape-html": "^1.0.3",
"esm": "^3.0.84",
"events-light": "^1.0.5",
@ -63,12 +68,10 @@
"localstorage-memory": "^1.0.3",
"lodash-es": "^4.17.11",
"lodash-webpack-plugin": "^0.11.5",
"mini-css-extract-plugin": "^0.5.0",
"mkdirp": "^0.5.1",
"node-fetch": "^2.3.0",
"node-sass": "^4.10.0",
"npm-run-all": "^4.1.5",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"p-any": "^1.1.0",
"page-lifecycle": "^0.1.1",
"performance-now": "^2.1.0",
@ -78,10 +81,9 @@
"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#nolan/sw-index-html-built",
"serve-static": "^1.13.2",
"stringz": "^1.0.0",
"style-loader": "^0.23.1",
"svelte": "^2.15.3",
"svelte-extras": "^2.0.2",
"svelte-loader": "^2.11.0",
@ -89,6 +91,7 @@
"svgo": "^1.1.1",
"terser-webpack-plugin": "^1.1.0",
"tiny-queue": "^0.2.1",
"uuid": "^3.3.2",
"web-animations-js": "^2.3.1",
"webpack": "^4.26.1",
"webpack-bundle-analyzer": "^3.0.3"
@ -140,8 +143,8 @@
],
"ignore": [
"dist",
"routes/_utils/asyncModules.js",
"routes/_components/dialog/asyncDialogs.js"
"src/routes/_utils/asyncModules.js",
"src/routes/_components/dialog/asyncDialogs.js"
]
},
"esm": {
@ -154,18 +157,16 @@
"NODE_ENV": "production"
},
"files": [
"assets",
"bin",
"original-assets",
"routes",
"inline-script.js",
"original-static",
"scss",
"templates",
"src",
"static",
"package.json",
"package-lock.json",
"server.js",
"inline-script.js",
"webpack.client.config.js",
"webpack.server.config.js"
"webpack",
"webpack.config.js"
],
"engines": {
"node": "^8.0.0"

Wyświetl plik

@ -1,36 +0,0 @@
<Nav {page} />
<div class="main-content">
<main class="{infiniteScrollPage ? 'infinite-scroll-page' : ''}">
<slot></slot>
</main>
{#if !$isUserLoggedIn && page === 'home'}
<InformationalFooter />
{/if}
</div>
<style>
/* this avoids a flash of the background color when switching timelines */
.infinite-scroll-page {
min-height: 100vh;
}
</style>
<script>
import Nav from './Nav.html'
import { store } from '../_store/store'
import InformationalFooter from './InformationalFooter.html'
export default {
components: {
Nav,
InformationalFooter
},
oncreate () {
let { page } = this.get()
this.store.set({ currentPage: page })
},
store: () => store,
computed: {
infiniteScrollPage: ({ $isUserLoggedIn, page }) => $isUserLoggedIn && page !== 'settings'
}
}
</script>

Wyświetl plik

@ -1,21 +0,0 @@
<Title name="Profile" />
<Layout page='tags'>
<LazyPage {pageComponent} {params} />
</Layout>
<script>
import Layout from '../_components/Layout.html'
import Title from '../_components/Title.html'
import LazyPage from '../_components/LazyPage.html'
import pageComponent from '../_pages/accounts/[accountId].html'
export default {
components: {
Layout,
Title,
LazyPage
},
data: () => ({
pageComponent
})
}
</script>

14
src/client.js 100644
Wyświetl plik

@ -0,0 +1,14 @@
import * as sapper from '../__sapper__/client.js'
import { loadPolyfills } from './routes/_utils/loadPolyfills'
import './routes/_utils/serviceWorkerClient'
import './routes/_utils/historyEvents'
import './routes/_utils/loadingMask'
loadPolyfills().then(() => {
console.log('init()')
sapper.start({ target: document.querySelector('#sapper') })
})
if (module.hot) {
module.hot.accept()
}

Wyświetl plik

@ -1,6 +1,6 @@
import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } from '../_api/oauth'
import { getInstanceInfo } from '../_api/instance'
import { goto } from 'sapper/runtime.js'
import { goto } from '../../../__sapper__/client'
import { switchToTheme } from '../_utils/themeEngine'
import { store } from '../_store/store'
import { updateVerifyCredentialsForInstance } from './instances'

Wyświetl plik

@ -2,7 +2,7 @@ import { getVerifyCredentials } from '../_api/user'
import { store } from '../_store/store'
import { switchToTheme } from '../_utils/themeEngine'
import { toast } from '../_utils/toast'
import { goto } from 'sapper/runtime.js'
import { goto } from '../../../__sapper__/client'
import { cacheFirstUpdateAfter } from '../_utils/sync'
import { getInstanceInfo } from '../_api/instance'
import { database } from '../_database/database'

Wyświetl plik

@ -32,8 +32,8 @@
</style>
<script>
import { store } from '../_store/store'
import LoadingPage from '../_components/LoadingPage.html'
import AccountSearchResult from '../_components/search/AccountSearchResult.html'
import LoadingPage from './LoadingPage.html'
import AccountSearchResult from './search/AccountSearchResult.html'
import { toast } from '../_utils/toast'
import { on } from '../_utils/eventBus'
@ -71,4 +71,4 @@
}
}
}
</script>
</script>

Wyświetl plik

@ -1,4 +1,4 @@
<!-- toggled in 2xx.html based on whether the user is logged in or not -->
<!-- toggled in template.html based on whether the user is logged in or not -->
<div class="hidden-from-ssr">
<slot></slot>
</div>
@ -6,4 +6,4 @@
.hidden-from-ssr {
opacity: 0;
}
</style>
</style>

Wyświetl plik

@ -2,6 +2,7 @@
<svelte:component this={pageComponent} {params} />
{/if}
<script>
import { doubleRAF } from '../_utils/doubleRAF'
// On the very first page load, avoid doing a "reveal" because
// it leads to a flash between when the SSR is shown, the two frame we hide it,
// and then when we show it again.
@ -13,14 +14,12 @@
export default {
oncreate () {
firstTime = false
requestAnimationFrame(() => {
requestAnimationFrame(() => {
this.set({ revealed: true })
})
})
// Yes, triple raf. This is to ensure the NavItem animation plays before we
// start rendering the new page.
doubleRAF(() => requestAnimationFrame(() => this.set({ revealed: true })))
},
data: () => ({
revealed: !process.browser || firstTime
})
}
</script>
</script>

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 443 B

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 443 B

Some files were not shown because too many files have changed in this diff Show More