This commit is contained in:
Daylin Morgan 2023-11-12 18:25:29 -06:00
parent 30ff5aefa3
commit bf06b027b2
Signed by: daylin
GPG Key ID: C1E52E7DD81DF79F
13 changed files with 2580 additions and 0 deletions

139
.gitignore vendored Normal file
View File

@ -0,0 +1,139 @@
### Node
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
##
*.workspace
site/uno.css
site/nimpkgs.js
src/nim.cfg
src/packages

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# nimpkgs

22
config.nims Normal file
View File

@ -0,0 +1,22 @@
import std/[strutils, strformat]
--backend:js
proc getCommitInfo*(): (string, string) =
if not dirExists "src/packages":
echo "cloning nim-lang/packages"
discard staticExec "git clone https://github.com/nim-lang/packages.git src/packages"
let output = (staticExec "git -C src/packages show -q --format='%h %H'").split()
return (output[0], output[1])
task setup, "run atlas init":
exec "atlas init --deps=.workspace"
exec "atlas install"
task build, "build":
let (short,long) = getCommitInfo()
selfExec fmt"js -o:site/nimpkgs.js -d:packagesHash:{long} -d:packagesHashAbbr:{short} -d:release src/nimpkgs.nim"
exec "pnpm run build"
task watch, "rebuild on change":
exec "watchexec -w src nim js -d:packagesHash:master -o:site/nimpkgs.js src/nimpkgs.nim"

17
nimpkgs.nimble Normal file
View File

@ -0,0 +1,17 @@
# Package
version = "2023.1001"
author = "Daylin Morgan"
description = "nim-lang packages alternate ui"
license = "MIT"
srcDir = "src"
bin = @["nimpkgs"]
# Dependencies
requires "nim >= 2.0.0"
requires "karax"
requires "jsony"

25
package.json Normal file
View File

@ -0,0 +1,25 @@
{
"scripts": {
"dev": "concurrently npm:server npm:uno:dev npm:watch",
"server": "http-server ./site",
"watch": "nim watch",
"build": "pnpm run uno:prd && pnpm run minify",
"minify": "esbuild --minify --outdir=site --allow-overwrite site/nimpkgs.js site/uno.css",
"uno:dev": "unocss \"./site/**/*.html\" \"./src/**/*.nim\" --out-file site/uno.css -w",
"uno:prd": "unocss \"./site/**/*.html\" \"./src/**/*.nim\" --out-file site/uno.css"
},
"author": "Daylin Morgan",
"license": "MIT",
"dependencies": {
"@catppuccin/palette": "^0.2.0",
"@types/promise-fs": "^2.1.5",
"@unocss/cli": "^0.57.3",
"@unocss/reset": "^0.57.3",
"unocss": "^0.57.3"
},
"devDependencies": {
"concurrently": "^8.2.2",
"esbuild": "^0.19.5",
"http-server": "^14.1.1"
}
}

1836
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

48
site/img/logo-crown.svg Normal file
View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="25.117779mm"
height="17.215555mm"
viewBox="0 0 89.000004 60.999998"
id="svg3522"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs3524" />
<metadata
id="metadata3527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-43.28551,-410.43363)">
<g
style="display:inline"
id="g4469"
transform="translate(-621.55272,-186.17892)">
<g
id="g4459">
<path
style="fill:#f3d400;fill-opacity:1;stroke:none"
d="m 709.69141,596.61258 c 0,0 -3.41031,2.69499 -6.88691,5.37174 -3.57641,-0.11362 -10.59106,0.68718 -14.39187,2.06946 -3.50133,-2.21819 -6.57787,-4.66728 -6.57787,-4.66728 0,0 -2.62896,4.52282 -4.28224,7.17702 -2.45187,1.30403 -4.91362,2.77074 -7.10764,4.7113 -2.55188,-1.01333 -5.5101,-2.24876 -5.60665,-2.28959 3.37945,6.81645 5.65131,13.64192 11.83134,17.74436 9.83897,-15.53906 55.55981,-14.10685 65.60219,-0.0881 6.49004,-3.38511 9.01412,-10.66815 11.56647,-17.39212 -0.27986,0.0922 -3.75271,1.25487 -6.00396,2.11349 -1.34414,-1.46336 -4.51234,-3.71327 -6.31301,-4.79936 -1.70802,-3.12771 -4.19395,-7.35313 -4.19395,-7.35313 0,0 -2.94437,2.1899 -6.35714,4.5792 -4.61059,-0.85108 -10.1872,-1.88519 -14.87749,-1.62916 -3.19286,-2.62436 -6.40127,-5.54786 -6.40127,-5.54786 z"
id="path3054" />
<path
style="fill:#ffe953;fill-opacity:1;stroke:none"
d="m 668.33241,623.47127 c 0,0 4.78987,11.5978 8.1165,19.65678 14.09625,18.59727 50.09234,19.89014 65.7848,0.36006 3.71345,-8.36876 8.72334,-20.1298 8.72334,-20.1298 -4.0259,5.96409 -10.5778,10.08114 -14.61301,12.29885 -2.86735,1.57082 -9.48338,2.52031 -9.48338,2.52031 l -17.36961,-9.00108 -17.46941,8.82104 c 0,0 -6.52806,-1.04882 -9.4834,-2.4303 -5.96472,-3.18408 -9.9764,-6.94592 -14.20583,-12.09586 z"
id="path3051" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

108
site/img/logo.svg Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="62.653446mm"
height="17.215555mm"
viewBox="0 0 222.0004 60.999998"
id="svg3522"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="logo.svg">
<defs
id="defs3524" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="138.06096"
inkscape:cy="17.963121"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1015"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata3527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-43.28551,-410.43363)">
<g
style="display:inline"
id="g4469"
transform="translate(-621.55272,-186.17892)">
<g
id="g4463">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 774.83823,652.61255 0,-39 c 0,0 14.0008,0 19.5004,0 5.4996,0 10.4996,5 10.5,10.5 4e-4,5.5 0,28.5 0,28.5 l -7,0 c 0,0 -3.9e-4,-18 -4e-4,-27 0,-2.71875 -2,-5 -5,-5 -3.66681,0 -11,0 -11,0 l 0,37 z"
id="path3118"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cczzccssccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 817.83863,652.61255 0,-39 7,0 0,39 z"
id="path3120"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 817.83863,604.61255 7,0 0,-8 -7,5 z"
id="path3122"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 844.83863,652.61255 -7,0 0,-39 38.5,0 c 6,0 10.49999,4.5 10.5,10.5 l 0,28.5 -7,5 -4e-4,-32 c -4e-5,-3 -2,-5 -5,-5 l -8.9996,0 0,32 -7,0 0,-32 -14,0 z"
id="path3124"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccssccsscccccc" />
</g>
<g
id="g4459">
<path
style="fill:#f3d400;fill-opacity:1;stroke:none"
d="m 709.69141,596.61258 c 0,0 -3.41031,2.69499 -6.88691,5.37174 -3.57641,-0.11362 -10.59106,0.68718 -14.39187,2.06946 -3.50133,-2.21819 -6.57787,-4.66728 -6.57787,-4.66728 0,0 -2.62896,4.52282 -4.28224,7.17702 -2.45187,1.30403 -4.91362,2.77074 -7.10764,4.7113 -2.55188,-1.01333 -5.5101,-2.24876 -5.60665,-2.28959 3.37945,6.81645 5.65131,13.64192 11.83134,17.74436 9.83897,-15.53906 55.55981,-14.10685 65.60219,-0.0881 6.49004,-3.38511 9.01412,-10.66815 11.56647,-17.39212 -0.27986,0.0922 -3.75271,1.25487 -6.00396,2.11349 -1.34414,-1.46336 -4.51234,-3.71327 -6.31301,-4.79936 -1.70802,-3.12771 -4.19395,-7.35313 -4.19395,-7.35313 0,0 -2.94437,2.1899 -6.35714,4.5792 -4.61059,-0.85108 -10.1872,-1.88519 -14.87749,-1.62916 -3.19286,-2.62436 -6.40127,-5.54786 -6.40127,-5.54786 z"
id="path3054"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccccc" />
<path
style="fill:#ffe953;fill-opacity:1;stroke:none"
d="m 668.33241,623.47127 c 0,0 4.78987,11.5978 8.1165,19.65678 14.09625,18.59727 50.09234,19.89014 65.7848,0.36006 3.71345,-8.36876 8.72334,-20.1298 8.72334,-20.1298 -4.0259,5.96409 -10.5778,10.08114 -14.61301,12.29885 -2.86735,1.57082 -9.48338,2.52031 -9.48338,2.52031 l -17.36961,-9.00108 -17.46941,8.82104 c 0,0 -6.52806,-1.04882 -9.4834,-2.4303 -5.96472,-3.18408 -9.9764,-6.94592 -14.20583,-12.09586 z"
id="path3051"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

18
site/index.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<link rel="icon" href="img/logo-crown.svg">
<title>nimpkgs</title>
<link href="uno.css" rel="stylesheet" type="text/css">
<!--
<link href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..800,0..1,0..1,1&display=swap" rel="stylesheet">
-->
<link href="https://fonts.googleapis.com/css2?family=Recursive:wght,CASL,MONO@300..1000,0..1,1&display=swap" rel="stylesheet">
</head>
<body id="body" class="text-ctp-text max-w-screen bg-ctp-base flex items-center justify-center">
<div id="ROOT"></div>
<script type="text/javascript" src="/nimpkgs.js"></script>
</body>
</html>

32
src/button.nim Normal file
View File

@ -0,0 +1,32 @@
import std/[dom, sugar]
include karax/prelude
import karax/vstyles
proc showScrollToTop() =
let mybutton = document.getElementById("myBtn")
if document.body.scrollTop > 500 or document.documentElement.scrollTop > 500:
mybutton.style.display = "block"
else:
mybutton.style.display = "none"
proc scrollToTop*() =
document.body.scrollTop = 0
document.documentElement.scrollTop = 0
document.addEventListener("scroll", (e: Event) => showScrollToTop())
proc scrollToTopButton*(): VNode =
result = buildHtml(tdiv):
button(
class =
"absolute fixed md:bottom-10 md:right-10 bottom-2 right-2" &
"md:p-5 p-2 cursor-pointer z-99 rounded" &
"bg-ctp-rosewater hover:bg-ctp-mauve text-ctp-mantle ",
`id` = "myBtn",
onClick = scrollToTop,
style = "display:none;".toCss
):
text "Back to top"

232
src/nimpkgs.nim Normal file
View File

@ -0,0 +1,232 @@
import std/[jsconsole, strutils, sets, sequtils, random]
include karax / prelude
import karax / vstyles
import packages
import button
type
Query = object
all, name, tag, license = "".kstring
randomize()
var
filteredPackages: seq[Package] = allPackages
searchInput: kstring = "".kstring
const
packagesGitUrl = "https://github.com/nim-lang/packages/blob/" & packagesHash & "/packages.json"
numPackages = allPackages.len
colors = [
"flamingo",
"pink",
"mauve",
"red",
"maroon",
"peach",
"yellow",
"green",
"teal",
"sky",
"sapphire",
"blue",
"lavender"
]
let
accent = colors.sample()
textStyle = (" text-ctp-" & accent & " ").kstring
borderStyle = (" b-ctp-" & accent & " ").kstring
randomIndices = [
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1), rand(
numPackages-1), rand(numPackages-1),
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1), rand(
numPackages-1), rand(numPackages-1)]
proc parseQuery(s: kstring): Query =
result = Query()
if ":" notin s:
result.all = s; return
let parts = s.split(" ")
for part in parts:
if ":" in part:
let
subparts = part.split(":")
k = subparts[0]
v = subparts[1]
case k:
of "name":
result.name = v
of "tag":
result.tag = v
of "license":
result.license = v
else: discard
else:
result.all &= part
proc searchPackages(q: Query) =
filteredPackages = @[]
if q == Query():
filteredPackages = allPackages
return
for pkg in allPackages:
let searchStr = ((pkg.name & " " & pkg.description & " " & (pkg.tags).join(" ").kstring))
if (q.name notin pkg.name) or
(q.license notin pkg.license) or
(q.tag != "".kstring and (q.tag notin pkg.tags)): continue
if q.all in searchStr:
filteredPackages.add pkg
proc setSearch(v: kstring): proc () =
result = proc() =
searchInput = v
searchPackages(parseQuery(v))
redraw()
proc fieldToDom(s: kstring): VNode =
result = buildHtml(tdiv(class = "font-black basis-1/4 sm:basis-1/6 shrink-0")):
text s & ":"
proc noProtocol(s: kstring): kstring = kstring(($s).replace("http://",
"").replace("https://", ""))
proc toDom(pkg: Package): VNode =
result = buildHtml(tdiv(class = "flex flex-col bg-ctp-crust rounded-xl my-5 p-5")):
h2(class = (textStyle & "font-black md:text-2xl text-lg").kstring,
style = "font-variation-settings: 'CASL' 1".toCss):
text ("# " & pkg.name).kstring
if pkg.alias != "":
tdiv:
text "alias for: "
span(onClick = setSearch("name:" & pkg.alias),
class = "hover:text-ctp-mauve"):
text pkg.alias
else:
text pkg.description
tdiv(class = "flex flex-col text-xs md:text-lg overflow-x-scroll"):
tdiv(class = "flex flex-row"):
fieldToDom("project")
a(href = pkg.url):
text pkg.url.noProtocol
tdiv(class = "flex flex-row"):
fieldToDom("web")
a(href = pkg.web): text pkg.web.noProtocol
if pkg.doc != "":
tdiv(class = "flex flex-row"):
fieldToDom("doc")
a(href = pkg.doc): text pkg.doc.noProtocol
tdiv(class = "flex flex-row"):
fieldToDom("license")
span: text pkg.license
tdiv(class = "flex flex-row"):
fieldToDom("tags")
tdiv():
for t in pkg.tags:
span(onClick = setSearch("tag:" & t),
class = "hover:text-ctp-mauve"):
text t
text "; "
# tdiv(class="bg-ctp-mantle rounded my-2 p-2"):
# text "nimble install " & p.name
# br()
# text "atlas use " & p.name
proc startChar(p: Package): char = p.name[0].toLowerAscii
proc toDom(pkgs: seq[Package]): VNode =
var l = 'a'
result = buildHtml(tdiv):
if pkgs[0].startChar == l: tdiv(id = ($l).kstring)
for pkg in pkgs:
let startC = pkg.name[0].toLowerAscii
if l != startC:
while l != startC: inc l
tdiv(id = ($l).kstring)
pkg.toDom
proc getSearchInput() =
searchInput = getVNodeById("search").getInputText
searchPackages(parseQuery(searchInput))
proc searchBar(): Vnode =
result = buildHtml(tdiv(class = "flex flex-col lg:flex-row items-center my-5")):
tdiv(class = "flex flex-row my-2"):
input(`type` = "text", class = "border-1 bg-ctp-crust rounded mx-3 p-2".kstring & borderStyle, `id` = "search",
placeholder = "query", value = searchInput,
onChange = getSearchInput)
button(`type` = "button", class = "border-1 rounded p-2".kstring &
borderStyle, onClick = getSearchInput):
text "search"
tdiv(class = "text-xs md:mx-5 flex flex-col md:flex-row"):
tdiv: text "examples: "
tdiv:
span(class = "bg-ctp-surfacetwo rounded text-ctp-subtextone p-1 grow-0"):
text "tag:database sqlite | license:MIT javascript"
proc headerBar(): VNode =
result = buildHtml(tdiv(class = "mt-5 mx-5 flex flex-wrap")):
tdiv(class = "flex items-center my-3 grow"):
img(src = "/img/logo.svg", class = "inline h-1em md:h-2em px-1")
span(class = "font-bold md:text-4xl text-lg",
style = "font-variation-settings: 'CASL' 1".toCss):
text "pkgs"
label(`for` = "menu-toggle",
class = "cursor-pointer md:hidden flex items-center px-3 py-2"
):
text "menu"
input(class = "hidden", type = "checkbox", `id` = "menu-toggle")
tdiv(class = "md:flex md:items-center justify-between hidden w-full md:w-auto",
`id` = "menu"):
nav:
ul(class = "md:flex items-center"):
for (url, msg) in [
(packagesGitUrl, "nim-lang/packages:" & packagesHashAbbr),
("http://github.com/daylinmorgan/nimpkgs", "source")
]:
li(class = "px-1"):
a(href = url.kstring, class = "text-ctp-surfacetwo text-xs"):
text msg
proc includedLinks(pkgs: seq[Package]): HashSet[char] =
pkgs.mapIt(it.startChar).toHashSet
proc letterlink(): VNode =
let activeLinks = includedLinks(filteredPackages)
result = buildHtml(tdiv(class = "flex flex-wrap md:text-xl text-md space-x-4 capitalize")):
for l in LowercaseLetters:
tdiv:
if l in activeLinks:
a(href = "#" & ($l).kstring):
text $l
else:
span(class = "text-ctp-crust"):
text $l
proc filteredPackagesDom(): VNode =
if filteredPackages.len > 0:
result = filteredPackages.toDom
else:
result = buildHtml():
text "no match...try a different query"
proc createDom(): VNode =
result = buildHtml(tdiv(class = "sm:w-3/4 md:w-2/3 max-w-[95%] md:mx-auto mx-5 md:text-lg text-sm")):
headerBar()
searchBar()
letterlink()
tdiv(class = "text-ctp-surfacetwo"):
text ($filteredPackages.len & "/" & $allPackages.len) & " packages"
if searchInput == "":
tdiv():
for idx in randomIndices:
allPackages[idx].toDom
hr()
filteredPackagesDom()
scrollToTopButton()
setRenderer createDom

29
src/packages.nim Normal file
View File

@ -0,0 +1,29 @@
import std/[algorithm, strutils]
import karax/kbase
import jsony
type
Package* = object
name*, url*, `method`*, description*, license*, web*, doc*, alias*: kstring
tags*: seq[kstring]
proc parseHook*(s: string, i: var int, v: var kstring) =
var str: string
parseHook(s, i, str)
v = cstring(str)
proc cmpPkgs(a, b: Package): int =
cmp(toLowerAscii($a.name), toLowerAscii($b.name))
proc getPackages(): seq[Package] =
const packagesJsonStr = slurp "./packages/packages.json"
result = packagesJsonStr.fromJson(seq[Package])
result.sort(cmpPkgs)
const
packagesHash* {.strdefine.} = "master"
packagesHashAbbr* {.strdefine.} = "master"
allPackages* = getPackages()

72
unocss.config.ts Normal file
View File

@ -0,0 +1,72 @@
import fs from "fs/promises";
import { variants } from "@catppuccin/palette";
import { defineConfig, presetUno } from "unocss";
const generatePalette = () => {
const colors = {};
Object.keys(variants.mocha).forEach((colorName) => {
const sanitizedName = colorName
.replace("0", "zero")
.replace("1", "one")
.replace("2", "two");
colors[sanitizedName] = variants.mocha[colorName].hex;
});
return colors;
};
const catppuccinColors = generatePalette()
export default defineConfig({
preflights: [
{
layer: "reset",
getCSS: () =>
fs.readFile("node_modules/@unocss/reset/tailwind.css", "utf-8"),
},
{
layer: "mycss",
getCSS: ({ theme }) => `
body {
font-family: 'Recursive', monospace;
font-variation-settings: 'MONO' 1;
}
#menu-toggle:checked + #menu {
display: block;
}
a {
text-decoration: underline dotted;
color: ${theme.colors.ctp.rosewater};
}
a:hover {
color: ${theme.colors.ctp.mauve};
}
`,
},
],
// accent color is dynamically generated
safelist: Object.keys(catppuccinColors).flatMap((key: string) => [`text-ctp-${key}`, `b-ctp-${key}`]),
presets: [presetUno()],
rules: [
["font-casual", { "font-variation-settings": "'CASL' 1;" }],
["font-mono-casual", { "font-variation-settings": "'MONO' 1, 'CASL' 1;" }],
],
shortcuts: {
btn: "border-1 border-solid rounded border-ctp-mauve flex flex-row hover:border-ctp-sky hover:text-ctp-rosewater m-2",
// link: "underline text-ctp-rosewater"
},
theme: {
colors: {
ctp: generatePalette(),
},
},
layers: {
reset: -1,
mycss: 0.5,
shortcuts: 0,
components: 1,
default: 2,
utilities: 3,
},
});