kopia lustrzana https://github.com/nolanlawson/pinafore
				
				
				
			
							rodzic
							
								
									6230c2703e
								
							
						
					
					
						commit
						283bc78b4f
					
				| 
						 | 
				
			
			@ -7,3 +7,4 @@ assets/*.css
 | 
			
		|||
/mastodon
 | 
			
		||||
mastodon.log
 | 
			
		||||
assets/robots.txt
 | 
			
		||||
/inline-script-checksum.json
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
#!/usr/bin/env node
 | 
			
		||||
 | 
			
		||||
const crypto = require('crypto')
 | 
			
		||||
const fs = require('fs')
 | 
			
		||||
const pify = require('pify')
 | 
			
		||||
const readFile = pify(fs.readFile.bind(fs))
 | 
			
		||||
const writeFile = pify(fs.writeFile.bind(fs))
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
async function main () {
 | 
			
		||||
  let headScriptFilepath = path.join(__dirname, '../inline-script.js')
 | 
			
		||||
  let headScript = await readFile(headScriptFilepath, 'utf8')
 | 
			
		||||
  headScript = `(function () {'use strict'; ${headScript}})()`
 | 
			
		||||
 | 
			
		||||
  let checksum = crypto.createHash('sha256').update(headScript).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(
 | 
			
		||||
    /<!-- insert inline script here -->[\s\S]+<!-- end insert inline script here -->/,
 | 
			
		||||
    '<!-- insert inline script here --><script>' + headScript + '</script><!-- end insert inline script here -->'
 | 
			
		||||
  )
 | 
			
		||||
  await writeFile(html2xxFilepath, html2xxFile, 'utf8')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main().catch(err => {
 | 
			
		||||
  console.error(err)
 | 
			
		||||
  process.exit(1)
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ const themes = [
 | 
			
		|||
export { themes }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Add your theme in `templates/2xx.html`.
 | 
			
		||||
Add your theme in `inline-script.js`.
 | 
			
		||||
```js
 | 
			
		||||
window.__themeColors = {
 | 
			
		||||
      'default': "royalblue",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
// 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',
 | 
			
		||||
  offline: '#999999'
 | 
			
		||||
}
 | 
			
		||||
if (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 !== 'default') {
 | 
			
		||||
    document.body.classList.add(`theme-${theme}`)
 | 
			
		||||
    let link = document.createElement('link')
 | 
			
		||||
    link.rel = 'stylesheet'
 | 
			
		||||
    link.href = `/theme-${theme}.css`
 | 
			
		||||
    document.head.appendChild(link)
 | 
			
		||||
    if (window.__themeColors[theme]) {
 | 
			
		||||
      document.getElementById('theThemeColor').content = window.__themeColors[theme]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
if (!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)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1563,6 +1563,11 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "camelize": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
 | 
			
		||||
    },
 | 
			
		||||
    "caniuse-api": {
 | 
			
		||||
      "version": "1.6.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2046,6 +2051,11 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
 | 
			
		||||
      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
 | 
			
		||||
    },
 | 
			
		||||
    "content-security-policy-builder": {
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-j+Nhmj1yfZAikJLImCvPJFE29x/UuBi+/MWqggGGc515JKaZrjuei2RhULJmy0MsstW3E3htl002bwmBNMKr7w=="
 | 
			
		||||
    },
 | 
			
		||||
    "content-type": {
 | 
			
		||||
      "version": "1.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2398,6 +2408,11 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "dasherize": {
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg="
 | 
			
		||||
    },
 | 
			
		||||
    "date-now": {
 | 
			
		||||
      "version": "0.1.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -4863,6 +4878,18 @@
 | 
			
		|||
        "sntp": "1.0.9"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "helmet-csp": {
 | 
			
		||||
      "version": "2.7.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.0.tgz",
 | 
			
		||||
      "integrity": "sha512-IGIAkWnxjRbgMXFA2/kmDqSIrIaSfZ6vhMHlSHw7jm7Gm9nVVXqwJ2B1YEpYrJsLrqY+w2Bbimk7snux9+sZAw==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "camelize": "1.0.0",
 | 
			
		||||
        "content-security-policy-builder": "2.0.0",
 | 
			
		||||
        "dasherize": "2.0.0",
 | 
			
		||||
        "lodash.reduce": "4.6.0",
 | 
			
		||||
        "platform": "1.3.5"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "highlight-es": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/highlight-es/-/highlight-es-1.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5783,6 +5810,11 @@
 | 
			
		|||
        "lodash.keys": "3.1.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "lodash.reduce": {
 | 
			
		||||
      "version": "4.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
 | 
			
		||||
      "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
 | 
			
		||||
    },
 | 
			
		||||
    "lodash.uniq": {
 | 
			
		||||
      "version": "4.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -7038,6 +7070,11 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "platform": {
 | 
			
		||||
      "version": "1.3.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
 | 
			
		||||
      "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q=="
 | 
			
		||||
    },
 | 
			
		||||
    "pluralize": {
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,14 +4,15 @@
 | 
			
		|||
  "version": "0.1.6",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "lint": "standard",
 | 
			
		||||
    "dev": "run-s build-svg serve-dev",
 | 
			
		||||
    "dev": "run-s build-svg build-inline-script serve-dev",
 | 
			
		||||
    "serve-dev": "run-p --race build-sass-watch serve",
 | 
			
		||||
    "serve": "node server.js",
 | 
			
		||||
    "build": "cross-env NODE_ENV=production run-s globalize-css build-sass build-svg sapper-build deglobalize-css",
 | 
			
		||||
    "build": "cross-env NODE_ENV=production run-s globalize-css build-sass build-svg build-inline-script sapper-build deglobalize-css",
 | 
			
		||||
    "sapper-build": "cross-env NODE_ENV=production sapper build",
 | 
			
		||||
    "start": "cross-env NODE_ENV=production node server.js",
 | 
			
		||||
    "build-and-start": "run-s build start",
 | 
			
		||||
    "build-svg": "node ./bin/build-svg.js",
 | 
			
		||||
    "build-inline-script": "node ./bin/build-inline-script.js",
 | 
			
		||||
    "build-sass": "node ./bin/build-sass.js",
 | 
			
		||||
    "build-sass-watch": "node ./bin/build-sass.js --watch",
 | 
			
		||||
    "run-mastodon": "node -r esm ./bin/run-mastodon",
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +49,7 @@
 | 
			
		|||
    "font-awesome-svg-png": "^1.2.2",
 | 
			
		||||
    "form-data": "^2.3.2",
 | 
			
		||||
    "glob": "^7.1.2",
 | 
			
		||||
    "helmet-csp": "^2.7.0",
 | 
			
		||||
    "indexeddb-getall-shim": "^1.3.1",
 | 
			
		||||
    "intersection-observer": "^0.5.0",
 | 
			
		||||
    "lodash": "^4.17.5",
 | 
			
		||||
| 
						 | 
				
			
			@ -140,6 +142,7 @@
 | 
			
		|||
      "package.json",
 | 
			
		||||
      "package-lock.json",
 | 
			
		||||
      "server.js",
 | 
			
		||||
      "inline-script.js",
 | 
			
		||||
      "webpack.client.config.js",
 | 
			
		||||
      "webpack.server.config.js"
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								server.js
								
								
								
								
							
							
						
						
									
										14
									
								
								server.js
								
								
								
								
							| 
						 | 
				
			
			@ -3,6 +3,9 @@ const compression = require('compression')
 | 
			
		|||
const sapper = require('sapper')
 | 
			
		||||
const serveStatic = require('serve-static')
 | 
			
		||||
const app = express()
 | 
			
		||||
const csp = require('helmet-csp')
 | 
			
		||||
 | 
			
		||||
const headScriptChecksum = require('./inline-script-checksum').checksum
 | 
			
		||||
 | 
			
		||||
const { PORT = 4002 } = process.env
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +18,17 @@ global.fetch = (url, opts) => {
 | 
			
		|||
 | 
			
		||||
app.use(compression({ threshold: 0 }))
 | 
			
		||||
 | 
			
		||||
app.use(csp({
 | 
			
		||||
  directives: {
 | 
			
		||||
    scriptSrc: [`'self'`, `'sha256-${headScriptChecksum}'`],
 | 
			
		||||
    workerSrc: [`'self'`],
 | 
			
		||||
    styleSrc: [`'self'`, `'unsafe-inline'`],
 | 
			
		||||
    frameSrc: [`'none'`],
 | 
			
		||||
    objectSrc: [`'none'`],
 | 
			
		||||
    manifestSrc: [`'self'`]
 | 
			
		||||
  }
 | 
			
		||||
}))
 | 
			
		||||
 | 
			
		||||
app.use(serveStatic('assets', {
 | 
			
		||||
  setHeaders: (res) => {
 | 
			
		||||
    res.setHeader('Cache-Control', 'public,max-age=600')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,42 +40,44 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
 | 
			
		|||
  %sapper.head%
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
  <script>
 | 
			
		||||
    <!-- load theme on startup (handled outside of Sapper/Svelte) -->
 | 
			
		||||
    window.__themeColors = {
 | 
			
		||||
      'default': "royalblue",
 | 
			
		||||
      scarlet:   "#e04e41",
 | 
			
		||||
      seafoam:   "#177380",
 | 
			
		||||
      hotpants:  "hotpink",
 | 
			
		||||
      oaken:     "saddlebrown",
 | 
			
		||||
      majesty:   "blueviolet",
 | 
			
		||||
      gecko:     "#4ab92f",
 | 
			
		||||
      ozark:     "#5263af",
 | 
			
		||||
      cobalt:    "#08439b",
 | 
			
		||||
      sorcery:   "#ae91e8",
 | 
			
		||||
      offline:   "#999999"
 | 
			
		||||
  <!-- auto-generated w/ build-inline-script.js -->
 | 
			
		||||
  <!-- insert inline script here --><script>(function () {'use strict'; // 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',
 | 
			
		||||
  offline: '#999999'
 | 
			
		||||
}
 | 
			
		||||
if (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 !== 'default') {
 | 
			
		||||
    document.body.classList.add(`theme-${theme}`)
 | 
			
		||||
    let link = document.createElement('link')
 | 
			
		||||
    link.rel = 'stylesheet'
 | 
			
		||||
    link.href = `/theme-${theme}.css`
 | 
			
		||||
    document.head.appendChild(link)
 | 
			
		||||
    if (window.__themeColors[theme]) {
 | 
			
		||||
      document.getElementById('theThemeColor').content = window.__themeColors[theme]
 | 
			
		||||
    }
 | 
			
		||||
    if (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 !== 'default') {
 | 
			
		||||
        document.body.classList.add(`theme-${theme}`)
 | 
			
		||||
        let link = document.createElement('link')
 | 
			
		||||
        link.rel = 'stylesheet'
 | 
			
		||||
        link.href = `/theme-${theme}.css`
 | 
			
		||||
        document.head.appendChild(link)
 | 
			
		||||
        if (window.__themeColors[theme]) {
 | 
			
		||||
          document.getElementById('theThemeColor').content = window.__themeColors[theme]
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (!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)
 | 
			
		||||
    }
 | 
			
		||||
  </script>
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
if (!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)
 | 
			
		||||
}
 | 
			
		||||
})()</script><!-- end insert inline script here -->
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" style="display:none;">
 | 
			
		||||
    <!-- auto-generated w/ build-svg.js -->
 | 
			
		||||
    <!-- insert svg here --><svg xmlns="http://www.w3.org/2000/svg" style="display:none;">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue