1import lume from "lume/mod.ts"; 2import date from "lume/plugins/date.ts"; 3import toml from "lume/plugins/toml.ts"; 4 5// Images 6import picture from "lume/plugins/picture.ts"; 7import transformImages from "lume/plugins/transform_images.ts"; 8 9// URL Management 10import slugifyUrls from "lume/plugins/slugify_urls.ts"; 11import resolveUrls from "lume/plugins/resolve_urls.ts"; 12 13// File Generation 14import feed from "lume/plugins/feed.ts"; 15import metas from "lume/plugins/metas.ts"; 16import readingInfo from "lume/plugins/reading_info.ts"; 17import robots from "lume/plugins/robots.ts"; 18import sitemap from "lume/plugins/sitemap.ts"; 19import sourceMaps from "lume/plugins/source_maps.ts"; 20 21// Optimization 22import brotli from "lume/plugins/brotli.ts"; 23import gzip from "lume/plugins/gzip.ts"; 24import minifyHTML from "lume/plugins/minify_html.ts"; 25import svgo from "lume/plugins/svgo.ts"; 26 27// Markdown-it plugins 28import { BiDirectionalLinks } from "@nolebase/markdown-it-bi-directional-links"; 29import { default as mdItObsidianCallouts } from "markdown-it-obsidian-callouts"; 30 31// Additional external plugins 32import toc from "lume_markdown_plugins/toc.ts"; 33import footnotes from "./plugins/footnotes.ts"; 34import slugify from "npm:@sindresorhus/slugify"; 35 36// CSS 37// // Base dependencies 38import tailwindcss from "lume/plugins/tailwindcss.ts"; 39// // Fonts 40import googleFonts from "lume/plugins/google_fonts.ts"; 41// // Optimization 42import lightningcss from "lume/plugins/lightningcss.ts"; 43 44// Custom Plugins 45import validateHTML from "./plugins/validateHTML.ts"; 46import openInEditor from "./plugins/openInEditor.ts"; 47 48// Disabled Plugins: 49// import nav from "lume/plugins/nav.ts"; 50// import og_images from "lume/plugins/og_images.ts"; 51// import pagefind from "lume/plugins/pagefind.ts"; 52// import purgecss from "lume/plugins/purgecss.ts"; 53// import relations from "lume/plugins/relations.ts"; 54// import sri from "lume/plugins/sri.ts"; 55 56// To Add: 57// https://deno.land/x/lume_shiki@0.0.16 58 59const site = lume({ 60 src: "./src", 61 location: new URL("https://pyrox.dev"), 62}, { 63 markdown: { 64 plugins: [ 65 [BiDirectionalLinks, { 66 dir: Deno.cwd() + "/src/", 67 stillRenderNoMatched: false, 68 }], 69 mdItObsidianCallouts, 70 footnotes, 71 ], 72 }, 73}); 74 75// Copy Static Files 76site.add(".css"); 77site.add("static/.well-known", ".well-known"); 78site.add(".woff2"); 79// Tailwind CSS 80site.use(tailwindcss()); 81 82// Fonts 83site.use( 84 googleFonts({ 85 subsets: ["latin", "latin-ext"], 86 folder: "/static/fonts/", 87 cssFile: "/static/fonts.css", 88 fonts: 89 "https://fonts.googleapis.com/css2?family=IBM+Plex+Serif:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900", 90 }), 91); 92 93site.use(picture()); 94site.use(transformImages()); 95site.add(".png"); 96// site.use(relations()); 97site.use(slugifyUrls()); 98site.use(svgo()); 99site.use(toml()); 100 101// Metadata 102site.use( 103 date({ 104 formats: { 105 SHORT_DATE: "yyyy-MM-dd", 106 POST_DATE: "dd MMM, yyyy", 107 }, 108 }), 109); 110site.use(metas()); 111site.use(readingInfo({ 112 // Number taken from: 113 // https://reader.ku.edu/sites/reader/files/2024-01/How%20many%20words%20do%20we%20read%20per%20minute%20(1).pdf 114 wordsPerMinute: 238, 115})); 116site.use(toc({ 117 slugify: (s: string) => slugify(s), 118})); 119 120// Ensure all URLs are to the final page links 121site.use(resolveUrls()); 122 123// RSS/JSON Feed Generation 124site.use( 125 feed({ 126 output: ["/blog.rss", "/blog.json"], 127 query: "category=blog", 128 info: { 129 title: "dish blog", 130 description: "dish's thoughts on many things", 131 published: new Date(), 132 lang: "en", 133 generator: true, 134 authorName: "dish", 135 authorUrl: "https://blog.pyrox.dev", 136 }, 137 items: { 138 title: "=title", 139 description: "=summary", 140 published: "=published", 141 updated: "=updated", 142 content: "$.e-content", 143 lang: "=lang", 144 image: "=banner", 145 authorName: "=author.name", 146 authorUrl: "=author.url", 147 }, 148 }), 149); 150 151// CSS postprocessing 152site.use(lightningcss({ 153 options: { 154 minify: true, 155 }, 156})); 157 158site.use(sitemap()); 159 160// Source Map Generation 161// Applies to CSS and JS 162site.use(sourceMaps()); 163 164site.use(validateHTML()); 165 166site.data("production", Deno.env.get("PRODUCTION") == "true"); 167// This only applies in dev mode 168if (Deno.env.get("PRODUCTION") == "false") { 169 site.use(openInEditor()); 170 site.add("static/scripts/open-in-editor.js"); 171} 172 173// This only applies in prod mode 174if (Deno.env.get("PRODUCTION") == "true") { 175 // Minify HTML 176 site.use(minifyHTML({ 177 options: { 178 do_not_minify_doctype: true, 179 keep_closing_tags: false, 180 keep_html_and_head_opening_tags: true, 181 keep_spaces_between_attributes: true, 182 ensure_spec_compliant_unquoted_attribute_values: true, 183 keep_comments: false, 184 }, 185 })); 186} 187 188// robots.txt generation 189site.use( 190 robots({ 191 disallow: [ 192 "AI2Bot", 193 "Amazonbot", 194 "Applebot-Extended", 195 "Bytespider", 196 "ChatGPT-User", 197 "ClaudeBot", 198 "Diffbot", 199 "DuckAssistBot", 200 "FacebookBot", 201 "GPTBot", 202 "Google-Extended", 203 "Meta-ExternalAgent", 204 "Meta-ExternalFetcher", 205 "OAI-SearchBot", 206 "Operator", 207 "PanguBot", 208 "PerplexityBot", 209 "SemrushBot", 210 "SemrushBot-OCOB", 211 "Timpibot", 212 "Webzio-Extended", 213 "YouBot", 214 "cohere-training-data-crawler", 215 "omgili", 216 "t3versions", 217 ], 218 }), 219); 220 221// Compress everything with Brotli/Gzip 222site.use( 223 brotli({ 224 quality: 11, 225 extensions: [ 226 ".html", 227 ".css", 228 ".js", 229 ".mjs", 230 ".svg", 231 ".json", 232 ".xml", 233 ".txt", 234 ".rss", 235 ".map", 236 ], 237 }), 238); 239site.use( 240 gzip({ 241 extensions: [ 242 ".html", 243 ".css", 244 ".js", 245 ".mjs", 246 ".svg", 247 ".json", 248 ".xml", 249 ".txt", 250 ".rss", 251 ".map", 252 ], 253 }), 254); 255 256// Open in Editor in Dev mode 257// Get current commit as a version number 258// Taken from https://github.com/pixeldesu/pixelde.su/blob/main/_config.ts 259const commitCmd = new Deno.Command("git", { args: ["rev-parse", "HEAD"] }); 260const { stdout } = await commitCmd.output(); 261const commitHash = new TextDecoder().decode(stdout); 262site.data("commit", commitHash); 263 264export default site;