mirror of
https://github.com/daylinmorgan/nimpkgs.git
synced 2024-12-22 02:50:44 -06:00
feat: update styles and add random "explore tags"
This commit is contained in:
parent
870f74a5a2
commit
b13d42a3a3
3 changed files with 89 additions and 39 deletions
|
@ -2,12 +2,17 @@ import std/[dom, sugar]
|
||||||
|
|
||||||
include karax/prelude
|
include karax/prelude
|
||||||
import karax/vstyles
|
import karax/vstyles
|
||||||
|
|
||||||
proc showScrollToTop() =
|
proc showScrollToTop() =
|
||||||
let mybutton = document.getElementById("myBtn")
|
# TODO: only show button when scrolling up
|
||||||
if document.body.scrollTop > 500 or document.documentElement.scrollTop > 500:
|
let mybtn = document.getElementById("scrollBtn")
|
||||||
mybutton.style.display = "block"
|
# if document.body.scrollTop > 500 or document.documentElement.scrollTop > 500:
|
||||||
else:
|
let show = (document.body.scrollTop > 500) or (
|
||||||
mybutton.style.display = "none"
|
document.documentElement.scrollTop > 500)
|
||||||
|
mybtn.style.display =
|
||||||
|
if show: "block"
|
||||||
|
else: "none"
|
||||||
|
|
||||||
|
|
||||||
proc scrollToTop*() =
|
proc scrollToTop*() =
|
||||||
document.body.scrollTop = 0
|
document.body.scrollTop = 0
|
||||||
|
@ -20,10 +25,10 @@ proc scrollToTopButton*(): VNode =
|
||||||
result = buildHtml(tdiv):
|
result = buildHtml(tdiv):
|
||||||
button(
|
button(
|
||||||
class =
|
class =
|
||||||
"absolute fixed md:bottom-10 md:right-10 bottom-2 right-2" &
|
" absolute fixed md:bottom-10 md:right-10 bottom-2 right-2 " &
|
||||||
"md:p-5 p-2 cursor-pointer z-99 rounded" &
|
" md:p-5 p-2 cursor-pointer z-99 rounded " &
|
||||||
"bg-ctp-rosewater hover:bg-ctp-mauve text-ctp-mantle ",
|
" bg-ctp-rosewater hover:bg-ctp-mauve text-ctp-mantle ",
|
||||||
`id` = "myBtn",
|
`id` = "scrollBtn",
|
||||||
onClick = scrollToTop,
|
onClick = scrollToTop,
|
||||||
style = "display:none;".toCss
|
style = "display:none;".toCss
|
||||||
):
|
):
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import std/[jsconsole, strutils, sets, sequtils, random]
|
import std/[strutils, sets, sequtils, random]
|
||||||
include karax / prelude
|
include karax / prelude
|
||||||
import karax / vstyles
|
|
||||||
|
|
||||||
import packages
|
import packages, button
|
||||||
import button
|
|
||||||
|
|
||||||
type
|
type
|
||||||
Query = object
|
Query = object
|
||||||
|
@ -11,12 +9,14 @@ type
|
||||||
|
|
||||||
randomize()
|
randomize()
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
filteredPackages: seq[Package] = allPackages
|
filteredPackages: seq[Package] = allPackages
|
||||||
searchInput: kstring = "".kstring
|
searchInput: kstring = "".kstring
|
||||||
const
|
const
|
||||||
packagesGitUrl = "https://github.com/nim-lang/packages/blob/" & packagesHash & "/packages.json"
|
packagesGitUrl = "https://github.com/nim-lang/packages/blob/" & packagesHash & "/packages.json"
|
||||||
numPackages = allPackages.len
|
numPackages = allPackages.len
|
||||||
|
numTags = allTags.len
|
||||||
colors = [
|
colors = [
|
||||||
"flamingo",
|
"flamingo",
|
||||||
"pink",
|
"pink",
|
||||||
|
@ -33,14 +33,20 @@ const
|
||||||
"lavender"
|
"lavender"
|
||||||
]
|
]
|
||||||
let
|
let
|
||||||
accent = colors.sample()
|
accent = (" " & colors.sample() & " ").kstring
|
||||||
textStyle = (" text-ctp-" & accent & " ").kstring
|
textStyle = (" text-ctp-" & accent & " ").kstring
|
||||||
borderStyle = (" b-ctp-" & accent & " ").kstring
|
borderStyle = (" b-ctp-" & accent & " ").kstring
|
||||||
randomIndices = [
|
randomPkgIndices = [
|
||||||
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1), rand(
|
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1),
|
||||||
numPackages-1), rand(numPackages-1),
|
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1),
|
||||||
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1), rand(
|
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1),
|
||||||
numPackages-1), rand(numPackages-1)]
|
rand(numPackages-1)]
|
||||||
|
randomTagIndices = [
|
||||||
|
rand(numTags-1), rand(numTags-1), rand(numTags-1),
|
||||||
|
rand(numTags-1), rand(numTags-1), rand(numTags-1)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc parseQuery(s: kstring): Query =
|
proc parseQuery(s: kstring): Query =
|
||||||
result = Query()
|
result = Query()
|
||||||
|
@ -95,8 +101,7 @@ proc noProtocol(s: kstring): kstring = kstring(($s).replace("http://",
|
||||||
|
|
||||||
proc toDom(pkg: Package): VNode =
|
proc toDom(pkg: Package): VNode =
|
||||||
result = buildHtml(tdiv(class = "flex flex-col bg-ctp-crust rounded-xl my-5 p-5")):
|
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,
|
h2(class = (textStyle & "font-black md:text-2xl text-lg font-casual").kstring):
|
||||||
style = "font-variation-settings: 'CASL' 1".toCss):
|
|
||||||
text ("# " & pkg.name).kstring
|
text ("# " & pkg.name).kstring
|
||||||
if pkg.alias != "":
|
if pkg.alias != "":
|
||||||
tdiv:
|
tdiv:
|
||||||
|
@ -152,8 +157,13 @@ proc getSearchInput() =
|
||||||
searchInput = getVNodeById("search").getInputText
|
searchInput = getVNodeById("search").getInputText
|
||||||
searchPackages(parseQuery(searchInput))
|
searchPackages(parseQuery(searchInput))
|
||||||
|
|
||||||
|
proc render(t: Tag): VNode =
|
||||||
|
result = buildHtml(tdiv(class = "bg-ctp-mantle m-1 p-1 rounded hover:text-ctp-mauve")):
|
||||||
|
tdiv(onClick = setSearch("tag:" & t.name)):
|
||||||
|
text t.name & "|" & kstring($t.packages)
|
||||||
|
|
||||||
proc searchBar(): Vnode =
|
proc searchBar(): Vnode =
|
||||||
result = buildHtml(tdiv(class = "flex flex-col lg:flex-row items-center my-5")):
|
result = buildHtml(tdiv(class = "flex flex-col md:flex-row md:items-center md:my-5")):
|
||||||
tdiv(class = "flex flex-row my-2"):
|
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",
|
input(`type` = "text", class = "border-1 bg-ctp-crust rounded mx-3 p-2".kstring & borderStyle, `id` = "search",
|
||||||
placeholder = "query", value = searchInput,
|
placeholder = "query", value = searchInput,
|
||||||
|
@ -161,25 +171,33 @@ proc searchBar(): Vnode =
|
||||||
button(`type` = "button", class = "border-1 rounded p-2".kstring &
|
button(`type` = "button", class = "border-1 rounded p-2".kstring &
|
||||||
borderStyle, onClick = getSearchInput):
|
borderStyle, onClick = getSearchInput):
|
||||||
text "search"
|
text "search"
|
||||||
tdiv(class = "text-xs md:mx-5 flex flex-col md:flex-row"):
|
#[
|
||||||
|
tdiv(class = "md:mx-5 flex flex-col items-center"):
|
||||||
tdiv: text "examples: "
|
tdiv: text "examples: "
|
||||||
tdiv:
|
tdiv(class="flex flex-col"):
|
||||||
span(class = "bg-ctp-surfacetwo rounded text-ctp-subtextone p-1 grow-0"):
|
for msg in ["tag:database sqlite","license:MIT javascript"]:
|
||||||
text "tag:database sqlite | license:MIT javascript"
|
span(class = "bg-ctp-mantle rounded text-ctp-subtextone m-1 p-1 text-xs"):
|
||||||
|
text msg
|
||||||
|
]#
|
||||||
|
tdiv(class = "flex flex-col mx-5"):
|
||||||
|
tdiv: text "explore tags:"
|
||||||
|
tdiv(class = "flex flex-wrap text-sm"):
|
||||||
|
for idx in randomTagIndices:
|
||||||
|
allTags[idx].render
|
||||||
|
|
||||||
|
|
||||||
proc headerBar(): VNode =
|
proc headerBar(): VNode =
|
||||||
result = buildHtml(tdiv(class = "mt-5 mx-5 flex flex-wrap")):
|
result = buildHtml(tdiv(class = "mt-5 mx-5 flex flex-wrap")):
|
||||||
tdiv(class = "flex items-center my-3 grow"):
|
tdiv(class = "flex items-center my-3 grow"):
|
||||||
img(src = "img/logo.svg", class = "inline h-1em md:h-2em px-1")
|
img(src = "img/logo.svg", class = "inline h-1em md:h-2em px-1")
|
||||||
span(class = "font-bold md:text-4xl text-lg",
|
span(class = "font-bold md:text-4xl text-lg font-casual"):
|
||||||
style = "font-variation-settings: 'CASL' 1".toCss):
|
|
||||||
text "pkgs"
|
text "pkgs"
|
||||||
label(`for` = "menu-toggle",
|
label(`for` = "menu-toggle",
|
||||||
class = "cursor-pointer md:hidden flex items-center px-3 py-2"
|
class = "cursor-pointer lg:hidden flex items-center px-3 py-2"
|
||||||
):
|
):
|
||||||
text "menu"
|
text "menu"
|
||||||
input(class = "hidden", type = "checkbox", `id` = "menu-toggle")
|
input(class = "hidden", type = "checkbox", `id` = "menu-toggle")
|
||||||
tdiv(class = "md:flex md:items-center justify-between hidden w-full md:w-auto",
|
tdiv(class = "lg:flex lg:items-center justify-between hidden w-full lg:w-auto",
|
||||||
`id` = "menu"):
|
`id` = "menu"):
|
||||||
nav:
|
nav:
|
||||||
ul(class = "md:flex items-center"):
|
ul(class = "md:flex items-center"):
|
||||||
|
@ -187,8 +205,8 @@ proc headerBar(): VNode =
|
||||||
(packagesGitUrl, "nim-lang/packages:" & packagesHashAbbr),
|
(packagesGitUrl, "nim-lang/packages:" & packagesHashAbbr),
|
||||||
("http://github.com/daylinmorgan/nimpkgs", "source")
|
("http://github.com/daylinmorgan/nimpkgs", "source")
|
||||||
]:
|
]:
|
||||||
li(class = "px-1"):
|
li(class = "p-2 hover:bg-ctp-mantle rounded text-sm"):
|
||||||
a(href = url.kstring, class = "text-ctp-surfacetwo text-xs"):
|
a(href = url.kstring, class = accent):
|
||||||
text msg
|
text msg
|
||||||
|
|
||||||
proc includedLinks(pkgs: seq[Package]): HashSet[char] =
|
proc includedLinks(pkgs: seq[Package]): HashSet[char] =
|
||||||
|
@ -196,9 +214,9 @@ proc includedLinks(pkgs: seq[Package]): HashSet[char] =
|
||||||
|
|
||||||
proc letterlink(): VNode =
|
proc letterlink(): VNode =
|
||||||
let activeLinks = includedLinks(filteredPackages)
|
let activeLinks = includedLinks(filteredPackages)
|
||||||
result = buildHtml(tdiv(class = "flex flex-wrap md:text-xl text-md space-x-4 capitalize")):
|
result = buildHtml(tdiv(class = "flex flex-wrap md:text-xl text-lg capitalize w-full justify-evenly gap-x-2 md:gap-x-auto")):
|
||||||
for l in LowercaseLetters:
|
for l in LowercaseLetters:
|
||||||
tdiv:
|
tdiv(class = "w-5"):
|
||||||
if l in activeLinks:
|
if l in activeLinks:
|
||||||
a(href = "#" & ($l).kstring):
|
a(href = "#" & ($l).kstring):
|
||||||
text $l
|
text $l
|
||||||
|
@ -215,7 +233,7 @@ proc filteredPackagesDom(): VNode =
|
||||||
|
|
||||||
|
|
||||||
proc createDom(): VNode =
|
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")):
|
result = buildHtml(tdiv(class = "md:w-3/4 max-w-[95%] md:mx-auto mx-5 md:text-lg text-sm")):
|
||||||
headerBar()
|
headerBar()
|
||||||
searchBar()
|
searchBar()
|
||||||
letterlink()
|
letterlink()
|
||||||
|
@ -223,7 +241,7 @@ proc createDom(): VNode =
|
||||||
text ($filteredPackages.len & "/" & $allPackages.len) & " packages"
|
text ($filteredPackages.len & "/" & $allPackages.len) & " packages"
|
||||||
if searchInput == "":
|
if searchInput == "":
|
||||||
tdiv():
|
tdiv():
|
||||||
for idx in randomIndices:
|
for idx in randomPkgIndices:
|
||||||
allPackages[idx].toDom
|
allPackages[idx].toDom
|
||||||
hr()
|
hr()
|
||||||
filteredPackagesDom()
|
filteredPackagesDom()
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import std/[algorithm, strutils]
|
import std/[algorithm, strutils, tables]
|
||||||
|
|
||||||
import karax/kbase
|
import karax/kbase
|
||||||
|
|
||||||
import jsony
|
import jsony
|
||||||
|
@ -8,6 +7,9 @@ type
|
||||||
Package* = object
|
Package* = object
|
||||||
name*, url*, `method`*, description*, license*, web*, doc*, alias*: kstring
|
name*, url*, `method`*, description*, license*, web*, doc*, alias*: kstring
|
||||||
tags*: seq[kstring]
|
tags*: seq[kstring]
|
||||||
|
Tag* = object
|
||||||
|
name*: kstring
|
||||||
|
packages*: int
|
||||||
|
|
||||||
proc parseHook*(s: string, i: var int, v: var kstring) =
|
proc parseHook*(s: string, i: var int, v: var kstring) =
|
||||||
var str: string
|
var str: string
|
||||||
|
@ -22,8 +24,33 @@ proc getPackages(): seq[Package] =
|
||||||
result = packagesJsonStr.fromJson(seq[Package])
|
result = packagesJsonStr.fromJson(seq[Package])
|
||||||
result.sort(cmpPkgs)
|
result.sort(cmpPkgs)
|
||||||
|
|
||||||
|
|
||||||
|
#[
|
||||||
|
import strutils, tables, heapqueue, algorithm
|
||||||
|
iterator topN[T](h: CountTable[T]|Table[T, int], n=10):
|
||||||
|
tuple[cnt: int; key: T] =
|
||||||
|
var q = initHeapQueue[tuple[cnt: int; key: T]]()
|
||||||
|
for key, cnt in h:
|
||||||
|
if q.len < n:
|
||||||
|
q.push((cnt, key))
|
||||||
|
elif cnt > q[0].cnt: # retain 1st seen on tied cnt
|
||||||
|
discard q.replace((cnt, key))
|
||||||
|
while q.len > 0: # q now has top n entries
|
||||||
|
yield q.pop
|
||||||
|
]#
|
||||||
|
|
||||||
|
proc getTags(pkgs: seq[Package]): seq[Tag] =
|
||||||
|
const minPackageCutoff = 10
|
||||||
|
var tags: seq[kstring]
|
||||||
|
for pkg in pkgs:
|
||||||
|
for tag in pkg.tags:
|
||||||
|
tags.add tag
|
||||||
|
for key, cnt in tags.toCountTable:
|
||||||
|
if cnt > minPackageCutoff:
|
||||||
|
result.add Tag(name: key, packages: cnt)
|
||||||
|
|
||||||
const
|
const
|
||||||
packagesHash* {.strdefine.} = "master"
|
packagesHash* {.strdefine.} = "master"
|
||||||
packagesHashAbbr* {.strdefine.} = "master"
|
packagesHashAbbr* {.strdefine.} = "master"
|
||||||
allPackages* = getPackages()
|
allPackages* = getPackages()
|
||||||
|
allTags* = allPackages.getTags()
|
||||||
|
|
Loading…
Reference in a new issue