Verified Commit 77c960fd authored by Dan Allen's avatar Dan Allen
Browse files

retake screenshots for showcase section

- take screenshots on computer with 3840x2400 resolution
- scale screenshots to 2564x1602 (2560x1600 with 2px border on sides and bottom)
- use clip-path to move tab in screenshot
- add script to squoosh generated images
- change aspect ratio to 16:10
- regenerate book image to have 16:10 aspect ratio w/ transparent 2px border on sides and bottom
- add support for specifying a role on a block image
- reduce top radius on screenshots; don't apply radius to book image
- slightly clean up CSS for positioning images
parent 5307f027
Pipeline #3464 passed with stage
in 34 seconds
......@@ -6,6 +6,7 @@
- DPI: 148
- Shutter (or smiliar) to take screenshots without the frame
- Firefox with dark color scheme
- Edit Firefox toolbar to be compact and remove flexible spaces
- Screenshot size: 2048x1152 (16/9)
* Hero screenshot size: 3840x2400 (16/10); then cropped to 2048x940
- Screenshots should not include border radius or drop-shadow
......@@ -18,4 +19,3 @@
. Run `node index.js`
Screenshots are generated in the `dist` directory
#!/bin/bash
node index.js
for img in dist/*.png; do
npx @squoosh/cli -d ../../pages/assets/img --quant '{"enabled":true,"zx":0,"maxNumColors":256,"dither":1}' --webp '{"quality":100,"target_size":0,"target_PSNR":0,"method":6,"sns_strength":50,"filter_strength":60,"filter_sharpness":0,"filter_type":1,"partitions":0,"segments":4,"pass":1,"show_compressed":0,"preprocessing":0,"autofilter":0,"partition_limit":0,"alpha_compression":1,"alpha_filtering":1,"alpha_quality":100,"lossless":1,"exact":0,"image_hint":0,"emulate_jpeg_size":0,"thread_level":0,"low_memory":0,"near_lossless":100,"use_delta_palette":0,"use_sharp_yuv":0}' $img
npx @squoosh/cli -d ../../pages/assets/img --quant '{"enabled":true,"zx":0,"maxNumColors":256,"dither":1}' --oxipng '{"level":3,"interlace":false}' $img
done
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body {
padding: 0;
margin: 0;
}
.frame {
display: grid;
grid-template-rows: min-content 1fr;
height: 1152px;
width: 2048px;
}
.header {
position: relative;
}
.close {
position: absolute;
right: 50px;
top: 19px;
opacity: 0.9;
}
.close:before, .close:after {
position: absolute;
left: 15px;
content: ' ';
height: 25px;
width: 2px;
background-color: #ffffff;
}
.close:before {
transform: rotate(45deg);
}
.close:after {
transform: rotate(-45deg);
}
.content {
background-repeat: no-repeat;
background-size: contain;
background-origin: content-box;
border-left: 1px solid rgba(27, 26, 33, 0.7);
border-right: 1px solid rgba(27, 26, 33, 0.7);
border-bottom: 1px solid rgba(27, 26, 33, 0.7);
}
</style>
<meta charset="utf-8">
<style>
:root {
/* settings */
--base-screenshot-width: 1280;
--base-screenshot-height: 720;
--base-screenshot-height: 800;
--base-screenshot-border-width: 1;
--base-screenshot-titlebar-height: 44;
--base-screenshot-tab-left: 40;
--screenshot-scale: 2; /* 3 = 3840; 2 = 2560; 1.5 = 1920 */
/* computed */
--screenshot-width: calc(var(--base-screenshot-width) * var(--screenshot-scale) * 1px);
--screenshot-height: calc(var(--base-screenshot-height) * var(--screenshot-scale) * 1px);
--screenshot-border-width: calc(var(--base-screenshot-border-width) * var(--screenshot-scale) * 1px);
--screenshot-titlebar-height: calc(var(--base-screenshot-titlebar-height) * var(--screenshot-scale) * 1px);
--screenshot-tab-left: calc(var(--base-screenshot-tab-left) * var(--screenshot-scale) * 1px);
}
body {
margin: 0;
}
.content {
width: var(--screenshot-width);
height: var(--screenshot-height);
background: no-repeat top left / cover;
position: relative;
border: var(--screenshot-border-width) solid #808080;
border-top: 0;
}
.titlebar-mask {
position: absolute;
height: var(--screenshot-titlebar-height);
background-color: #1c1b22;
width: 50%;
top: 0;
}
.tab {
position: absolute;
width: inherit;
height: inherit;
background: no-repeat var(--screenshot-tab-left) top / cover;
clip-path: polygon(0 0, 50% 0, 50% var(--screenshot-titlebar-height), 0 var(--screenshot-titlebar-height));
}
</style>
</head>
<body>
<div class="frame">
<div class="header">
<div class="close"></div>
</div>
<div class="content"></div>
<div class="content">
<div class="titlebar-mask"></div>
<div class="tab"></div>
</div>
</body>
</html>
</head>
......@@ -6,70 +6,18 @@ import { readdir } from 'fs/promises'
const __dirname = dirname(fileURLToPath(import.meta.url))
function getStyle(file) {
if (file.startsWith('man-page')) {
return `.content {
let style = [`.content, .tab {
background-image: url(./img/${file});
padding-left: 16px;
padding-top: 16px;
background-color: #242424;
}
.header {
height: 67px;
background-color: #1c1b22;
border-bottom: 4px solid #2a2932;
}`
}
if (file.startsWith('intellij')) {
return `.frame {
height: 1280px;
width: 2048px;
}
.content {
background-image: url(./img/${file});
height: 1280px;
border-left: 3px solid #272727;
border-right: 3px solid #272727;
border-bottom: 3px solid #272727;
}
.content::before {
background: #f3f3f3;
content: "";
height: 32px;
left: 1870px;
position: absolute;
top: 60px;
width: 170px;
}
.content::after {
background: #fff url(./img/filetype-icon.png) no-repeat;
background-size: 100% auto;
content: "";
height: 26px;
left: 1707px;
position: absolute;
top: 103px;
width: 22px;
}
.header {
height: 50px;
background: linear-gradient(#2a2a2a, #262626);
border-bottom: 4px solid #272727;
border-top-left-radius: 25px;
border-top-right-radius: 25px;
}
.close {
}`]
if (file === 'man-page-git-for-each-ref.png') {
style.push(`.content {
border-color: #383838;
}`)
style.push(`.titlebar-mask, .tab {
display: none;
}`
}`)
}
return `.content {
background-image: url(./img/${file});
}`
return style.join('\n')
}
try {
......@@ -78,6 +26,7 @@ try {
await page.goto(`file://${join(__dirname, 'index.html')}`)
const files = await readdir(join(__dirname, 'img'))
for (const file of files) {
if (file === 'filetype-icon.png' || file === 'intellij-asciidoc-editor.png') continue
await page.addStyleTag({ content: getStyle(file) })
await page.screenshot({ path: join(__dirname, 'dist', file), fullPage: true, omitBackground: true })
await page.reload() // reset styles
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body {
padding: 0;
margin: 0;
}
.frame {
display: grid;
grid-template-rows: min-content 1fr;
height: 1152px;
width: 2048px;
}
.header {
position: relative;
}
.close {
position: absolute;
right: 50px;
top: 19px;
opacity: 0.9;
}
.close:before, .close:after {
position: absolute;
left: 15px;
content: ' ';
height: 25px;
width: 2px;
background-color: #ffffff;
}
.close:before {
transform: rotate(45deg);
}
.close:after {
transform: rotate(-45deg);
}
.content {
background-repeat: no-repeat;
background-size: contain;
background-origin: content-box;
border-left: 1px solid rgba(27, 26, 33, 0.7);
border-right: 1px solid rgba(27, 26, 33, 0.7);
border-bottom: 1px solid rgba(27, 26, 33, 0.7);
}
</style>
</head>
<body>
<div class="frame">
<div class="header">
<div class="close"></div>
</div>
<div class="content"></div>
</div>
</body>
</html>
import puppeteer from 'puppeteer'
import { dirname, join } from 'path'
import { fileURLToPath } from 'url'
import { readdir } from 'fs/promises'
const __dirname = dirname(fileURLToPath(import.meta.url))
function getStyle(file) {
if (file.startsWith('man-page')) {
return `.content {
background-image: url(./img/${file});
padding-left: 16px;
padding-top: 16px;
background-color: #242424;
}
.header {
height: 67px;
background-color: #1c1b22;
border-bottom: 4px solid #2a2932;
}`
}
if (file.startsWith('intellij')) {
return `.frame {
height: 1280px;
width: 2048px;
}
.content {
background-image: url(./img/${file});
height: 1280px;
border-left: 3px solid #272727;
border-right: 3px solid #272727;
border-bottom: 3px solid #272727;
}
.content::before {
background: #f3f3f3;
content: "";
height: 32px;
left: 1870px;
position: absolute;
top: 60px;
width: 170px;
}
.content::after {
background: #fff url(./img/filetype-icon.png) no-repeat;
background-size: 100% auto;
content: "";
height: 26px;
left: 1707px;
position: absolute;
top: 103px;
width: 22px;
}
.header {
height: 50px;
background: linear-gradient(#2a2a2a, #262626);
border-bottom: 4px solid #272727;
border-top-left-radius: 25px;
border-top-right-radius: 25px;
}
.close {
display: none;
}`
}
return `.content {
background-image: url(./img/${file});
}`
}
try {
const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] })
const page = await browser.newPage()
await page.goto(`file://${join(__dirname, 'index.html')}`)
const files = await readdir(join(__dirname, 'img'))
for (const file of files) {
await page.addStyleTag({ content: getStyle(file) })
await page.screenshot({ path: join(__dirname, 'dist', file), fullPage: true, omitBackground: true })
await page.reload() // reset styles
}
await browser.close()
} catch (err) {
console.error('Something went wrong!', err)
process.exit(1)
}
......@@ -134,7 +134,8 @@ class DocumentModelConverter {
const img = `<img src="${node.getImageUri(target)}" alt="${encodeAttributeValue(node.getAlt())}"/>`
const mimeType = target.endsWith('png') ? 'image/png' : 'image/jpeg'
const targetInfo = parse(target)
return `<div class="imageblock">
const role = node.getRole()
return `<div class="imageblock${role ? ' ' + role : ''}">
<picture class="content">
<source srcset="${targetInfo.dir}/${targetInfo.name}.webp" type="image/webp">
<source srcset="${node.getImageUri(target)}" type="${mimeType}">
......
......@@ -507,15 +507,20 @@ section.about .columns > .column:nth-child(2) {
}
section.about .imageblock img {
width: 100%;
margin-top: 0.5rem;
border-top-left-radius: 7px;
border-top-right-radius: 7px;
border-radius: 5px 5px 0 0;
filter: drop-shadow(0 5px 20px rgb(0 0 0 / 10%));
width: 100%;
}
section.about .tabset .content {
padding-top: 1.5rem;
section.about .imageblock.book img {
border-radius: 0;
filter: none;
margin-top: -0.75rem;
margin-bottom: 0.75rem;
}
section.about .tab-pane .imageblock {
margin-top: 1.5rem;
}
.main section h2 {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment