From 55fabb4b05a6147db0a1221d8d6b91065ccf8917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 17 Oct 2024 12:39:49 +0200 Subject: [PATCH 1/9] tailwind --- package.json | 1 + src/build.ts | 6 +- src/preview.ts | 6 +- src/rollup.ts | 41 ++++- src/style/default.css | 1 + src/style/tailwind.css | 3 + yarn.lock | 393 +++++++++++++++++++++++++++++++++++++++-- 7 files changed, 430 insertions(+), 21 deletions(-) create mode 100644 src/style/tailwind.css diff --git a/package.json b/package.json index 2ec036819..385530d91 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "cross-env": "^7.0.3", "d3-dsv": "^3.0.1", "d3-format": "^3.1.0", + "esbuild-plugin-tailwindcss": "^1.2.1", "eslint": "^8.50.0", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", diff --git a/src/build.ts b/src/build.ts index ccf9df04d..c5e18e003 100644 --- a/src/build.ts +++ b/src/build.ts @@ -164,10 +164,10 @@ export async function build( effects.output.write(`${faint("build")} ${path} ${faint("→")} `); if (specifier.startsWith("observablehq:theme-")) { const match = /^observablehq:theme-(?[\w-]+(,[\w-]+)*)?\.css$/.exec(specifier); - contents = await bundleStyles({theme: match!.groups!.theme?.split(",") ?? [], minify: true}); + contents = await bundleStyles({theme: match!.groups!.theme?.split(",") ?? [], minify: true, root}); } else { const clientPath = getClientPath(path.slice("/_observablehq/".length)); - contents = await bundleStyles({path: clientPath, minify: true}); + contents = await bundleStyles({path: clientPath, minify: true, root}); } const hash = createHash("sha256").update(contents).digest("hex").slice(0, 8); const alias = applyHash(path, hash); @@ -181,7 +181,7 @@ export async function build( } else if (!/^\w+:/.test(specifier)) { const sourcePath = join(root, specifier); effects.output.write(`${faint("build")} ${sourcePath} ${faint("→")} `); - const contents = await bundleStyles({path: sourcePath, minify: true}); + const contents = await bundleStyles({path: sourcePath, minify: true, root}); const hash = createHash("sha256").update(contents).digest("hex").slice(0, 8); const alias = applyHash(join("/_import", specifier), hash); aliases.set(resolveStylesheetPath(root, specifier), alias); diff --git a/src/preview.ts b/src/preview.ts index 42f3c931a..710d2335c 100644 --- a/src/preview.ts +++ b/src/preview.ts @@ -132,13 +132,13 @@ export class PreviewServer { } else if (pathname === "/_observablehq/minisearch.json") { end(req, res, await searchIndex(config), "application/json"); } else if ((match = /^\/_observablehq\/theme-(?[\w-]+(,[\w-]+)*)?\.css$/.exec(pathname))) { - end(req, res, await bundleStyles({theme: match.groups!.theme?.split(",") ?? []}), "text/css"); + end(req, res, await bundleStyles({theme: match.groups!.theme?.split(",") ?? [], root}), "text/css"); } else if (pathname.startsWith("/_observablehq/") && pathname.endsWith(".js")) { const path = getClientPath(pathname.slice("/_observablehq/".length)); end(req, res, await rollupClient(path, root, pathname), "text/javascript"); } else if (pathname.startsWith("/_observablehq/") && pathname.endsWith(".css")) { const path = getClientPath(pathname.slice("/_observablehq/".length)); - end(req, res, await bundleStyles({path}), "text/css"); + end(req, res, await bundleStyles({path, root}), "text/css"); } else if (pathname.startsWith("/_node/") || pathname.startsWith("/_jsr/")) { send(req, pathname, {root: join(root, ".observablehq", "cache")}).pipe(res); } else if (pathname.startsWith("/_npm/")) { @@ -151,7 +151,7 @@ export class PreviewServer { if (module) { const sourcePath = join(root, path); await access(sourcePath, constants.R_OK); - end(req, res, await bundleStyles({path: sourcePath}), "text/css"); + end(req, res, await bundleStyles({path: sourcePath, root}), "text/css"); return; } } else if (pathname.endsWith(".js")) { diff --git a/src/rollup.ts b/src/rollup.ts index d380630a0..7ae3367c3 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -1,11 +1,14 @@ +import {writeFileSync} from "fs"; import {extname, resolve} from "node:path/posix"; import {nodeResolve} from "@rollup/plugin-node-resolve"; import {simple} from "acorn-walk"; import {build} from "esbuild"; +import type {Plugin as ESBuildPlugin} from "esbuild"; +import {tailwindPlugin} from "esbuild-plugin-tailwindcss"; import type {AstNode, OutputChunk, Plugin, ResolveIdResult} from "rollup"; import {rollup} from "rollup"; import esbuild from "rollup-plugin-esbuild"; -import {getClientPath, getStylePath} from "./files.js"; +import {getClientPath, getStylePath, maybeStat} from "./files.js"; import type {StringLiteral} from "./javascript/source.js"; import {getStringLiteralValue, isStringLiteral} from "./javascript/source.js"; import {resolveNpmImport} from "./npm.js"; @@ -36,17 +39,20 @@ function rewriteInputsNamespace(code: string) { export async function bundleStyles({ minify = false, path, - theme + theme, + root }: { minify?: boolean; path?: string; theme?: string[]; + root: string; }): Promise { const result = await build({ bundle: true, ...(path ? {entryPoints: [path]} : {stdin: {contents: renderTheme(theme!), loader: "css"}}), write: false, minify, + plugins: [await tailwindConfig(root)], alias: STYLE_MODULES }); let text = result.outputFiles[0].text; @@ -184,3 +190,34 @@ function importMetaResolve(path: string, resolveImport: ImportResolver): Plugin } }; } + +// Create a tailwind plugin, configured to reference as content the project +// files that might contain tailwind class names, and the 'tw-' prefix. If a +// tailwind.config.js is present in the project root, we import and merge it. +async function tailwindConfig(root: string): Promise { + const twconfig = "tailwind.config.js"; + const configPath = `./${root}/.observablehq/cache/${twconfig}`; + const s = await maybeStat(`./${root}/${twconfig}`); + const m = await maybeStat(configPath); + if (!m || !s || !(m.mtimeMs > s.mtimeMs)) { + writeFileSync( + configPath, + ` +// File generated by rollup.ts; to configure tailwind, edit ${root}/tailwind.config.js +${s ? `import config from "../../${twconfig}"` : "const config = {}"}; +export default { + content: { + files: [ + "${root}/**/*.{js,md}" /* pages and components */, + "${root}/.observablehq/cache/**/*.md" /* page loaders */, + "${root}/.observablehq/cache/_import/**/*.js" /* transpiled components */ + ] + }, + prefix: 'tw-', + ...config +}; +` + ); + } + return tailwindPlugin({configPath}); +} diff --git a/src/style/default.css b/src/style/default.css index 29a2865e0..9802917c2 100644 --- a/src/style/default.css +++ b/src/style/default.css @@ -1,3 +1,4 @@ +@import url("./tailwind.css"); @import url("./global.css"); @import url("./layout.css"); @import url("./grid.css"); diff --git a/src/style/tailwind.css b/src/style/tailwind.css new file mode 100644 index 000000000..ebbedf96c --- /dev/null +++ b/src/style/tailwind.css @@ -0,0 +1,3 @@ +/* @import "tailwindcss/base"; */ +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; diff --git a/yarn.lock b/yarn.lock index 27820eaa7..d54bd2d3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + "@asamuzakjp/dom-selector@^2.0.1": version "2.0.2" resolved "https://registry.yarnpkg.com/@asamuzakjp/dom-selector/-/dom-selector-2.0.2.tgz#160f601d9a465bbdf641410afdc527f37325506e" @@ -343,17 +348,31 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.12": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.24": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -868,6 +887,11 @@ ansi-styles@^6.1.0, ansi-styles@^6.2.1: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -876,6 +900,11 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -974,6 +1003,18 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +autoprefixer@^10.4.13: + version "10.4.20" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" + integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== + dependencies: + browserslist "^4.23.3" + caniuse-lite "^1.0.30001646" + fraction.js "^4.3.7" + normalize-range "^0.1.2" + picocolors "^1.0.1" + postcss-value-parser "^4.2.0" + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -1035,6 +1076,16 @@ browser-stdout@^1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== +browserslist@^4.23.3: + version "4.24.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.0.tgz#a1325fe4bc80b64fda169629fc01b3d6cecd38d4" + integrity sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A== + dependencies: + caniuse-lite "^1.0.30001663" + electron-to-chromium "^1.5.28" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + bundle-name@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" @@ -1075,11 +1126,21 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + camelcase@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001663: + version "1.0.30001669" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz#fda8f1d29a8bfdc42de0c170d7f34a9cf19ed7a3" + integrity sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w== + chai-http@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/chai-http/-/chai-http-4.4.0.tgz#bb8c346caa25b3c76118c68f7a7cecc0493669b8" @@ -1194,6 +1255,11 @@ commander@7: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1270,6 +1336,11 @@ css-tree@^2.3.1: mdn-data "2.0.30" source-map-js "^1.0.1" +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + cssstyle@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.1.0.tgz#161faee382af1bafadb6d3867a92a19bcb4aea70" @@ -1457,6 +1528,11 @@ dezalgo@^1.0.4: asap "^2.0.0" wrappy "1" +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + diff@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" @@ -1469,6 +1545,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -1493,6 +1574,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +electron-to-chromium@^1.5.28: + version "1.5.39" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.39.tgz#5cbe5200b43dff7b7c2bcb6bdacf65d514c76bb2" + integrity sha512-4xkpSR6CjuiaNyvwiWDI85N9AxsvbPawB8xc7yzLPonYTuP19BVgYweKyUMFtHEZgIcHWMt1ks5Cqx2m+6/Grg== + emoji-regex@^10.3.0: version "10.4.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" @@ -1627,6 +1713,16 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild-plugin-tailwindcss@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/esbuild-plugin-tailwindcss/-/esbuild-plugin-tailwindcss-1.2.1.tgz#2f88a54c9070fa8a20420eb47c5fd06f94c5a3d1" + integrity sha512-vPVSWBvUcxqBjObNTNA5vH0OhivbnQBeFfji4Q1QdyfaHUFd66R1ztskkTr8G1ipkGck/YsAZpgcQUdbGPofNQ== + dependencies: + autoprefixer "^10.4.13" + postcss "^8.4.21" + postcss-modules "^6.0.0" + tailwindcss "^3.2.4" + esbuild@^0.20.1: version "0.20.2" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" @@ -1686,7 +1782,7 @@ esbuild@~0.23.0: "@esbuild/win32-ia32" "0.23.1" "@esbuild/win32-x64" "0.23.1" -escalade@^3.1.1: +escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== @@ -1892,7 +1988,7 @@ fast-fifo@^1.2.0, fast-fifo@^1.3.2: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.2.9, fast-glob@^3.3.2: +fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -2005,6 +2101,11 @@ formidable@^2.1.2: once "^1.4.0" qs "^6.11.0" +fraction.js@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -2047,6 +2148,13 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +generic-names@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-4.0.0.tgz#0bd8a2fd23fe8ea16cbd0a279acd69c06933d9a3" + integrity sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A== + dependencies: + loader-utils "^3.2.0" + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2299,6 +2407,11 @@ iconv-lite@0.6, iconv-lite@0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -2548,11 +2661,6 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-unicode-supported@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" - integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== - is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -2618,6 +2726,11 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jiti@^1.21.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== + "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2724,6 +2837,21 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" +lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lilconfig@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + linkify-it@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" @@ -2731,6 +2859,11 @@ linkify-it@^5.0.0: dependencies: uc.micro "^2.0.0" +loader-utils@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" + integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -2738,6 +2871,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -2826,7 +2964,7 @@ methods@^1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.4: +micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -2963,16 +3101,50 @@ ms@2.1.3, ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + object-inspect@^1.13.1: version "1.13.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" @@ -3138,11 +3310,26 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== +picocolors@^1.0.1, picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + pkg-dir@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-8.0.0.tgz#8f3de8ba83d46b72a05c80bfd4e579f060fa91e2" @@ -3155,6 +3342,101 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" + integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== + dependencies: + lilconfig "^3.0.0" + yaml "^2.3.4" + +postcss-modules-extract-imports@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-modules@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-6.0.0.tgz#cac283dbabbbdc2558c45391cbd0e2df9ec50118" + integrity sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ== + dependencies: + generic-names "^4.0.0" + icss-utils "^5.1.0" + lodash.camelcase "^4.3.0" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + string-hash "^1.1.1" + +postcss-nested@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" + integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== + dependencies: + postcss-selector-parser "^6.1.1" + +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.21, postcss@^8.4.23: + version "8.4.47" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" + integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== + dependencies: + nanoid "^3.3.7" + picocolors "^1.1.0" + source-map-js "^1.2.1" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -3234,6 +3516,13 @@ react@^18.2.0: dependencies: loose-envify "^1.1.0" +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" @@ -3299,7 +3588,7 @@ resolve.exports@^2.0.2: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.22.1, resolve@^1.22.4: +resolve@^1.1.7, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3562,7 +3851,7 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-js@^1.0.1: +source-map-js@^1.0.1, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -3593,6 +3882,11 @@ streamx@^2.15.0: optionalDependencies: bare-events "^2.2.0" +string-hash@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== + "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -3700,6 +3994,19 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +sucrase@^3.32.0: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + superagent@^8.0.9: version "8.1.2" resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" @@ -3740,6 +4047,34 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tailwindcss@^3.2.4: + version "3.4.14" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.14.tgz#6dd23a7f54ec197b19159e91e3bb1e55e7aa73ac" + integrity sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.0" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -3802,6 +4137,20 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3841,6 +4190,11 @@ ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -3989,6 +4343,14 @@ untildify@^5.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-5.0.0.tgz#3e40c5dd67518cb8582a027b78d3c2747234f921" integrity sha512-bOgQLUnd2G5rhzaTvh1VCI9Fo6bC5cLTpH17T5aFfamyXFYDbbdzN6IXdeoc3jBS7T9hNTmJtYUzJCJ2Xlc9gA== +update-browserslist-db@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4004,7 +4366,7 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -util-deprecate@~1.0.1: +util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -4155,6 +4517,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^2.3.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" + integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ== + yargs-parser@^20.2.2, yargs-parser@^20.2.9: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" From 65dd0106b7248a37a0fa74c755e7f43568544658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 17 Oct 2024 14:03:44 +0200 Subject: [PATCH 2/9] fix test --- src/rollup.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rollup.ts b/src/rollup.ts index 7ae3367c3..c07349e8a 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -1,4 +1,4 @@ -import {writeFileSync} from "fs"; +import {writeFile} from "node:fs/promises"; import {extname, resolve} from "node:path/posix"; import {nodeResolve} from "@rollup/plugin-node-resolve"; import {simple} from "acorn-walk"; @@ -8,7 +8,7 @@ import {tailwindPlugin} from "esbuild-plugin-tailwindcss"; import type {AstNode, OutputChunk, Plugin, ResolveIdResult} from "rollup"; import {rollup} from "rollup"; import esbuild from "rollup-plugin-esbuild"; -import {getClientPath, getStylePath, maybeStat} from "./files.js"; +import {getClientPath, getStylePath, maybeStat, prepareOutput} from "./files.js"; import type {StringLiteral} from "./javascript/source.js"; import {getStringLiteralValue, isStringLiteral} from "./javascript/source.js"; import {resolveNpmImport} from "./npm.js"; @@ -200,7 +200,8 @@ async function tailwindConfig(root: string): Promise { const s = await maybeStat(`./${root}/${twconfig}`); const m = await maybeStat(configPath); if (!m || !s || !(m.mtimeMs > s.mtimeMs)) { - writeFileSync( + await prepareOutput(configPath); + await writeFile( configPath, ` // File generated by rollup.ts; to configure tailwind, edit ${root}/tailwind.config.js From b453fc474a6ec8b854a8a165f350f4d9cacf87a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 17 Oct 2024 14:42:18 +0200 Subject: [PATCH 3/9] windows? --- src/rollup.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rollup.ts b/src/rollup.ts index c07349e8a..6302b49c5 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -1,5 +1,5 @@ import {writeFile} from "node:fs/promises"; -import {extname, resolve} from "node:path/posix"; +import {extname, join, resolve} from "node:path/posix"; import {nodeResolve} from "@rollup/plugin-node-resolve"; import {simple} from "acorn-walk"; import {build} from "esbuild"; @@ -196,8 +196,8 @@ function importMetaResolve(path: string, resolveImport: ImportResolver): Plugin // tailwind.config.js is present in the project root, we import and merge it. async function tailwindConfig(root: string): Promise { const twconfig = "tailwind.config.js"; - const configPath = `./${root}/.observablehq/cache/${twconfig}`; - const s = await maybeStat(`./${root}/${twconfig}`); + const configPath = join(root, ".observablehq", "cache", twconfig); + const s = await maybeStat(join(root, twconfig)); const m = await maybeStat(configPath); if (!m || !s || !(m.mtimeMs > s.mtimeMs)) { await prepareOutput(configPath); From 65e7676f04818f16886fb8060279b8899e230073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 17 Oct 2024 17:01:08 +0200 Subject: [PATCH 4/9] part of the solution for dark mode --- src/rollup.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rollup.ts b/src/rollup.ts index 6302b49c5..35946944c 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -214,6 +214,7 @@ export default { "${root}/.observablehq/cache/_import/**/*.js" /* transpiled components */ ] }, + darkMode: ["variant", "&:where([class~=dark], [class~=dark] *)"], prefix: 'tw-', ...config }; From 15217919af797ad74d31c7042ed2e3cb6fa7d93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Fri, 25 Oct 2024 12:21:09 +0200 Subject: [PATCH 5/9] separate tailwind.css; always refresh it in preview; blocklist the grid classes for compatibility --- src/client/preview.js | 2 ++ src/{style => client}/tailwind.css | 0 src/resolvers.ts | 1 + src/rollup.ts | 8 ++++++-- src/style/default.css | 1 - 5 files changed, 9 insertions(+), 3 deletions(-) rename src/{style => client}/tailwind.css (100%) diff --git a/src/client/preview.js b/src/client/preview.js index e8c4683e9..c52616f48 100644 --- a/src/client/preview.js +++ b/src/client/preview.js @@ -155,6 +155,8 @@ export function open({hash, eval: compile} = {}) { for (const href of message.stylesheets.removed) { document.head.querySelector(`link[rel="stylesheet"][href="${href}"]`)?.remove(); } + const tw = document.head.querySelector('link[rel="stylesheet"][href$="_observablehq/tailwind.css"]'); + if (tw) tw.href = "" + tw.href; // reload tailwind.css } enableCopyButtons(); break; diff --git a/src/style/tailwind.css b/src/client/tailwind.css similarity index 100% rename from src/style/tailwind.css rename to src/client/tailwind.css diff --git a/src/resolvers.ts b/src/resolvers.ts index 3e9bd49fd..1f1c50b7c 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -348,6 +348,7 @@ async function resolveResolvers( } // Add implicit stylesheets. + stylesheets.add("observablehq:tailwind.css"); for (const specifier of getImplicitStylesheets(staticImports)) { stylesheets.add(specifier); if (specifier.startsWith("npm:")) { diff --git a/src/rollup.ts b/src/rollup.ts index 35946944c..106868f8d 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -20,6 +20,7 @@ import {THEMES, renderTheme} from "./theme.js"; const STYLE_MODULES = { "observablehq:default.css": getStylePath("default.css"), + "observablehq:tailwind.css": getStylePath("tailwind.css"), ...Object.fromEntries(THEMES.map(({name, path}) => [`observablehq:theme-${name}.css`, path])) }; @@ -47,16 +48,18 @@ export async function bundleStyles({ theme?: string[]; root: string; }): Promise { + const plugins = path === getClientPath("tailwind.css") ? [await tailwindConfig(root)] : undefined; const result = await build({ bundle: true, ...(path ? {entryPoints: [path]} : {stdin: {contents: renderTheme(theme!), loader: "css"}}), write: false, minify, - plugins: [await tailwindConfig(root)], + plugins, alias: STYLE_MODULES }); let text = result.outputFiles[0].text; if (path === getClientPath("stdlib/inputs.css")) text = rewriteInputsNamespace(text); + return text; } @@ -215,7 +218,8 @@ export default { ] }, darkMode: ["variant", "&:where([class~=dark], [class~=dark] *)"], - prefix: 'tw-', + blocklist: ["grid", "grid-cols-2", "grid-cols-3", "grid-cols-4"], + prefix: "", ...config }; ` diff --git a/src/style/default.css b/src/style/default.css index 9802917c2..29a2865e0 100644 --- a/src/style/default.css +++ b/src/style/default.css @@ -1,4 +1,3 @@ -@import url("./tailwind.css"); @import url("./global.css"); @import url("./layout.css"); @import url("./grid.css"); From cfc5867cad3271acc2c04e9ac44cf2427d909e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Fri, 25 Oct 2024 18:05:53 +0200 Subject: [PATCH 6/9] =?UTF-8?q?we=20have=20to=20use=20tailwind's=20base.cs?= =?UTF-8?q?s=20otherwise=20some=20of=20the=20styles=20are=20broken=20but?= =?UTF-8?q?=20this=20resets=20h1,h2,h3=E2=80=A6,=20which=20we=20don't=20wa?= =?UTF-8?q?nt.=20So=20let's=20remove=20that=20particular=20declaration=20(?= =?UTF-8?q?dirty=20for=20now)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (for instance, `focus:ring-2 focus:ring-purple-600 focus:ring-offset-2`) --- src/client/tailwind.css | 2 +- src/rollup.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/client/tailwind.css b/src/client/tailwind.css index ebbedf96c..76fcadcc0 100644 --- a/src/client/tailwind.css +++ b/src/client/tailwind.css @@ -1,3 +1,3 @@ -/* @import "tailwindcss/base"; */ +@import "tailwindcss/base"; @import "tailwindcss/components"; @import "tailwindcss/utilities"; diff --git a/src/rollup.ts b/src/rollup.ts index 106868f8d..3e9e23d31 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -59,6 +59,10 @@ export async function bundleStyles({ }); let text = result.outputFiles[0].text; if (path === getClientPath("stdlib/inputs.css")) text = rewriteInputsNamespace(text); + // dirty patch for tailwind: remove margin:0 and styles resets for headers + // etc. It should probably be a tailwind plugin instead. + if (path === getClientPath("tailwind.css")) + text = text.replaceAll(/}[^{]*h1,\n*h2,\n*h3,\n*h4,\n*h5,\n*h6[^}]+}\s*/g, "}"); return text; } From f0167bea74bb2019883e6d2f08cbc18234237536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Fri, 25 Oct 2024 19:36:14 +0200 Subject: [PATCH 7/9] breakpoints in coordination with framework's --- src/rollup.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/rollup.ts b/src/rollup.ts index 3e9e23d31..2bf4919c1 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -62,7 +62,10 @@ export async function bundleStyles({ // dirty patch for tailwind: remove margin:0 and styles resets for headers // etc. It should probably be a tailwind plugin instead. if (path === getClientPath("tailwind.css")) - text = text.replaceAll(/}[^{]*h1,\n*h2,\n*h3,\n*h4,\n*h5,\n*h6[^}]+}\s*/g, "}"); + text = text + .replaceAll(/}[^{]*h1,\n*h2,\n*h3,\n*h4,\n*h5,\n*h6[^}]+}\s*/g, "}") + .replace(/}[^{]*body[^}]+}\s*/, "}") + .replace(/box-sizing:\s*border-box;/, ""); return text; } @@ -212,7 +215,8 @@ async function tailwindConfig(root: string): Promise { configPath, ` // File generated by rollup.ts; to configure tailwind, edit ${root}/tailwind.config.js -${s ? `import config from "../../${twconfig}"` : "const config = {}"}; +${s ? `import cfg from "../../${twconfig}"` : "const cfg = {}"}; +const {theme, ...config} = cfg ?? {}; export default { content: { files: [ @@ -224,6 +228,15 @@ export default { darkMode: ["variant", "&:where([class~=dark], [class~=dark] *)"], blocklist: ["grid", "grid-cols-2", "grid-cols-3", "grid-cols-4"], prefix: "", + theme: { + screens: { + sm: "640px", + md: "768px", + lg: "calc(640px + 5rem + 192px)", + xl: "calc(640px + 7rem + 272px + 192px)" + }, + ...theme + }, ...config }; ` From 91401b755d5950ed69bd3eac2f3db428eef3695c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Fri, 25 Oct 2024 22:19:43 +0200 Subject: [PATCH 8/9] better breakpoints --- src/rollup.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rollup.ts b/src/rollup.ts index 2bf4919c1..41e617e89 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -232,8 +232,7 @@ export default { screens: { sm: "640px", md: "768px", - lg: "calc(640px + 5rem + 192px)", - xl: "calc(640px + 7rem + 272px + 192px)" + lg: [{min: "calc(640px + 5rem + 192px)", max: "calc(912px + 6rem)"}, {min: "calc(640px + 7rem + 272px + 192px)"}] }, ...theme }, From f3b5771b06799c76b4349e49b2e032f7d4e71440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Mon, 28 Oct 2024 13:45:23 +0100 Subject: [PATCH 9/9] document tailwind --- docs/markdown.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/markdown.md b/docs/markdown.md index 16d4fd455..fae85129e 100644 --- a/docs/markdown.md +++ b/docs/markdown.md @@ -368,3 +368,44 @@ You may also want to add `noopener noreferrer` if linking to an untrusted origin ![A horse](./horse.jpg) ![A happy kitten](https://placekitten.com/200/300) ``` + +## Tailwind CSS + +To go beyond grids and cards, Framework integrates [Tailwind](https://tailwindcss.com/), a toolkit that predefines utility classes driving styles directly from HTML. + +For example, let’s create a button with several styles — like `px-*` for horizontal padding: + +```html echo + +``` + +These classes drive the text’s size, the button’s rounded corners, the border and color of the text, *etc.* Note in particular the `hover:` modifier, which applies styles *conditionally*, when the pointer is over the button. Other supported modifiers include pseudo-classes (`:hover`, `:focus`, `:first-child`, and `:required`), pseudo-elements (`::before`, `::after`, `::placeholder`, and `::selection`), attribute selectors (`[dir="rtl"]` and `[open]`)… + +Size modifiers adapt styles to the container width: +

+sm: +md: +lg: +

+ +The `dark:` modifier adapts to the current page’s `color-scheme`, to better support dark mode. + +Modifiers can be stacked; for instance, the `md:` pill above adopts a different shade of purple in light and dark modes, using the following classes: + +```html run=false + +``` + +While Tailwind offers a lot of features, those that you don’t actually use are not added to the bundled stylesheet, keeping its size as small as possible. (The list of classes used is derived by a simple string-based search in your Markdown pages and JavaScript modules.) You can fine-tune the configuration by creating a `tailwind.config.js` [configuration file](https://tailwindcss.com/docs/configuration) in your [source root](./config#root). + +For details, see [Tailwind’s official documentation](https://tailwindcss.com/docs/). + +```js +// https://github.com/observablehq/framework/pull/1780 +document.body.classList.toggle("dark", dark); +```