chore: hash images (#5219)
* 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:
Родитель
3fbf6b73da
Коммит
9e4cb8ad4f
|
@ -120,8 +120,6 @@ describe('electronjs.org', () => {
|
||||||
expect(typeHits.first()).to.contain('window-all-closed')
|
expect(typeHits.first()).to.contain('window-all-closed')
|
||||||
if (type.includes('package'))
|
if (type.includes('package'))
|
||||||
expect(typeHits.first()).to.contain('about-window')
|
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": "^7.21.0",
|
||||||
"eslint-config-prettier": "^8.1.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
|
"globby": "^11.0.2",
|
||||||
"handlebars-loader": "^1.7.1",
|
"handlebars-loader": "^1.7.1",
|
||||||
"husky": "^4.3.8",
|
"husky": "^4.3.8",
|
||||||
"lint-staged": "^10.5.4",
|
"lint-staged": "^10.5.4",
|
||||||
|
|
|
@ -2,9 +2,10 @@ const crypto = require('crypto')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const sass = require('node-sass')
|
const sass = require('node-sass')
|
||||||
|
const globby = require('globby')
|
||||||
|
|
||||||
function dir(...parts) {
|
function dir(...parts) {
|
||||||
return path.join(__dirname, '..', ...parts)
|
return path.posix.join(__dirname, '..', ...parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
const env = process.env.NODE_ENV
|
const env = process.env.NODE_ENV
|
||||||
|
@ -16,20 +17,35 @@ const PATHS = {
|
||||||
|
|
||||||
cssEntry: dir('public', 'styles', 'index.scss'),
|
cssEntry: dir('public', 'styles', 'index.scss'),
|
||||||
cssDestinationDir: dir('precompiled', 'styles'),
|
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() {
|
async function precompileAssets() {
|
||||||
try {
|
try {
|
||||||
console.log('Creating directories...')
|
console.log('Creating directories...')
|
||||||
await fs.ensureDir(PATHS.styles)
|
await fs.ensureDir(PATHS.styles)
|
||||||
|
await fs.ensureDir(PATHS.imageDestinationDir)
|
||||||
console.log('Precompiling CSS...')
|
console.log('Precompiling CSS...')
|
||||||
await precompileCss()
|
await precompileCss()
|
||||||
|
console.log('Hashing images...')
|
||||||
|
await precompileImages()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateHash(content) {
|
||||||
|
const hash = crypto.createHash('md4').update(content).digest('hex')
|
||||||
|
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
function precompileCss() {
|
function precompileCss() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
sass.render(
|
sass.render(
|
||||||
|
@ -43,10 +59,7 @@ function precompileCss() {
|
||||||
return reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cssHash = crypto
|
const cssHash = calculateHash(result.css)
|
||||||
.createHash('md4')
|
|
||||||
.update(result.css)
|
|
||||||
.digest('hex')
|
|
||||||
const cssFileName =
|
const cssFileName =
|
||||||
env === 'production' ? `index.${cssHash}.min.css` : 'index.css'
|
env === 'production' ? `index.${cssHash}.min.css` : 'index.css'
|
||||||
const cssFile = path.resolve(PATHS.cssDestinationDir, cssFileName)
|
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) {
|
if (require.main === module) {
|
||||||
precompileAssets().catch((err) => {
|
precompileAssets().catch((err) => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
|
@ -17,10 +17,6 @@ const types = [
|
||||||
name: 'package',
|
name: 'package',
|
||||||
path: '/community',
|
path: '/community',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'app',
|
|
||||||
path: '/apps',
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
const typeNames = types.map((type) => type.name)
|
const typeNames = types.map((type) => type.name)
|
||||||
|
|
||||||
|
|
25
server.js
25
server.js
|
@ -90,23 +90,42 @@ if (process.env.NODE_ENV === 'production') {
|
||||||
'styles',
|
'styles',
|
||||||
'manifest.json'
|
'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') {
|
if (type === 'js') {
|
||||||
return jsManifest[name] || 'unknown.name'
|
return jsManifest[name] || 'unknown.name'
|
||||||
}
|
}
|
||||||
if (type === 'css') {
|
if (type === 'css') {
|
||||||
return cssManifest[name] || 'unknown.name'
|
return cssManifest[name] || 'unknown.name'
|
||||||
}
|
}
|
||||||
|
if (type === 'image') {
|
||||||
|
return imagesManifest[name] || 'unknown.name'
|
||||||
|
}
|
||||||
return 'unknown.type'
|
return 'unknown.type'
|
||||||
})
|
})
|
||||||
} else {
|
} 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') {
|
if (type === 'js') {
|
||||||
return `/scripts/${name}`
|
return `/scripts/${name}`
|
||||||
}
|
}
|
||||||
if (type === 'css') {
|
if (type === 'css') {
|
||||||
return `/styles/${name}`
|
return `/styles/${name}`
|
||||||
}
|
}
|
||||||
|
if (type === 'image') {
|
||||||
|
return `/images${name}`
|
||||||
|
}
|
||||||
return 'unknown.type'
|
return 'unknown.type'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -138,7 +157,7 @@ app.use(
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
app.use(express.static(path.join(__dirname, 'public'), { redirect: false }))
|
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(slashes(false))
|
||||||
app.use(langResolver)
|
app.use(langResolver)
|
||||||
app.use(contextBuilder)
|
app.use(contextBuilder)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="app-result">
|
<div class="app-result">
|
||||||
<a class="app-result-icon-link" href="/apps/{{slug}}">
|
<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>
|
</a>
|
||||||
<span class="search-small-text"><a href="/apps/{{slug}}">{{{name}}}</a> - {{{_highlightResult.description.value}}}</span>
|
<span class="search-small-text"><a href="/apps/{{slug}}">{{{name}}}</a> - {{{_highlightResult.description.value}}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<div class='listed-app-logo-wrapper'>
|
<div class='listed-app-logo-wrapper'>
|
||||||
<div class="listed-app-logo-placeholder placeholder" style="background: {{this.goodColorOnWhite}}">
|
<div class="listed-app-logo-placeholder placeholder" style="background: {{this.goodColorOnWhite}}">
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<span class='listed-app-name text-gray-dark'>{{this.name}}</span>
|
<span class='listed-app-name text-gray-dark'>{{this.name}}</span>
|
||||||
<span class='listed-app-description text-gray-light'>{{this.description}}</span>
|
<span class='listed-app-description text-gray-light'>{{this.description}}</span>
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
<div class="container-xl media-fluid">
|
<div class="container-xl media-fluid">
|
||||||
<div class="clearfix pt-md-6">
|
<div class="clearfix pt-md-6">
|
||||||
<div class="col-md-3 float-md-left pr-md-5 mb-3 mb-md-0">
|
<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>
|
||||||
<div class="col-md-9 float-md-left pl-md-5 text-center text-md-left">
|
<div class="col-md-9 float-md-left pl-md-5 text-center text-md-left">
|
||||||
<h1 class="f00-light lh-condensed mb-3">
|
<h1 class="f00-light lh-condensed mb-3">
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<div class="devtron">
|
<div class="devtron">
|
||||||
<div class="jumbotron text-center">
|
<div class="jumbotron text-center">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/devtron-icon.svg" alt="Devtron icon">
|
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/devtron-icon.svg'}}" alt="Devtron icon">
|
||||||
<p><img src="{{ site.baseurl }}/images/devtron-logo.svg" alt="Devtron logo"></p>
|
<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>
|
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron DevTools Extension</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6'>
|
<div class='col-xs-12 col-md-6'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
<div class='row mt-8'>
|
<div class='row mt-8'>
|
||||||
<div class='col-xs-12 col-md-6 mb-4'>
|
<div class='col-xs-12 col-md-6 mb-4'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6 text-left'>
|
<div class='col-xs-12 col-md-6 text-left'>
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6'>
|
<div class='col-xs-12 col-md-6'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
<div class='row mt-8'>
|
<div class='row mt-8'>
|
||||||
<div class='col-xs-12 col-md-6 mb-4'>
|
<div class='col-xs-12 col-md-6 mb-4'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6 text-left'>
|
<div class='col-xs-12 col-md-6 text-left'>
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img
|
<img
|
||||||
class="mb-4 mb-lg-6 fiddle-icon"
|
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"
|
alt="Electron Fiddle Icon"
|
||||||
/>
|
/>
|
||||||
<p>
|
<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>
|
||||||
<p class="jumbotron-lead">
|
<p class="jumbotron-lead">
|
||||||
<span class="jumbotron-lead-muted">{{localized.landing.fiddle.lead_desc}}</span>
|
<span class="jumbotron-lead-muted">{{localized.landing.fiddle.lead_desc}}</span>
|
||||||
|
@ -176,7 +176,7 @@
|
||||||
<div class="f-app-frame">
|
<div class="f-app-frame">
|
||||||
<img
|
<img
|
||||||
alt="Screenshot of Electron Fiddle"
|
alt="Screenshot of Electron Fiddle"
|
||||||
src="{{ site.baseurl }}/images/fiddle/explore-electron.png"
|
src="{{ static-asset 'image' '/fiddle/explore-electron.png'}}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -187,7 +187,7 @@
|
||||||
<div class="f-app-frame">
|
<div class="f-app-frame">
|
||||||
<img
|
<img
|
||||||
alt="Screenshot of Electron Fiddle Editor"
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
@ -206,7 +206,7 @@
|
||||||
<div class="f-app-frame">
|
<div class="f-app-frame">
|
||||||
<img
|
<img
|
||||||
alt="Screenshot of Electron Fiddle Compile And Package Menu"
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
@ -217,7 +217,7 @@
|
||||||
<div class="f-app-frame">
|
<div class="f-app-frame">
|
||||||
<img
|
<img
|
||||||
alt="Screenshot of Electron Fiddle Starting Point"
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,11 +51,11 @@
|
||||||
{{#each apps}}
|
{{#each apps}}
|
||||||
<a class="featured-app-list-item" href="{{ this.url }}" target="_blank" rel="noopener">
|
<a class="featured-app-list-item" href="{{ this.url }}" target="_blank" rel="noopener">
|
||||||
<picture>
|
<picture>
|
||||||
<source srcset="{{ site.baseurl }}/images/featured_apps/{{ screenshot }}.webp" type="image/webp">
|
<source srcset="{{ static-asset 'image' '/featured_apps/' screenshot '.webp'}}" type="image/webp">
|
||||||
<source srcset="{{ site.baseurl }}/images/featured_apps/{{ screenshot }}.png" type="image/png">
|
<source srcset="{{ static-asset 'image' '/featured_apps/' screenshot '.png'}}" type="image/png">
|
||||||
<img alt="" src="{{ site.baseurl }}/images/featured_apps/{{ screenshot }}.png">
|
<img alt="" src="{{ static-asset 'image' '/featured_apps/' screenshot '.png'}}">
|
||||||
</picture>
|
</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>
|
<h4>{{this.name}}</h4>
|
||||||
</a>
|
</a>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -75,17 +75,17 @@
|
||||||
|
|
||||||
<div class="d-sm-flex flex-row text-center text-small mt-6">
|
<div class="d-sm-flex flex-row text-center text-small mt-6">
|
||||||
<div class="col-xs-12 col-sm-4">
|
<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>
|
<h3 class="f1-light mb-2 mt-0">{{{localized.web_technologies.title}}}</h3>
|
||||||
<p class="f4">{{{localized.web_technologies.description}}}</p>
|
<p class="f4">{{{localized.web_technologies.description}}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-4">
|
<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>
|
<h3 class="f1-light mb-2 mt-0">{{{localized.open_source.title}}}</h3>
|
||||||
<p class="f4">{{{localized.open_source.description}}}</p>
|
<p class="f4">{{{localized.open_source.description}}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-4">
|
<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>
|
<h3 class="f1-light mb-2 mt-0">{{{localized.cross_platform.title}}}</h3>
|
||||||
<p class="f4">{{{localized.cross_platform.description}}}</p>
|
<p class="f4">{{{localized.cross_platform.description}}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -142,7 +142,7 @@
|
||||||
<div class='col-md-5 flex-md-self-center text-center'>
|
<div class='col-md-5 flex-md-self-center text-center'>
|
||||||
<a href="https://github.com/electron/electron-api-demos/releases">
|
<a href="https://github.com/electron/electron-api-demos/releases">
|
||||||
<div class="app-frame py-4 px-6">
|
<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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -168,11 +168,11 @@
|
||||||
<a href="/fiddle">
|
<a href="/fiddle">
|
||||||
<img
|
<img
|
||||||
class="mb-4 mb-lg-6 fiddle-icon"
|
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"
|
alt="Electron Fiddle Icon"
|
||||||
/>
|
/>
|
||||||
<p>
|
<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>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<a href='/apps/{{this.slug}}' title='{{this.name}}' class='featured-app'>
|
<a href='/apps/{{this.slug}}' title='{{this.name}}' class='featured-app'>
|
||||||
<div class='featured-app-logo-wrapper'>
|
<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>
|
||||||
<div class='featured-app-name'>{{this.name}}</div>
|
<div class='featured-app-name'>{{this.name}}</div>
|
||||||
<div class='featured-app-description' style='display:none;'>{{this.description}}</div>
|
<div class='featured-app-description' style='display:none;'>{{this.description}}</div>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-openjs col-md-12 col-lg-8 float-right p-4 f6">
|
<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
|
<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.
|
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
|
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}}" />
|
<meta property="twitter:image" content="{{page.image}}" />
|
||||||
{{else}}
|
{{else}}
|
||||||
<meta name="twitter:card" content="summary">
|
<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}}
|
{{/if}}
|
||||||
|
|
||||||
<!-- consumed by scripts/get-localized-strings -->
|
<!-- 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="localized.fiddle_launch_button.launch_in_fiddle" content="{{localized.fiddle_launch_button.launch_in_fiddle}}" />
|
||||||
|
|
||||||
<meta name="twitter:site" content="@ElectronJS" />
|
<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 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="alternate" type="application/rss+xml" title="Electron Releases" href="https://electronjs.org/releases.xml" />
|
||||||
<link rel='stylesheet' href='{{static-asset "css" "index.css"}}'>
|
<link rel='stylesheet' href='{{static-asset "css" "index.css"}}'>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<div class="spectron">
|
<div class="spectron">
|
||||||
<div class="jumbotron text-center">
|
<div class="jumbotron text-center">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/spectron-icon.svg" alt="Spectron icon">
|
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/spectron-icon.svg'}}" alt="Spectron icon">
|
||||||
<p><img src="{{ site.baseurl }}/images/spectron-logo.svg" alt="Spectron logo"></p>
|
<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>
|
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron Testing Framework</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<div class="devtron">
|
<div class="devtron">
|
||||||
<div class="jumbotron text-center">
|
<div class="jumbotron text-center">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/devtron-icon.svg" alt="Devtron icon">
|
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/devtron-icon.svg'}}" alt="Devtron icon">
|
||||||
<p><img src="{{ site.baseurl }}/images/devtron-logo.svg" alt="Devtron logo"></p>
|
<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>
|
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron DevTools Extension</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6'>
|
<div class='col-xs-12 col-md-6'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
<div class='row mt-8'>
|
<div class='row mt-8'>
|
||||||
<div class='col-xs-12 col-md-6 mb-4'>
|
<div class='col-xs-12 col-md-6 mb-4'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6 text-left'>
|
<div class='col-xs-12 col-md-6 text-left'>
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6'>
|
<div class='col-xs-12 col-md-6'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
<div class='row mt-8'>
|
<div class='row mt-8'>
|
||||||
<div class='col-xs-12 col-md-6 mb-4'>
|
<div class='col-xs-12 col-md-6 mb-4'>
|
||||||
<div class="app-frame">
|
<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>
|
</div>
|
||||||
<div class='col-xs-12 col-md-6 text-left'>
|
<div class='col-xs-12 col-md-6 text-left'>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{{#if this.title}}
|
{{#if this.title}}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{site.baseurl}}/userland/{{this.slug}}" class="inner">
|
<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>
|
<h3>{{this.title}}</h3>
|
||||||
<p>{{this.description}}</p>
|
<p>{{this.description}}</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<div class="spectron">
|
<div class="spectron">
|
||||||
<div class="jumbotron text-center">
|
<div class="jumbotron text-center">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img class="mb-4 mb-lg-6" src="{{ site.baseurl }}/images/spectron-icon.svg" alt="Spectron icon">
|
<img class="mb-4 mb-lg-6" src="{{ static-asset 'image' '/spectron-icon.svg'}}" alt="Spectron icon">
|
||||||
<p><img src="{{ site.baseurl }}/images/spectron-logo.svg" alt="Spectron logo"></p>
|
<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>
|
<p class='jumbotron-lead'><span class='jumbotron-lead-muted'>An Electron Testing Framework</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче