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