mirror of
https://github.com/daylinmorgan/nimpkgs.git
synced 2024-11-13 15:17:53 -06:00
mvp
This commit is contained in:
parent
30ff5aefa3
commit
bf06b027b2
13 changed files with 2580 additions and 0 deletions
139
.gitignore
vendored
Normal file
139
.gitignore
vendored
Normal 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
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# nimpkgs
|
||||
|
22
config.nims
Normal file
22
config.nims
Normal 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
17
nimpkgs.nimble
Normal 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
25
package.json
Normal 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
1836
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
48
site/img/logo-crown.svg
Normal file
48
site/img/logo-crown.svg
Normal 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
108
site/img/logo.svg
Normal 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
18
site/index.html
Normal 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
32
src/button.nim
Normal 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
232
src/nimpkgs.nim
Normal 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
29
src/packages.nim
Normal 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
72
unocss.config.ts
Normal 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,
|
||||
},
|
||||
});
|
Loading…
Reference in a new issue