* chore: hash images

* Apply suggestions from code review

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* Use posix separator so globby works

* Fixing precompile on Windows

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Erick Zhao <erick@hotmail.ca>
This commit is contained in:
Antón Molleda 2021-03-15 15:10:16 -07:00 коммит произвёл GitHub
Родитель 3fbf6b73da
Коммит 9e4cb8ad4f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 133 добавлений и 54 удалений

Просмотреть файл

@ -120,8 +120,6 @@ describe('electronjs.org', () => {
expect(typeHits.first()).to.contain('window-all-closed')
if (type.includes('package'))
expect(typeHits.first()).to.contain('about-window')
if (type.includes('app'))
expect(typeHits.first()).to.contain('PhotoScreenSaver')
})
})
})

Просмотреть файл

@ -102,6 +102,7 @@
"eslint": "^7.21.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"globby": "^11.0.2",
"handlebars-loader": "^1.7.1",
"husky": "^4.3.8",
"lint-staged": "^10.5.4",

Просмотреть файл

@ -2,9 +2,10 @@ const crypto = require('crypto')
const path = require('path')
const fs = require('fs-extra')
const sass = require('node-sass')
const globby = require('globby')
function dir(...parts) {
return path.join(__dirname, '..', ...parts)
return path.posix.join(__dirname, '..', ...parts)
}
const env = process.env.NODE_ENV
@ -16,20 +17,35 @@ const PATHS = {
cssEntry: dir('public', 'styles', 'index.scss'),
cssDestinationDir: dir('precompiled', 'styles'),
imagesDir: dir('public', 'images'),
imageDestinationDir: dir('precompiled', 'images'),
appImgDir: dir('node_modules', 'electron-apps', 'apps'),
appImgDestinationDir: dir('precompiled', 'images', 'app-img'),
}
async function precompileAssets() {
try {
console.log('Creating directories...')
await fs.ensureDir(PATHS.styles)
await fs.ensureDir(PATHS.imageDestinationDir)
console.log('Precompiling CSS...')
await precompileCss()
console.log('Hashing images...')
await precompileImages()
} catch (err) {
console.error(err)
process.exit(1)
}
}
function calculateHash(content) {
const hash = crypto.createHash('md4').update(content).digest('hex')
return hash
}
function precompileCss() {
return new Promise((resolve, reject) => {
sass.render(
@ -43,10 +59,7 @@ function precompileCss() {
return reject(err)
}
const cssHash = crypto
.createHash('md4')
.update(result.css)
.digest('hex')
const cssHash = calculateHash(result.css)
const cssFileName =
env === 'production' ? `index.${cssHash}.min.css` : 'index.css'
const cssFile = path.resolve(PATHS.cssDestinationDir, cssFileName)
@ -62,6 +75,58 @@ function precompileCss() {
})
}
async function precompileImages() {
// globby patterns only accept `/` (https://github.com/sindresorhus/globby#api)
const websiteImages = await globby(`${PATHS.imagesDir}/**/*`, {
onlyFiles: true,
})
const appImages = await globby(`${PATHS.appImgDir}/**/*.png`, {
onlyFiles: true,
})
const images = [...appImages, ...websiteImages]
const manifest = {}
for (const image of images) {
const basename = path.basename(image)
const extension = path.extname(image)
const filename = basename.replace(extension, '')
const content = await fs.readFile(image)
// We could optimize the images here and save a few bytes
const hash = calculateHash(content)
// Can't use `path.resolve` here because the resulting path on Windows
// will make the calculation of `value` later on even more convoluted
const imageDestination = image
.replace(PATHS.imagesDir, PATHS.imageDestinationDir)
.replace(PATHS.appImgDir, PATHS.appImgDestinationDir)
.replace(basename, `${filename}.${hash}${extension}`)
const finalDir = path.dirname(imageDestination)
await fs.ensureDir(finalDir)
await fs.copyFile(image, imageDestination)
const key = image.includes(PATHS.imagesDir)
? `${image.replace(PATHS.imagesDir, '')}`
: `/app-img${image.replace(PATHS.appImgDir, '')}`
const value = `/images${imageDestination.replace(
PATHS.imageDestinationDir,
''
)}`
manifest[key] = value
}
await fs.writeFile(
path.resolve(PATHS.imageDestinationDir, 'manifest.json'),
JSON.stringify(manifest, null, 2)
)
}
if (require.main === module) {
precompileAssets().catch((err) => {
console.error(err)

Просмотреть файл

@ -17,10 +17,6 @@ const types = [
name: 'package',
path: '/community',
},
{
name: 'app',
path: '/apps',
},
]
const typeNames = types.map((type) => type.name)

Просмотреть файл

@ -90,23 +90,42 @@ if (process.env.NODE_ENV === 'production') {
'styles',
'manifest.json'
))
hbs.registerHelper('static-asset', (type, name) => {
const imagesManifest = require(path.join(
__dirname,
'precompiled',
'images',
'manifest.json'
))
hbs.registerHelper('static-asset', (type, ...parts) => {
// `parts` should be at minimum [name, function]
// but it could also be [part1, part2, part3, function ]
// if we want to link to dynamic images
const name = parts.length === 2 ? parts[0] : parts.slice(0, -1).join('')
if (type === 'js') {
return jsManifest[name] || 'unknown.name'
}
if (type === 'css') {
return cssManifest[name] || 'unknown.name'
}
if (type === 'image') {
return imagesManifest[name] || 'unknown.name'
}
return 'unknown.type'
})
} else {
hbs.registerHelper('static-asset', (type, name) => {
hbs.registerHelper('static-asset', (type, ...parts) => {
const name = parts.length === 2 ? parts[0] : parts.slice(0, -1).join('')
if (type === 'js') {
return `/scripts/${name}`
}
if (type === 'css') {
return `/styles/${name}`
}
if (type === 'image') {
return `/images${name}`
}
return 'unknown.type'
})
}
@ -138,7 +157,7 @@ app.use(
})
)
app.use(express.static(path.join(__dirname, 'public'), { redirect: false }))
app.use('/app-img', express.static(appImgDir, { redirect: false }))
app.use('/images/app-img', express.static(appImgDir, { redirect: false }))
app.use(slashes(false))
app.use(langResolver)
app.use(contextBuilder)

Просмотреть файл

@ -1,6 +1,6 @@
<div class="app-result">
<a class="app-result-icon-link" href="/apps/{{slug}}">
<img class="app-result-icon" src="/app-img/{{slug}}/{{icon32}}" alt="{{slug}} icon">
<img class="app-result-icon" src="{{ static-asset 'image' '/app-img/' slug '/' icon32 }}" alt="{{slug}} icon">
</a>
<span class="search-small-text"><a href="/apps/{{slug}}">{{{name}}}</a> - {{{_highlightResult.description.value}}}</span>
</div>

Просмотреть файл

@ -44,7 +44,7 @@
<div class='listed-app-logo-wrapper'>
<div class="listed-app-logo-placeholder placeholder" style="background: {{this.goodColorOnWhite}}">
</div>
<img class='listed-app-logo' data-src='/app-img/{{this.slug}}/{{this.icon64}}' alt='{{app.name}}'>
<img class='listed-app-logo' data-src="{{ static-asset 'image' '/app-img/' this.slug '/' this.icon64 }}" alt='{{app.name}}'>
</div>
<span class='listed-app-name text-gray-dark'>{{this.name}}</span>
<span class='listed-app-description text-gray-light'>{{this.description}}</span>

Просмотреть файл

@ -62,7 +62,7 @@
<div class="container-xl media-fluid">
<div class="clearfix pt-md-6">
<div class="col-md-3 float-md-left pr-md-5 mb-3 mb-md-0">
<div class="CircleBadge CircleBadge--large mx-auto box-shadow-large mt-1" style="background-color: #ffffff;"><img class="CircleBadge-icon" src='/app-img/{{app.slug}}/{{app.icon128}}' alt='{{app.name}}'></div>
<div class="CircleBadge CircleBadge--large mx-auto box-shadow-large mt-1" style="background-color: #ffffff;"><img class="CircleBadge-icon" src="{{ static-asset 'image' '/app-img/' app.slug '/' app.icon128 }}" alt='{{app.name}}'></div>
</div>
<div class="col-md-9 float-md-left pl-md-5 text-center text-md-left">
<h1 class="f00-light lh-condensed mb-3">

Просмотреть файл

@ -1,8 +1,8 @@
<div class="devtron">
<div class="jumbotron text-center">
<div class="container">
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/devtron-icon.svg" alt="Devtron icon">
<p><img src="{{ site.baseurl }}/images/devtron-logo.svg" alt="Devtron logo"></p>
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/devtron-icon.svg'}}" alt="Devtron icon">
<p><img src="{{ static-asset 'image' '/devtron-logo.svg'}}" alt="Devtron logo"></p>
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron DevTools Extension</span></p>
</div>
</div>
@ -26,7 +26,7 @@
</div>
<div class='col-xs-12 col-md-6'>
<div class="app-frame">
<img alt="Screenshot of Devtron Require Graph" src='{{ site.baseurl }}/images/devtron-require-graph.png'>
<img alt="Screenshot of Devtron Require Graph" src="{{ static-asset 'image' '/devtron-require-graph.png'}}">
</div>
</div>
</div>
@ -34,7 +34,7 @@
<div class='row mt-8'>
<div class='col-xs-12 col-md-6 mb-4'>
<div class="app-frame">
<img alt="Screenshot of Devtron Event Listeners" src='{{ site.baseurl }}/images/devtron-event-listeners.png'>
<img alt="Screenshot of Devtron Event Listeners" src="{{ static-asset 'image' '/devtron-event-listeners.png'}}">
</div>
</div>
<div class='col-xs-12 col-md-6 text-left'>
@ -56,7 +56,7 @@
</div>
<div class='col-xs-12 col-md-6'>
<div class="app-frame">
<img alt="Screenshot of Devtron IPC Monitor" src='{{ site.baseurl }}/images/devtron-ipc.png'>
<img alt="Screenshot of Devtron IPC Monitor" src="{{ static-asset 'image' '/devtron-ipc.png'}}">
</div>
</div>
</div>
@ -64,7 +64,7 @@
<div class='row mt-8'>
<div class='col-xs-12 col-md-6 mb-4'>
<div class="app-frame">
<img alt="Screenshot of Devtron Linter" src='{{ site.baseurl }}/images/devtron-linter.png'>
<img alt="Screenshot of Devtron Linter" src="{{ static-asset 'image' '/devtron-linter.png'}}">
</div>
</div>
<div class='col-xs-12 col-md-6 text-left'>

Просмотреть файл

@ -3,11 +3,11 @@
<div class="container">
<img
class="mb-4 mb-lg-6 fiddle-icon"
src="{{ site.baseurl }}/images/fiddle/fiddle-icon.svg"
src="{{ static-asset 'image' '/fiddle/fiddle-icon.svg'}}"
alt="Electron Fiddle Icon"
/>
<p>
<img src="{{ site.baseurl }}/images/fiddle/fiddle-logo.svg" alt="Electron Fiddle">
<img src="{{ static-asset 'image' '/fiddle/fiddle-logo.svg'}}" alt="Electron Fiddle">
</p>
<p class="jumbotron-lead">
<span class="jumbotron-lead-muted">{{localized.landing.fiddle.lead_desc}}</span>
@ -176,7 +176,7 @@
<div class="f-app-frame">
<img
alt="Screenshot of Electron Fiddle"
src="{{ site.baseurl }}/images/fiddle/explore-electron.png"
src="{{ static-asset 'image' '/fiddle/explore-electron.png'}}"
/>
</div>
</div>
@ -187,7 +187,7 @@
<div class="f-app-frame">
<img
alt="Screenshot of Electron Fiddle Editor"
src="{{ site.baseurl }}/images/fiddle/code-with-types.png"
src="{{ static-asset 'image' '/fiddle/code-with-types.png'}}"
/>
</div>
</div>
@ -206,7 +206,7 @@
<div class="f-app-frame">
<img
alt="Screenshot of Electron Fiddle Compile And Package Menu"
src="{{ site.baseurl }}/images/fiddle/compile-and-package.png"
src="{{ static-asset 'image' '/fiddle/compile-and-package.png'}}"
/>
</div>
</div>
@ -217,7 +217,7 @@
<div class="f-app-frame">
<img
alt="Screenshot of Electron Fiddle Starting Point"
src="{{ site.baseurl }}/images/fiddle/easy-start.png"
src="{{ static-asset 'image' '/fiddle/easy-start.png'}}"
/>
</div>
</div>

Просмотреть файл

@ -51,11 +51,11 @@
{{#each apps}}
<a class="featured-app-list-item" href="{{ this.url }}" target="_blank" rel="noopener">
<picture>
<source srcset="{{ site.baseurl }}/images/featured_apps/{{ screenshot }}.webp" type="image/webp">
<source srcset="{{ site.baseurl }}/images/featured_apps/{{ screenshot }}.png" type="image/png">
<img alt="" src="{{ site.baseurl }}/images/featured_apps/{{ screenshot }}.png">
<source srcset="{{ static-asset 'image' '/featured_apps/' screenshot '.webp'}}" type="image/webp">
<source srcset="{{ static-asset 'image' '/featured_apps/' screenshot '.png'}}" type="image/png">
<img alt="" src="{{ static-asset 'image' '/featured_apps/' screenshot '.png'}}">
</picture>
<img class="icon" data-src="{{ site.baseurl }}/images/featured_apps/{{ icon }}" alt="">
<img class="icon" data-src="{{ static-asset 'image' '/featured_apps/' icon}}" alt="">
<h4>{{this.name}}</h4>
</a>
{{/each}}
@ -75,17 +75,17 @@
<div class="d-sm-flex flex-row text-center text-small mt-6">
<div class="col-xs-12 col-sm-4">
<img class="home-illu" role="presentation" src="/images/web-tech.svg" aria-hidden="true">
<img class="home-illu" role="presentation" src="{{ static-asset 'image' '/web-tech.svg'}}" aria-hidden="true">
<h3 class="f1-light mb-2 mt-0">{{{localized.web_technologies.title}}}</h3>
<p class="f4">{{{localized.web_technologies.description}}}</p>
</div>
<div class="col-xs-12 col-sm-4">
<img class="home-illu" role="presentation" src="/images/open-source.svg" aria-hidden="true">
<img class="home-illu" role="presentation" src="{{ static-asset 'image' '/open-source.svg'}}" aria-hidden="true">
<h3 class="f1-light mb-2 mt-0">{{{localized.open_source.title}}}</h3>
<p class="f4">{{{localized.open_source.description}}}</p>
</div>
<div class="col-xs-12 col-sm-4">
<img class="home-illu" role="presentation" src="/images/cross-platform.svg" aria-hidden="true">
<img class="home-illu" role="presentation" src="{{ static-asset 'image' '/cross-platform.svg'}}" aria-hidden="true">
<h3 class="f1-light mb-2 mt-0">{{{localized.cross_platform.title}}}</h3>
<p class="f4">{{{localized.cross_platform.description}}}</p>
</div>
@ -142,7 +142,7 @@
<div class='col-md-5 flex-md-self-center text-center'>
<a href="https://github.com/electron/electron-api-demos/releases">
<div class="app-frame py-4 px-6">
<img alt="Screenshot of Electron API Demos app" width="249px" height="221px" src='/images/electron-api-demos.png'>
<img alt="Screenshot of Electron API Demos app" width="249px" height="221px" src="{{ static-asset 'image' '/electron-api-demos.png'}}">
</div>
</a>
</div>
@ -168,11 +168,11 @@
<a href="/fiddle">
<img
class="mb-4 mb-lg-6 fiddle-icon"
src="{{ site.baseurl }}/images/fiddle/fiddle-icon.svg"
src="{{ static-asset 'image' '/fiddle/fiddle-icon.svg'}}"
alt="Electron Fiddle Icon"
/>
<p>
<img src="{{ site.baseurl }}/images/fiddle/fiddle-logo.svg" alt="Electron Fiddle">
<img src="{{ static-asset 'image' '/fiddle/fiddle-logo.svg'}}" alt="Electron Fiddle">
</p>
</a>
</div>

Просмотреть файл

@ -1,6 +1,6 @@
<a href='/apps/{{this.slug}}' title='{{this.name}}' class='featured-app'>
<div class='featured-app-logo-wrapper'>
<img class='featured-app-logo' data-src='/app-img/{{this.slug}}/{{this.icon}}' alt='{{this.name}}'>
<img class='featured-app-logo' data-src="{{ static-asset 'image' '/app-img/' this.slug '/' this.icon }}" alt='{{this.name}}'>
</div>
<div class='featured-app-name'>{{this.name}}</div>
<div class='featured-app-description' style='display:none;'>{{this.description}}</div>

Просмотреть файл

@ -32,7 +32,7 @@
</nav>
</div>
<div class="footer-openjs col-md-12 col-lg-8 float-right p-4 f6">
<img class="footer-openjs-logo mb-4" src="/images/openjsf.svg" alt="OpenJS Foundation" />
<img class="footer-openjs-logo mb-4" src="{{ static-asset 'image' '/openjsf.svg'}}" alt="OpenJS Foundation" />
<p>Copyright <a href="https://openjsf.org">OpenJS Foundation</a> and Electron contributors. All rights
reserved. The <a href="https://openjsf.org">OpenJS Foundation</a> has registered trademarks and uses trademarks.
For a list of trademarks of the <a href="https://openjsf.org">OpenJS Foundation</a>, please see our <a

Просмотреть файл

@ -28,7 +28,7 @@
<meta property="twitter:image" content="{{page.image}}" />
{{else}}
<meta name="twitter:card" content="summary">
<meta property="twitter:image" content="https://www.electronjs.org/images/electron-icon.png" />
<meta property="twitter:image" content="https://www.electronjs.org/{{ static-asset 'image' 'images/electron-icon.png'}}" />
{{/if}}
<!-- consumed by scripts/get-localized-strings -->
@ -39,7 +39,7 @@
<meta name="localized.fiddle_launch_button.launch_in_fiddle" content="{{localized.fiddle_launch_button.launch_in_fiddle}}" />
<meta name="twitter:site" content="@ElectronJS" />
<link rel='shortcut icon' href='/images/favicon.ico'/>
<link rel='shortcut icon' href="{{ static-asset 'image' '/favicon.ico'}}" />
<link rel="alternate" type="application/rss+xml" title="Electron Blog" href="https://electronjs.org/blog.xml" />
<link rel="alternate" type="application/rss+xml" title="Electron Releases" href="https://electronjs.org/releases.xml" />
<link rel='stylesheet' href='{{static-asset "css" "index.css"}}'>

Просмотреть файл

@ -1,8 +1,8 @@
<div class="spectron">
<div class="jumbotron text-center">
<div class="container">
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/spectron-icon.svg" alt="Spectron icon">
<p><img src="{{ site.baseurl }}/images/spectron-logo.svg" alt="Spectron logo"></p>
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/spectron-icon.svg'}}" alt="Spectron icon">
<p><img src="{{ static-asset 'image' '/spectron-logo.svg'}}" alt="Spectron logo"></p>
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron Testing Framework</span></p>
</div>
</div>

Просмотреть файл

@ -1,8 +1,8 @@
<div class="devtron">
<div class="jumbotron text-center">
<div class="container">
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/devtron-icon.svg" alt="Devtron icon">
<p><img src="{{ site.baseurl }}/images/devtron-logo.svg" alt="Devtron logo"></p>
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/devtron-icon.svg'}}" alt="Devtron icon">
<p><img src="{{ static-asset 'image' '/devtron-logo.svg'}}" alt="Devtron logo"></p>
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron DevTools Extension</span></p>
</div>
</div>
@ -26,7 +26,7 @@
</div>
<div class='col-xs-12 col-md-6'>
<div class="app-frame">
<img alt="Screenshot of Devtron Require Graph" src='{{ site.baseurl }}/images/devtron-require-graph.png'>
<img alt="Screenshot of Devtron Require Graph" src="{{ static-asset 'image' '/devtron-require-graph.png'}}">
</div>
</div>
</div>
@ -34,7 +34,7 @@
<div class='row mt-8'>
<div class='col-xs-12 col-md-6 mb-4'>
<div class="app-frame">
<img alt="Screenshot of Devtron Event Listeners" src='{{ site.baseurl }}/images/devtron-event-listeners.png'>
<img alt="Screenshot of Devtron Event Listeners" src="{{ static-asset 'image' '/devtron-event-listeners.png'}}">
</div>
</div>
<div class='col-xs-12 col-md-6 text-left'>
@ -56,7 +56,7 @@
</div>
<div class='col-xs-12 col-md-6'>
<div class="app-frame">
<img alt="Screenshot of Devtron IPC Monitor" src='{{ site.baseurl }}/images/devtron-ipc.png'>
<img alt="Screenshot of Devtron IPC Monitor" src="{{ static-asset 'image' '/devtron-ipc.png'}}">
</div>
</div>
</div>
@ -64,7 +64,7 @@
<div class='row mt-8'>
<div class='col-xs-12 col-md-6 mb-4'>
<div class="app-frame">
<img alt="Screenshot of Devtron Linter" src='{{ site.baseurl }}/images/devtron-linter.png'>
<img alt="Screenshot of Devtron Linter" src="{{ static-asset 'image' '/devtron-linter.png'}}">
</div>
</div>
<div class='col-xs-12 col-md-6 text-left'>

Просмотреть файл

@ -9,7 +9,7 @@
{{#if this.title}}
<li>
<a href="{{site.baseurl}}/userland/{{this.slug}}" class="inner">
<img src="{{site.baseurl}}/images/userland/{{this.slug}}.svg" alt="{{this.title}} icon">
<img src="{{ static-asset 'image' '/userland/' this.slug '.svg'}}" alt="{{this.title}} icon">
<h3>{{this.title}}</h3>
<p>{{this.description}}</p>
</a>

Просмотреть файл

@ -1,8 +1,8 @@
<div class="spectron">
<div class="jumbotron text-center">
<div class="container">
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/spectron-icon.svg" alt="Spectron icon">
<p><img src="{{ site.baseurl }}/images/spectron-logo.svg" alt="Spectron logo"></p>
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/spectron-icon.svg'}}" alt="Spectron icon">
<p><img src="{{ static-asset 'image' '/spectron-logo.svg'}}" alt="Spectron logo"></p>
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron Testing Framework</span></p>
</div>
</div>