From eb882747f7457f08089cde3f6a6e319158676591 Mon Sep 17 00:00:00 2001 From: James Fenn Date: Tue, 4 Apr 2023 18:01:07 -0400 Subject: [PATCH] add banner card generator layout --- .../social-previews/layouts/banner.css.ts | 104 ++++++++++++++++++ .../social-previews/layouts/banner.tsx | 60 ++++++++++ ...ter-preview.css => twitter-preview.css.ts} | 7 +- .../layouts/twitter-preview.tsx | 15 +-- .../shared-post-preview-png.ts | 5 +- public/.gitignore | 2 +- 6 files changed, 174 insertions(+), 19 deletions(-) create mode 100644 build-scripts/social-previews/layouts/banner.css.ts create mode 100644 build-scripts/social-previews/layouts/banner.tsx rename build-scripts/social-previews/layouts/{twitter-preview.css => twitter-preview.css.ts} (99%) diff --git a/build-scripts/social-previews/layouts/banner.css.ts b/build-scripts/social-previews/layouts/banner.css.ts new file mode 100644 index 00000000..1df7a40f --- /dev/null +++ b/build-scripts/social-previews/layouts/banner.css.ts @@ -0,0 +1,104 @@ +export default ` +.codeScreenBg { + perspective: 200px; + perspective-origin: center; +} + +.codeScreenBg { + background: url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCABIAIADASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAECAwQFBv/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHhWUyNsqZRozlhDTXvDldLnCzW01KcbCmF9ImmSIotuy2G3veW9DFnC73mxUaM1XW5WTqATTGIG0iWvER2OWoggpNMQwBAwAJXGeWpmRa4mUtgQbiA0DAd4FgAAKIEEBCICiB//8QAIxAAAQQBBAIDAQAAAAAAAAAAAQACAxESECEwMSAyBBMiI//aAAgBAQABBQIbK9ogpRsw4optlRsNy+jk/rRyPg12zjaeaR9Gdtbala5SDUJ6LdtR2U0onaHuJv5LLMyDb0j9p+28AdivjzD63yU2U26/56ONnzvSGXFfbm1x/XM11c+JWJ5KKDfAhYqvOkBw0sVjp//EABQRAQAAAAAAAAAAAAAAAAAAAFD/2gAIAQMBAT8BI//EABQRAQAAAAAAAAAAAAAAAAAAAFD/2gAIAQIBAT8BI//EABsQAAMAAwEBAAAAAAAAAAAAAAABIRARIDBg/9oACAEBAAY/AsTEzCi4XSRpEzti96QvF8abS+Y//8QAHxAAAwACAgMBAQAAAAAAAAAAAAERITEQQSBRYTBx/9oACAEBAAE/IWC7RjVT+sQ6XuFc9cs31ntiNwbcLJazs2b2dHYsHZoy2ZZfPRCaIX7iGoZzgXitG4nklwQSmy2W24fC0jCkE5p+I2TIdbRTr2IXSlSsCpPCQgfxxmtImDrPkQ8jdSd8D2Yg2HRn9D2JxpmQL43hZDdKUmqkN25xdFm/ajMEbf4rjriNnwIdeM807oStkS65Sx+o2XKXgrFr8WrI4Q//2gAMAwEAAgADAAAAELF3261HEKNNDcYDWOBNCizLMDBPOYaJPPIXfHfYXP/EABQRAQAAAAAAAAAAAAAAAAAAAFD/2gAIAQMBAT8QI//EABkRAQACAwAAAAAAAAAAAAAAAAEAESAwQP/aAAgBAgEBPxDWwzSBXJ//xAAeEAEAAwEBAAMBAQAAAAAAAAABABEhMUEQUWFxgf/aAAgBAQABPxBVDED24YAfYyo4Vw9juZZ/JELbL2D6mBShKHOuv3GodNltJsiUZSpo9fs6H3KhChxss1ucJ1nsVy8nbiuBOJl0z1BayVAKHr1ZRwAL/s5eWwPZWWR4djk0u7KVMAz9jqksb3Iz9RGEuFpEos5HSyDaDOZdRcnnsESg3m+T0oTFTarZYzl9RL4obCNxQk17P9gDFr3ZQKyZYADyHRZKilpeX8FXZH7IKWx0n3LICBabuMc0mn7iGReseW6sijAKNXexalcOkfslgnXZyH8g7MMuIWuWLZX14mU5SzEZi3TRBTjHWDVkLj2XPIYQdiCuxorbi1LghuBKZFVftj1jjk9tgk9jRCPZ18ZFCwRQX8Ytahl/cI6/k/Jgh+x35DdyBbkcqN7TDkHws6Z/scbU6gxT6grjLJWwiEREEFLYQZfww/Y5EGeRP22IDrCs/9k='), radial-gradient(ellipse 200% 100%, #EEE, #FFF); + background-blend-mode: screen; + background-size: cover; + z-index: -4; +} + +.codeScreenBg.blur { + --gradient: linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,1)); + -webkit-mask-image: var(--gradient); + mask-image: var(--gradient); + filter: blur(5px); +} + +.codeScreen, .rect { + --z: 0px; + transform: rotateX(var(--rotX)) rotateY(21deg) rotateZ(336deg) translate(25%, -20%) translateZ(var(--z)); + transform-origin: center; +} + +.codeScreen { + height: 1000px; + overflow: hidden; + background-color: #FFF; + position: absolute; + top: 0; + left: 20%; + right: 0; + box-shadow: 0 0 180px 0 #0002; + border-radius: 20px; + border-left: 10px solid #CCC; +} + +.rect { + width: 180px; + height: 180px; + background-color: #8885; + backdrop-filter: blur(2px); + border: 4px solid #FFF; + box-shadow: -80px -10px 30px #0005; + + --x: 0px; + --y: 0px; + --z: 80px; + + position: absolute; + top: calc(50% + var(--y)); + left: calc(50% + var(--x)); +} + +.rect img { + margin: 20px; + width: calc(100% - 40px); + filter: grayscale(1); +} + +.tags { + position: absolute; + top: 25%; + left: 5%; + font-size: 10rem; + font-family: monospace; + text-transform: uppercase; + font-weight: bolder; +} + +.tags span { + display: block; + color: rgba(0, 0, 0, 0.15); +} + +pre { + background: none !important; + border: none !important; + color: #000 !important; +} + +pre code span { + text-shadow: currentColor 1px 0 10px; +} + +.absoluteFill { + height: 100%; + width: 100%; + position: absolute; + box-sizing: border-box; + top: 0; + left: 0; +} + +.codeScreenOverlay { + background: linear-gradient(340deg, rgba(0,0,0,.5), rgba(0,0,0,0)), url('data:image/svg+xml;utf8,'); + background-blend-mode: screen; + filter: contrast(800%) brightness(200%) saturate(0%); + opacity: 0.1; + z-index: -2; +} +`; diff --git a/build-scripts/social-previews/layouts/banner.tsx b/build-scripts/social-previews/layouts/banner.tsx new file mode 100644 index 00000000..343da972 --- /dev/null +++ b/build-scripts/social-previews/layouts/banner.tsx @@ -0,0 +1,60 @@ +import * as React from 'preact'; +import { readFileAsBase64 } from '../utils'; +import * as fs from 'fs'; +import { ComponentProps } from '../base'; +import style from './banner.css'; +import classnames from 'classnames'; + +const unicornFile = readFileAsBase64("src/assets/unicorn_utterances_sticker_512.png"); + +function BannerCodeScreen({ + post, + postHtml, + blur, +}: { + post: ComponentProps['post'], + postHtml: string, + blur?: boolean, +}) { + const rotX = (post.description.length % 30) - 10; + + return <> +
+
+
+				
+ { + post.tags.map((tag) => ( + {tag} + )) + } +
+
+
+ +
+
+ ; +} + +function Banner({ + post, + postHtml, +}: ComponentProps) { + return <> + + +
+ ; +} + +export default { + name: "banner", + css: style, + Component: Banner, +}; diff --git a/build-scripts/social-previews/layouts/twitter-preview.css b/build-scripts/social-previews/layouts/twitter-preview.css.ts similarity index 99% rename from build-scripts/social-previews/layouts/twitter-preview.css rename to build-scripts/social-previews/layouts/twitter-preview.css.ts index 3d61fbb7..5a5cd279 100644 --- a/build-scripts/social-previews/layouts/twitter-preview.css +++ b/build-scripts/social-previews/layouts/twitter-preview.css.ts @@ -1,10 +1,6 @@ +export default ` @import url("https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"); -html, body { - margin: 0; - padding: 0; -} - * { font-family: "Work Sans"; color: var(--white); @@ -145,3 +141,4 @@ html, body { .secondHalfTitle { color: #f5acc9; } +`; diff --git a/build-scripts/social-previews/layouts/twitter-preview.tsx b/build-scripts/social-previews/layouts/twitter-preview.tsx index 23cc88e5..28adcbdd 100644 --- a/build-scripts/social-previews/layouts/twitter-preview.tsx +++ b/build-scripts/social-previews/layouts/twitter-preview.tsx @@ -1,11 +1,7 @@ import * as React from 'preact'; import { readFileAsBase64 } from '../utils'; -import { dirname, resolve } from 'path'; -import * as fs from 'fs'; import { ComponentProps } from '../base'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); +import style from './twitter-preview.css'; export function splitSentence(str: string): [string, string] { const splitStr = str.split(" "); @@ -42,9 +38,7 @@ export function splitSentence(str: string): [string, string] { return [str, ""]; } -const unicornUtterancesHead = readFileAsBase64( - resolve("src/assets/unicorn_head_1024.png") -); +const unicornUtterancesHead = readFileAsBase64("src/assets/unicorn_head_1024.png"); interface TwitterCodeScreenProps { title: string; @@ -131,9 +125,6 @@ const TwitterLargeCard = ({ export default { name: "twitter-preview", - css: fs.readFileSync( - resolve(__dirname, "./twitter-preview.css"), - "utf8" - ), + css: style, Component: TwitterLargeCard, }; diff --git a/build-scripts/social-previews/shared-post-preview-png.ts b/build-scripts/social-previews/shared-post-preview-png.ts index ede426d1..543032de 100644 --- a/build-scripts/social-previews/shared-post-preview-png.ts +++ b/build-scripts/social-previews/shared-post-preview-png.ts @@ -12,10 +12,11 @@ import remarkToRehype from "remark-rehype"; import { findAllAfter } from "unist-util-find-all-after"; import rehypeStringify from "rehype-stringify"; +import banner from "./layouts/banner"; import twitterPreview from "./layouts/twitter-preview"; import { Layout } from "./base"; -export const layouts: Layout[] = [twitterPreview]; +export const layouts: Layout[] = [banner, twitterPreview]; // https://github.com/shikijs/twoslash/issues/147 const remarkTwoslash = @@ -103,6 +104,8 @@ export const renderPostPreviewToString = async (