mirror of
https://github.com/alrayyes/wiki.git
synced 2025-05-02 14:58:14 +00:00
nested tag support and tag index page
This commit is contained in:
parent
c0278a8c65
commit
cee2883c08
13 changed files with 125 additions and 37 deletions
quartz/components
|
@ -20,11 +20,20 @@ function byDateAndAlphabetical(f1: QuartzPluginData, f2: QuartzPluginData): numb
|
|||
return f1Title.localeCompare(f2Title)
|
||||
}
|
||||
|
||||
export function PageList({ fileData, allFiles }: QuartzComponentProps) {
|
||||
type Props = {
|
||||
limit?: number
|
||||
} & QuartzComponentProps
|
||||
|
||||
export function PageList({ fileData, allFiles, limit }: Props) {
|
||||
const slug = canonicalizeServer(fileData.slug!)
|
||||
let list = allFiles.sort(byDateAndAlphabetical)
|
||||
if (limit) {
|
||||
list = list.slice(0, limit)
|
||||
}
|
||||
|
||||
return (
|
||||
<ul class="section-ul">
|
||||
{allFiles.sort(byDateAndAlphabetical).map((page) => {
|
||||
{list.map((page) => {
|
||||
const title = page.frontmatter?.title
|
||||
const pageSlug = canonicalizeServer(page.slug!)
|
||||
const tags = page.frontmatter?.tags ?? []
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { canonicalizeServer, pathToRoot } from "../path"
|
||||
import { canonicalizeServer, pathToRoot, slugTag } from "../path"
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import { slug as slugAnchor } from "github-slugger"
|
||||
|
||||
function TagList({ fileData }: QuartzComponentProps) {
|
||||
const tags = fileData.frontmatter?.tags
|
||||
|
@ -11,7 +10,7 @@ function TagList({ fileData }: QuartzComponentProps) {
|
|||
<ul class="tags">
|
||||
{tags.map((tag) => {
|
||||
const display = `#${tag}`
|
||||
const linkDest = baseDir + `/tags/${slugAnchor(tag)}`
|
||||
const linkDest = baseDir + `/tags/${slugTag(tag)}`
|
||||
return (
|
||||
<li>
|
||||
<a href={linkDest} class="internal tag-link">
|
||||
|
|
|
@ -3,33 +3,75 @@ import { Fragment, jsx, jsxs } from "preact/jsx-runtime"
|
|||
import { toJsxRuntime } from "hast-util-to-jsx-runtime"
|
||||
import style from "../styles/listPage.scss"
|
||||
import { PageList } from "../PageList"
|
||||
import { ServerSlug, canonicalizeServer } from "../../path"
|
||||
import { ServerSlug, canonicalizeServer, getAllSegmentPrefixes } from "../../path"
|
||||
import { QuartzPluginData } from "../../plugins/vfile"
|
||||
|
||||
const numPages = 10
|
||||
function TagContent(props: QuartzComponentProps) {
|
||||
const { tree, fileData, allFiles } = props
|
||||
const slug = fileData.slug
|
||||
|
||||
if (slug?.startsWith("tags/")) {
|
||||
const tag = canonicalizeServer(slug.slice("tags/".length) as ServerSlug)
|
||||
const allPagesWithTag = allFiles.filter((file) => (file.frontmatter?.tags ?? []).includes(tag))
|
||||
const listProps = {
|
||||
...props,
|
||||
allFiles: allPagesWithTag,
|
||||
if (!slug?.startsWith("tags/")) {
|
||||
throw new Error(`Component "TagContent" tried to render a non-tag page: ${slug}`)
|
||||
}
|
||||
|
||||
const tag = canonicalizeServer(slug.slice("tags/".length) as ServerSlug)
|
||||
const allPagesWithTag = (tag: string) =>
|
||||
allFiles.filter((file) =>
|
||||
(file.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes).includes(tag),
|
||||
)
|
||||
|
||||
// @ts-ignore
|
||||
const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" })
|
||||
if (tag === "") {
|
||||
const tags = [...new Set(allFiles.flatMap((data) => data.frontmatter?.tags ?? []))]
|
||||
const tagItemMap: Map<string, QuartzPluginData[]> = new Map()
|
||||
for (const tag of tags) {
|
||||
tagItemMap.set(tag, allPagesWithTag(tag))
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" })
|
||||
return (
|
||||
<div class="popover-hint">
|
||||
<article>{content}</article>
|
||||
<p>{allPagesWithTag.length} items with this tag.</p>
|
||||
<p>Found {tags.length} total tags.</p>
|
||||
<div>
|
||||
{tags.map((tag) => {
|
||||
const pages = tagItemMap.get(tag)!
|
||||
const listProps = {
|
||||
...props,
|
||||
allFiles: pages,
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
<a class="internal tag-link" href={`./tags/${tag}`}>
|
||||
#{tag}
|
||||
</a>
|
||||
</h2>
|
||||
<p>{pages.length} items with this tag. {pages.length > numPages && `Showing first ${numPages}.`}</p>
|
||||
<PageList limit={numPages} {...listProps} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
const pages = allPagesWithTag(tag)
|
||||
const listProps = {
|
||||
...props,
|
||||
allFiles: pages,
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="popover-hint">
|
||||
<article>{content}</article>
|
||||
<p>{pages.length} items with this tag.</p>
|
||||
<div>
|
||||
<PageList {...listProps} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
throw new Error(`Component "TagContent" tried to render a non-tag page: ${slug}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
position: relative;
|
||||
width: 30rem;
|
||||
max-height: 20rem;
|
||||
padding: 0 1rem 2rem 1rem;
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
font-weight: initial;
|
||||
line-height: normal;
|
||||
font-size: initial;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue