diff options
author | Deniz Akşimşek <deniz@denizaksimsek.com> | 2022-05-16 12:27:01 +0300 |
---|---|---|
committer | Deniz Akşimşek <deniz@denizaksimsek.com> | 2022-05-16 12:27:01 +0300 |
commit | 44d2d6d244b575a3960f0f9adfeaf5a9810b43a1 (patch) | |
tree | 3c94bf0956772d783093885c3082efbf52441373 | |
parent | 77df6301f193eed1917ca30e5bf31f689302e2b5 (diff) | |
download | missing-44d2d6d244b575a3960f0f9adfeaf5a9810b43a1.tar.gz missing-44d2d6d244b575a3960f0f9adfeaf5a9810b43a1.zip |
Switch to Deno & Lume
Minified CSS build doesn't work.
There are some weird character encoding glitches.
-rw-r--r-- | .vscode/settings.json | 3 | ||||
-rw-r--r-- | build/postcss.js | 75 | ||||
-rw-r--r-- | build/postcss.ts | 69 | ||||
-rw-r--r-- | deno.json | 7 | ||||
-rw-r--r-- | import_map.json | 5 | ||||
-rw-r--r-- | www/_build/filters.ts | 55 | ||||
-rw-r--r-- | www/_build/get-dates-from-git.ts | 28 | ||||
-rw-r--r-- | www/_build/highlighting.ts | 16 | ||||
-rw-r--r-- | www/_build/util.ts | 16 | ||||
-rw-r--r-- | www/_config.ts | 42 | ||||
-rw-r--r-- | www/_includes/layout.eta (renamed from www/includes/layout.html) | 4 | ||||
-rw-r--r-- | www/_includes/prose.eta | 7 | ||||
-rw-r--r-- | www/demos.md | 8 | ||||
-rw-r--r-- | www/demos/blogpost.html | 2 | ||||
-rw-r--r-- | www/demos/cards.html | 2 | ||||
-rw-r--r-- | www/demos/grid.html | 2 | ||||
-rw-r--r-- | www/demos/html5.html | 2 | ||||
-rw-r--r-- | www/demos/landing-page.html | 2 | ||||
-rw-r--r-- | www/demos/shell.html | 2 | ||||
-rw-r--r-- | www/demos/tabs.html | 2 | ||||
-rw-r--r-- | www/docs/docs.json | 2 | ||||
-rw-r--r-- | www/includes/prose.html | 7 | ||||
-rw-r--r-- | www/index.md | 2 | ||||
-rw-r--r-- | www/pages/concepts.md | 2 | ||||
-rw-r--r-- | www/pages/rfp.md | 2 | ||||
-rw-r--r-- | www/playground.html | 2 |
26 files changed, 265 insertions, 101 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index fe2f34f..32b38a8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,6 @@ "titleBar.inactiveBackground": "#5a938099", "titleBar.inactiveForeground": "#e7e7e799" }, - "peacock.color": "#5a9380" + "peacock.color": "#5a9380", + "deno.enable": true }
\ No newline at end of file diff --git a/build/postcss.js b/build/postcss.js deleted file mode 100644 index 0111630..0000000 --- a/build/postcss.js +++ /dev/null @@ -1,75 +0,0 @@ -import { readFile, mkdir, writeFile } from 'node:fs/promises' -import { join, dirname } from 'node:path' -import { fileURLToPath } from 'node:url' -import { brotliCompress as brotli, gzip } from 'node:zlib' - -import postcss from 'postcss' - -// Plugins -import presetEnv from 'postcss-preset-env' -import atImport from 'postcss-import' -import importGlob from 'postcss-import-ext-glob' -import mixins from 'postcss-mixins' -import cssnano from 'cssnano' - - -// Paths -const __dirname = dirname(fileURLToPath(import.meta.url)) - -const entrypoint = join(__dirname, '../src/main.css') -const dist = join(__dirname, '../dist/') - -const prodTarget = join(dist, '/missing.min.css') -const devTarget = join(dist, '/missing.css') - - -const build = async () => { - const postcssMain = postcss([ - importGlob(), - atImport(), - presetEnv({ - browsers: 'supports css-variables', - stage: 0, - features: { - 'custom-properties': false, - }, - }), - mixins(), - ]) - - const postcssMinifier = postcss([cssnano({ preset: 'default' })]) - - const css = await readFile(entrypoint, { encoding: 'utf8' }) - - await mkdir(dist, { recursive: true }) - - const result = - await postcssMain.process(css, { from: entrypoint, to: devTarget }) - await w(result.css, devTarget) - - const { css: minifiedCSS } = - await postcssMinifier.process(result, { from: entrypoint, to: prodTarget }) - await w(minifiedCSS, prodTarget) - - await Promise.all([ - compress(minifiedCSS, brotli).then(c => w(c, prodTarget + ".br")), - compress(minifiedCSS, gzip ).then(c => w(c, prodTarget + ".gz")), - ]) -} - -const compress = (data, compressor) => new Promise((resolve, reject) => - compressor(data, (err, compressed) => { - if (err) reject(err) - else resolve(compressed) - }) -) - -const w = async (data, path) => { - await writeFile(path, data, { flag: "w" }) - console.log("Wrote " + path) -} - -build() - -export default build - diff --git a/build/postcss.ts b/build/postcss.ts new file mode 100644 index 0000000..15bd000 --- /dev/null +++ b/build/postcss.ts @@ -0,0 +1,69 @@ + +import { join, dirname, fromFileUrl } from 'https://deno.land/std@0.139.0/path/mod.ts' + +import { gzip } from "https://deno.land/x/compress@v0.4.5/mod.ts" +import { compress as brotli } from 'https://deno.land/x/brotli@v0.1.4/mod.ts' + +import postcss from "https://esm.sh/postcss@8.4.13" + +// Plugins +import nesting from 'https://esm.sh/postcss-nesting?deps=postcss@8.4.13' +import customSelectors from 'https://esm.sh/postcss-custom-selectors?deps=postcss@8.4.13' +import atImport from 'https://esm.sh/postcss-import?deps=postcss@8.4.13' +import importGlob from 'https://esm.sh/postcss-import-ext-glob?deps=postcss@8.4.13' +import mixins from 'https://esm.sh/postcss-mixins?deps=postcss@8.4.13' +import cssnano from 'https://esm.sh/cssnano?deps=postcss@8.4.13' + +// Paths +const __dirname = dirname(fromFileUrl(import.meta.url)) + +const entrypoint = join(__dirname, '../src/main.css') +const dist = join(__dirname, '../dist/') + +const prodTarget = join(dist, '/missing.min.css') +const devTarget = join(dist, '/missing.css') + +const dec = new TextDecoder +const enc = new TextEncoder + +const build = async () => { + const postcssMain = postcss([ + nesting(), + customSelectors(), + importGlob(), + atImport(), + mixins(), + ]) + + // const postcssMinifier = postcss([cssnano({ preset: 'default' })]) + + const css = dec.decode(await Deno.readFile(entrypoint)) + + await Deno.mkdir(dist, { recursive: true }) + + const result = + await postcssMain.process(css, { from: entrypoint, to: devTarget }) + const outputCss = enc.encode(result.css) + await w(outputCss, devTarget) + + // const minifyResult = + // await postcssMinifier.process(result, { from: entrypoint, to: prodTarget }) + // const minifiedCSS = enc.encode(minifyResult.css) + // await w(minifiedCSS, prodTarget) + + // await Promise.all([ + // w(brotli(minifiedCSS), prodTarget + ".br"), + // w(gzip (minifiedCSS), prodTarget + ".gz"), + // ]) +} + + +const w = async (data: Uint8Array, path: string | URL) => { + await Deno.writeFile(path, data) + console.log("Wrote " + path) +} + +build() + +export default build + diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..e56e2ba --- /dev/null +++ b/deno.json @@ -0,0 +1,7 @@ +{ + "importMap": "import_map.json", + "tasks": { + "build": "deno run -A https://deno.land/x/lume@v1.7.4/ci.ts --config=www/_config.ts", + "serve": "deno task build -- -s" + } +}
\ No newline at end of file diff --git a/import_map.json b/import_map.json new file mode 100644 index 0000000..6610cfe --- /dev/null +++ b/import_map.json @@ -0,0 +1,5 @@ +{ + "imports": { + "lume/": "https://deno.land/x/lume@v1.7.4/" + } +}
\ No newline at end of file diff --git a/www/_build/filters.ts b/www/_build/filters.ts new file mode 100644 index 0000000..460be6e --- /dev/null +++ b/www/_build/filters.ts @@ -0,0 +1,55 @@ +import type { Site } from "lume/core.ts"; + +/** + * Includes the filters: + * - `peekHtml` for generating a text extract from HTML + * - `repeat`, a loop with extra features + */ +export default () => { + return (site: Site) => { + site.filter("peekHtml", peekHtml) + site.filter("repeat", repeat) + } +} + +function peekHtml(html: string, n: number = 80) { + const text = html.replace(/<\/?[^>]+(>|$)/g, "").replace(/\s+/g, " ") + if (text.length < n) return text + else return text.slice(0, n - 1) + "…" +} + +interface LoopContext { + i: number + first: boolean + last?: boolean + sep(s: string): string +} + +function repeat<T>( + root: Iterable<T>, + cb: (t: T, loop: LoopContext) => void +): void { + // deno-lint-ignore no-explicit-any + function hasLength(a: any): a is { length: number } { + return "length" in a && typeof a.length === "number" + } + + let i = 0 + for (const t of root) { + const ctx: LoopContext = { + i, + first: i === 0, + sep(s) { + return this.last ? "" : s + } + } + + if (hasLength(root)) { + ctx.last = i === root.length - 1 + } + + cb(t, ctx) + i++ + } +} + diff --git a/www/_build/get-dates-from-git.ts b/www/_build/get-dates-from-git.ts new file mode 100644 index 0000000..7f65a1e --- /dev/null +++ b/www/_build/get-dates-from-git.ts @@ -0,0 +1,28 @@ +import type { Site, Page } from "lume/core.ts"; +import { exec } from "./util.ts"; + +/** + * Set created and last modified dates for pages by looking at Git history. + */ +export default () => { + return (site: Site) => { + site.preprocess("*", async (page: Page) => { + // Pull content dates from git. + + const gitLog = await exec([ + "git", "log", // git commits + "--follow", // handle renames + "--format=%aI", // commit date, as ISO date + "www" + page.src.path + page.src.ext // for this file + ]) + + const dates = gitLog.split("\n") + dates.pop() // remove trailing newline + + if (dates.length === 0) return + + if (dates.length > 1) page.data["last modified"] = new Date(dates[0]) + page.data.date = new Date(dates[dates.length - 1]) + }) + } +} diff --git a/www/_build/highlighting.ts b/www/_build/highlighting.ts new file mode 100644 index 0000000..b314688 --- /dev/null +++ b/www/_build/highlighting.ts @@ -0,0 +1,16 @@ + +import prismHighlight from "https://raw.githubusercontent.com/lumeland/experimental-plugins/main/prism/mod.ts" +import Prism from "https://raw.githubusercontent.com/lumeland/experimental-plugins/main/prism/deps.ts" +import prismHyperscript from "https://esm.sh/prism-hyperscript" +import type { Site } from "lume/core.ts" + +/** + * Highlight code, including _hyperscript, with Prism. + */ +export default () => { + prismHyperscript(Prism) + + return (site: Site) => { + site.use(prismHighlight()) + } +} diff --git a/www/_build/util.ts b/www/_build/util.ts new file mode 100644 index 0000000..8425d6a --- /dev/null +++ b/www/_build/util.ts @@ -0,0 +1,16 @@ + +export async function exec(cmd: string[]) { + const proc = await Deno.run({ + cmd, + stdout: "piped", + stdin: "null" + }) + + let str = "" + const decoder = new TextDecoder + const buf = new Uint8Array(1024); + const n = await proc.stdout.read(buf) as number + str += decoder.decode(buf.subarray(0, n)) + + return str +} diff --git a/www/_config.ts b/www/_config.ts new file mode 100644 index 0000000..498a49d --- /dev/null +++ b/www/_config.ts @@ -0,0 +1,42 @@ + +import "https://deno.land/x/dotenv@v3.2.0/load.ts" + +import lume from "lume/mod.ts" +import date from "lume/plugins/date.ts" +import basePath from "lume/plugins/base_path.ts" +import resolveUrls from "lume/plugins/resolve_urls.ts" +import eta from "lume/plugins/eta.ts" + +import highlighting from "./_build/highlighting.ts" +import getDatesFromGit from "./_build/get-dates-from-git.ts" +import myFilters from "./_build/filters.ts" + +import mdAttrs from "https://esm.sh/markdown-it-attrs" +import mdDeflist from "https://esm.sh/markdown-it-deflist" +import mdContainer from "https://esm.sh/@gerhobbelt/markdown-it-container" + +import postcss from "../build/postcss.ts" + +export default lume( + { + location: new URL("https://missing.style/"), + src: "www", + dest: "dist", + }, { + markdown: { + plugins: [ + mdAttrs, + mdDeflist, + [mdContainer, "box"], + ] + } + } + ) + .addEventListener("afterBuild", postcss) + .use(date()) + .use(highlighting()) + .use(basePath()) + .use(resolveUrls()) + .use(eta()) + .use(myFilters()) + .use(getDatesFromGit()) diff --git a/www/includes/layout.html b/www/_includes/layout.eta index 6906d2f..32d6088 100644 --- a/www/includes/layout.html +++ b/www/_includes/layout.eta @@ -2,7 +2,7 @@ --- <!doctype html> -<html lang="{{ lang | d(en) }}"> +<html lang="<%= it.lang ?? "en" %>"> <head> <meta charset="utf=8"> <meta name="viewport" content="width=device-width"> @@ -11,7 +11,7 @@ <script src="https://unpkg.com/hyperscript.org"></script> </head> <body> - {{ content | safe }} + <%~ content %> <footer> <p><a href="/">Missing.css</a>, from diff --git a/www/_includes/prose.eta b/www/_includes/prose.eta new file mode 100644 index 0000000..6037d7a --- /dev/null +++ b/www/_includes/prose.eta @@ -0,0 +1,7 @@ +--- +layout: layout.eta +--- + +<main> + <%~ content %> +</main> diff --git a/www/demos.md b/www/demos.md index f2417d6..b4f21a7 100644 --- a/www/demos.md +++ b/www/demos.md @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta --- <main> @@ -7,9 +7,9 @@ layout: layout.html # Demos <ul class='list-of-links'> -{% for demo in collections.demos -%} -<li><p><a href="{{demo.url}}">{{demo.data.name}}</a> -{% endfor %} +<% for (const demo in collections.demos _%> +<li><p><a href="<%= demo.url %>"><%= demo.data.name %></a> +<% } %> </ul> </main> diff --git a/www/demos/blogpost.html b/www/demos/blogpost.html index efed34a..7d0e0f5 100644 --- a/www/demos/blogpost.html +++ b/www/demos/blogpost.html @@ -1,6 +1,6 @@ --- name: Blog post -layout: layout.html +layout: layout.eta --- <main> diff --git a/www/demos/cards.html b/www/demos/cards.html index daebd0e..23adec1 100644 --- a/www/demos/cards.html +++ b/www/demos/cards.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta name: Cards --- diff --git a/www/demos/grid.html b/www/demos/grid.html index 798b8e6..c5ab2c0 100644 --- a/www/demos/grid.html +++ b/www/demos/grid.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta name: Grid --- diff --git a/www/demos/html5.html b/www/demos/html5.html index 57895f9..4ba1e90 100644 --- a/www/demos/html5.html +++ b/www/demos/html5.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta name: HTML5 Element Catalog --- diff --git a/www/demos/landing-page.html b/www/demos/landing-page.html index a7b2692..aad0833 100644 --- a/www/demos/landing-page.html +++ b/www/demos/landing-page.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta name: Landing Page --- diff --git a/www/demos/shell.html b/www/demos/shell.html index 1bc46cb..80676d8 100644 --- a/www/demos/shell.html +++ b/www/demos/shell.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta name: Shell --- diff --git a/www/demos/tabs.html b/www/demos/tabs.html index 4644354..f7794b0 100644 --- a/www/demos/tabs.html +++ b/www/demos/tabs.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta name: Tabs --- diff --git a/www/docs/docs.json b/www/docs/docs.json index c19f8c4..f03e27b 100644 --- a/www/docs/docs.json +++ b/www/docs/docs.json @@ -1,3 +1,3 @@ { - "layout": "prose.html" + "layout": "prose.eta" }
\ No newline at end of file diff --git a/www/includes/prose.html b/www/includes/prose.html deleted file mode 100644 index 4c88c0b..0000000 --- a/www/includes/prose.html +++ /dev/null @@ -1,7 +0,0 @@ ---- -layout: layout.html ---- - -<main> - {{ content | safe }} -</main> diff --git a/www/index.md b/www/index.md index ce30715..da19e9b 100644 --- a/www/index.md +++ b/www/index.md @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta --- <main> diff --git a/www/pages/concepts.md b/www/pages/concepts.md index f5cadd1..dbd4fd6 100644 --- a/www/pages/concepts.md +++ b/www/pages/concepts.md @@ -1,6 +1,6 @@ --- permalink: concepts/ -layout: prose.html +layout: prose.eta --- # Concepts diff --git a/www/pages/rfp.md b/www/pages/rfp.md index 65719c7..bbfa865 100644 --- a/www/pages/rfp.md +++ b/www/pages/rfp.md @@ -1,6 +1,6 @@ --- permalink: rfp/ -layout: prose.html +layout: prose.eta --- # missing CSS Library RFP diff --git a/www/playground.html b/www/playground.html index c0c22d6..8addcde 100644 --- a/www/playground.html +++ b/www/playground.html @@ -1,5 +1,5 @@ --- -layout: layout.html +layout: layout.eta permalink: /playground/ --- |