timconspicuous.neocities.org

Lume 3.0 migration

+58 -180
+2 -3
.gitignore
··· 1 1 _cache 2 - _site 2 + public/ 3 3 deno.lock 4 - .vscode 5 - .env 4 + env
-83
_cms.ts
··· 1 - import lumeCMS from "lume/cms/mod.ts"; 2 - 3 - const cms = lumeCMS(); 4 - 5 - cms.document( 6 - "home: The profile page", 7 - "src:index.yml", 8 - [ 9 - { 10 - type: "hidden", 11 - name: "layout", 12 - value: "layouts/home.vto", 13 - }, 14 - { 15 - type: "object", 16 - name: "header", 17 - description: "The header of the page", 18 - fields: [ 19 - "title: text", 20 - "description: markdown", 21 - "avatar: file", 22 - ], 23 - }, 24 - { 25 - type: "object", 26 - name: "metas", 27 - description: "Data for the meta tags", 28 - fields: [ 29 - "title: text", 30 - "description: text", 31 - "image: text", 32 - "twitter: text", 33 - "generator: checkbox", 34 - ], 35 - }, 36 - { 37 - name: "links", 38 - type: "object-list", 39 - description: "The list of links.", 40 - fields: [ 41 - { 42 - type: "text", 43 - name: "type", 44 - description: 45 - "The type of link. It uses the icons and colors from https://simpleicons.org/. For example, 'github', 'instagram', etc.", 46 - options: [ 47 - "github", 48 - "instagram", 49 - "linkedin", 50 - "x", 51 - "youtube", 52 - "facebook", 53 - "tiktok", 54 - "patreon", 55 - "paypal", 56 - "mastodon", 57 - "discord", 58 - "spotify", 59 - "opencollective", 60 - "twitch", 61 - ], 62 - }, 63 - "text: text", 64 - "href: text", 65 - "only_icon: checkbox", 66 - ], 67 - }, 68 - { 69 - name: "extra_head", 70 - type: "code", 71 - description: "Extra content to include in the <head> tag", 72 - }, 73 - { 74 - name: "footer", 75 - type: "markdown", 76 - description: "The footer of the page", 77 - }, 78 - ], 79 - ); 80 - 81 - cms.upload("uploads: Uploaded files", "src:*{.jpg,.svg}"); 82 - 83 - export default cms;
+10 -3
_config.ts
··· 1 1 import lume from "lume/mod.ts"; 2 - import plugins from "./plugins.ts"; 2 + import jsx from "lume/plugins/jsx.ts"; 3 + import postcss from "lume/plugins/postcss.ts"; 4 + import simpleIcons from "https://deno.land/x/lume_icon_plugins@v0.2.4/simpleicons.ts"; 3 5 4 6 const site = lume({ 5 7 src: "./src", 8 + dest: "./public" 6 9 }); 7 10 8 - site.use(plugins()); 11 + site.use(jsx()); 12 + site.use(postcss()); 13 + site.add("styles.css"); 14 + site.copy([".jpg", ".svg"]); 15 + site.use(simpleIcons()); 9 16 10 - export default site; 17 + export default site;
+33 -23
deno.json
··· 1 1 { 2 - "imports": { 3 - "lume/": "https://deno.land/x/lume@v2.4.2/", 4 - "lume/cms/": "https://cdn.jsdelivr.net/gh/lumeland/cms@0.7.3/" 5 - }, 6 - "tasks": { 7 - "lume": "echo \"import 'lume/cli.ts'\" | deno run -A -", 8 - "build": "deno task lume", 9 - "serve": "deno task lume -s" 10 - }, 11 - "compilerOptions": { 12 - "types": [ 13 - "lume/types.ts" 14 - ], 15 - "jsx": "react-jsx", 16 - "jsxImportSource": "npm:preact" 17 - }, 18 - "exclude": [ 19 - "./_site" 20 - ], 21 - "fmt": { 22 - "useTabs": true, 23 - "indentWidth": 4 24 - } 2 + "imports": { 3 + "lume/": "https://deno.land/x/lume@v3.0.8/", 4 + "lume/cms/": "https://cdn.jsdelivr.net/gh/lumeland/cms@0.12.5/", 5 + "lume/jsx-runtime": "https://deno.land/x/ssx@v0.1.12/jsx-runtime.ts" 6 + }, 7 + "tasks": { 8 + "lume": "echo \"import 'lume/cli.ts'\" | deno run -A -", 9 + "build": "deno task lume", 10 + "serve": "deno task lume -s" 11 + }, 12 + "compilerOptions": { 13 + "types": [ 14 + "lume/types.ts" 15 + ], 16 + "jsx": "react-jsx", 17 + "jsxImportSource": "lume" 18 + }, 19 + "exclude": [ 20 + "./public" 21 + ], 22 + "fmt": { 23 + "useTabs": true, 24 + "indentWidth": 4 25 + }, 26 + "unstable": [ 27 + "temporal", 28 + "fmt-component" 29 + ], 30 + "lint": { 31 + "plugins": [ 32 + "https://deno.land/x/lume@v3.0.8/lint.ts" 33 + ] 34 + } 25 35 }
-25
mod.ts
··· 1 - import plugins from "./plugins.ts"; 2 - 3 - import "lume/types.ts"; 4 - 5 - export default function () { 6 - return (site: Lume.Site) => { 7 - // Configure the site 8 - site.use(plugins()); 9 - 10 - // Add remote files 11 - const files = [ 12 - "_includes/css/header.css", 13 - "_includes/css/link.css", 14 - "_includes/layouts/base.vto", 15 - "index.yml", 16 - "styles.css", 17 - "favicon.svg", 18 - "avatar.jpg", 19 - ]; 20 - 21 - for (const file of files) { 22 - site.remoteFile(file, import.meta.resolve(`./src/${file}`)); 23 - } 24 - }; 25 - }
-32
plugins.ts
··· 1 - import "lume/types.ts"; 2 - import Color from "npm:colorjs.io@0.5.2"; 3 - import simpleIcons from "https://deno.land/x/lume_icon_plugins@v0.1.1/simpleicons.ts"; 4 - import basePath from "lume/plugins/base_path.ts"; 5 - import favicon from "lume/plugins/favicon.ts"; 6 - import metas from "lume/plugins/metas.ts"; 7 - import postcss from "lume/plugins/postcss.ts"; 8 - import transformImages from "lume/plugins/transform_images.ts"; 9 - import jsx from "lume/plugins/jsx_preact.ts"; 10 - 11 - /** Configure the site */ 12 - export default function () { 13 - return (site: Lume.Site) => { 14 - site.use(postcss()) 15 - .use(metas()) 16 - .use(favicon()) 17 - .use(basePath()) 18 - .mergeKey("extra_head", "stringArray") 19 - .use(transformImages()) 20 - .use(simpleIcons()) 21 - .use(jsx()); 22 - 23 - site.data("textColor", (hex: string) => { 24 - const color = new Color(`#${hex}`); 25 - const onWhite = Math.abs(color.contrastWCAG21("white")); 26 - const onBlack = Math.abs(color.contrastWCAG21("black")); 27 - return (onWhite + 0.5) > onBlack ? "white" : "black"; 28 - }); 29 - 30 - site.copy([".jpg", ".webp", ".png"]); 31 - }; 32 - }
+11 -6
src/_components/Button.tsx
··· 23 23 // Function to determine text color based on background color brightness 24 24 const getTextColor = (backgroundColor: string) => { 25 25 // Remove the # if present and pad to 6 characters if needed 26 - const color = (backgroundColor.startsWith("#") 27 - ? backgroundColor.slice(1) 28 - : backgroundColor 29 - ).padEnd(6, backgroundColor.length <= 4 ? backgroundColor.slice(-1) : ""); 26 + const color = 27 + (backgroundColor.startsWith("#") 28 + ? backgroundColor.slice(1) 29 + : backgroundColor).padEnd( 30 + 6, 31 + backgroundColor.length <= 4 32 + ? backgroundColor.slice(-1) 33 + : "", 34 + ); 30 35 31 36 // Convert hex to RGB 32 37 const r = parseInt(color.substring(0, 2), 16); ··· 34 39 const b = parseInt(color.substring(4, 6), 16); 35 40 36 41 // Calculate luminance to determine perceived brightness 37 - const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b); 42 + const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b; 38 43 39 44 // Return black for light backgrounds, white for dark ones 40 45 return luminance > 128 ? "#000000" : "#ffffff"; ··· 55 60 }} 56 61 /> 57 62 ); 58 - } 63 + }
-2
src/_components/Linktree.tsx
··· 35 35 </> 36 36 ); 37 37 } 38 - 39 - export const css = "@import './_components/Button.css';";
+1 -3
src/_includes/layout.tsx
··· 3 3 const description = data.header?.description || data.description || ""; 4 4 const avatar = data.header?.avatar || "/avatar.jpg"; 5 5 const footer = data.footer || ""; 6 - const links = data.links || []; 7 6 8 7 return ( 9 8 <html lang={data.lang || "en"}> ··· 26 25 media="(prefers-color-scheme: dark)" 27 26 /> 28 27 <link rel="stylesheet" href="/styles.css" /> 29 - <link rel="stylesheet" href="/components.css" /> 30 28 <link 31 29 rel="icon" 32 30 type="image/png" 33 31 sizes="32x32" 34 - href="/favicon.png" 32 + href="/favicon.svg" 35 33 /> 36 34 <link rel="canonical" href={data.url} /> 37 35 {data.extra_head?.map((item: string) => (
src/index.tsx src/index.page.tsx
+1
src/styles.css
··· 1 1 /* Lume's design system */ 2 2 @import "https://unpkg.com/@lumeland/ds@0.5.2/ds.css"; 3 + @import "./_components/Button.css"; 3 4 4 5 body { 5 6 display: grid;