Skip to content

Commit c1d6717

Browse files
committed
fix
1 parent 17f85ee commit c1d6717

8 files changed

Lines changed: 136 additions & 57 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
---
22
title: horticulture
33
---
4+
5+
Horticulture is a term I started using during the [[tags/seasons/rhythm/index|Season of Rhythm]], specifically picked up from the term [[content/notes/digital-gardening-with-quartz|digital gardening.]]
6+
7+
Most of the time, horticulture relates to maintaining [[tags/seasons/systems/index|systems]] like this blog, along with other personal systems that either maintain my ability to manage my own life, and, in turn, might require their own maintenance over time.

quartz/cfg.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,6 @@ export interface FullPageLayout {
103103

104104
export type PageLayout = Pick<FullPageLayout, "beforeBody" | "left" | "right"> & {
105105
pageHeader?: QuartzComponent[]
106+
afterBody?: QuartzComponent[]
106107
}
107108
export type SharedLayout = Pick<FullPageLayout, "head" | "header" | "footer" | "afterBody">

quartz/components/Footer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default ((opts?: Options) => {
1212
const links = opts?.links ?? []
1313
return (
1414
<footer class={`${displayClass ?? ""}`}>
15+
<hr />
1516
<ul>
1617
{Object.entries(links).map(([text, link]) => (
1718
<li>

quartz/components/PostListing.tsx

Lines changed: 112 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ export interface PostListingOptions {
1010
*/
1111
limit?: number
1212

13+
/**
14+
* Number of posts to show before collapsing the rest into a details element.
15+
* If undefined, all posts are shown without collapsing.
16+
*/
17+
collapsedItemCount?: number
18+
1319
/**
1420
* Sorting function for posts. Defaults to byDateAndAlphabetical.
1521
*/
@@ -21,9 +27,16 @@ export interface PostListingOptions {
2127
*/
2228
excludeTags?: string[]
2329

30+
/**
31+
* If true, filters posts to only those that have the current page's tag.
32+
* Only works on tag pages (pages with slug starting with "tags/").
33+
* Default: false
34+
*/
35+
filterToCurrentTag?: boolean
36+
2437
/**
2538
* Filter function to determine which pages to include.
26-
* Takes precedence over excludeTags if both are specified.
39+
* Takes precedence over excludeTags and filterToCurrentTag if specified.
2740
*/
2841
filter?: (file: QuartzPluginData) => boolean
2942

@@ -75,12 +88,27 @@ export default ((userOpts?: Partial<PostListingOptions>) => {
7588
if (opts.filter) {
7689
// Use custom filter if provided
7790
filteredFiles = filteredFiles.filter(opts.filter)
78-
} else if (opts.excludeTags && opts.excludeTags.length > 0) {
79-
// Use excludeTags filter
80-
filteredFiles = filteredFiles.filter((file) => {
81-
const tags = file.frontmatter?.tags ?? []
82-
return !tags.some((tag) => opts.excludeTags!.includes(tag))
83-
})
91+
} else {
92+
// Apply filterToCurrentTag if on a tag page
93+
if (opts.filterToCurrentTag && fileData.slug?.startsWith("tags/")) {
94+
// Extract tag from slug: "tags/horticulture/index" -> "horticulture"
95+
const currentTag = fileData.slug
96+
.replace(/^tags\//, "")
97+
.replace(/\/index$/, "")
98+
.replace(/\/$/, "")
99+
filteredFiles = filteredFiles.filter((file) => {
100+
const tags = file.frontmatter?.tags ?? []
101+
return tags.includes(currentTag)
102+
})
103+
}
104+
105+
// Apply excludeTags filter
106+
if (opts.excludeTags && opts.excludeTags.length > 0) {
107+
filteredFiles = filteredFiles.filter((file) => {
108+
const tags = file.frontmatter?.tags ?? []
109+
return !tags.some((tag) => opts.excludeTags!.includes(tag))
110+
})
111+
}
84112
}
85113

86114
// Apply sorting
@@ -96,47 +124,65 @@ export default ((userOpts?: Partial<PostListingOptions>) => {
96124
return <p class="post-listing-empty">{opts.emptyMessage}</p>
97125
}
98126

99-
return (
100-
<ul class="section-ul">
101-
{list.map((page) => {
102-
const title = page.frontmatter?.title
103-
const tags = page.frontmatter?.tags ?? []
104-
105-
return (
106-
<li class="section-li">
107-
<div class="section">
108-
{opts.showDates && page.dates && (
109-
<p class="meta">
110-
<Date date={getDate(cfg, page)!} locale={cfg.locale} />
111-
</p>
112-
)}
113-
<div class="desc">
114-
<h3>
115-
<a href={resolveRelative(fileData.slug!, page.slug!)} class="internal">
116-
{title}
117-
</a>
118-
</h3>
119-
</div>
120-
{opts.showTags && tags.length > 0 && (
121-
<ul class="tags">
122-
{tags.map((tag) => (
123-
<li>
124-
<a
125-
class="internal tag-link"
126-
href={resolveRelative(fileData.slug!, `tags/${tag}` as FullSlug)}
127-
>
128-
{tag}
129-
</a>
130-
</li>
131-
))}
132-
</ul>
133-
)}
127+
// Render list items
128+
const renderListItems = (items: QuartzPluginData[]) =>
129+
items.map((page) => {
130+
const title = page.frontmatter?.title
131+
const tags = page.frontmatter?.tags ?? []
132+
133+
return (
134+
<li class="section-li">
135+
<div class="section">
136+
{opts.showDates && page.dates && (
137+
<p class="meta">
138+
<Date date={getDate(cfg, page)!} locale={cfg.locale} />
139+
</p>
140+
)}
141+
<div class="desc">
142+
<h3>
143+
<a href={resolveRelative(fileData.slug!, page.slug!)} class="internal">
144+
{title}
145+
</a>
146+
</h3>
134147
</div>
135-
</li>
136-
)
137-
})}
138-
</ul>
139-
)
148+
{opts.showTags && tags.length > 0 && (
149+
<ul class="tags">
150+
{tags.map((tag) => (
151+
<li>
152+
<a
153+
class="internal tag-link"
154+
href={resolveRelative(fileData.slug!, `tags/${tag}` as FullSlug)}
155+
>
156+
{tag}
157+
</a>
158+
</li>
159+
))}
160+
</ul>
161+
)}
162+
</div>
163+
</li>
164+
)
165+
})
166+
167+
// Handle collapsible list if collapsedItemCount is set
168+
if (opts.collapsedItemCount && list.length > opts.collapsedItemCount) {
169+
const visibleItems = list.slice(0, opts.collapsedItemCount)
170+
const collapsedItems = list.slice(opts.collapsedItemCount)
171+
172+
return (
173+
<div>
174+
<ul class="section-ul">{renderListItems(visibleItems)}</ul>
175+
<details class="post-listing-collapse">
176+
<summary>
177+
Show {collapsedItems.length} more {collapsedItems.length === 1 ? "post" : "posts"}
178+
</summary>
179+
<ul class="section-ul">{renderListItems(collapsedItems)}</ul>
180+
</details>
181+
</div>
182+
)
183+
}
184+
185+
return <ul class="section-ul">{renderListItems(list)}</ul>
140186
}
141187

142188
PostListing.css = `
@@ -152,6 +198,25 @@ export default ((userOpts?: Partial<PostListingOptions>) => {
152198
color: var(--gray);
153199
font-style: italic;
154200
}
201+
202+
.post-listing-collapse {
203+
margin-top: 1rem;
204+
}
205+
206+
.post-listing-collapse > summary {
207+
cursor: pointer;
208+
color: var(--secondary);
209+
font-weight: 600;
210+
padding: 0.5rem 0;
211+
}
212+
213+
.post-listing-collapse > summary:hover {
214+
color: var(--tertiary);
215+
}
216+
217+
.post-listing-collapse > .section-ul {
218+
margin-top: 1rem;
219+
}
155220
`
156221

157222
return PostListing

quartz/components/pages/TagContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default (() => {
2222
? fileData.description
2323
: htmlToJsx(fileData.filePath!, tree)
2424
) as ComponentChildren
25-
25+
2626
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
2727
const classes = cssClasses.join(" ")
2828

quartz/components/styles/footer.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
footer {
2-
text-align: left;
2+
text-align: center;
33
margin-bottom: 4rem;
44
opacity: 0.7;
55

@@ -11,5 +11,6 @@ footer {
1111
flex-direction: row;
1212
gap: 1rem;
1313
margin-top: -1rem;
14+
justify-content: center;
1415
}
1516
}

quartz/layouts/index.layout.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,6 @@ export const indexLayout: PageLayout = {
8383
Component.ArticleTitle(),
8484
Component.ContentMeta(),
8585
Component.TagList(),
86-
Component.PostListing({
87-
excludeTags: ["private"],
88-
showEmptyMessage: false,
89-
}),
9086
],
9187
left: [
9288
Component.PageTitle(),
@@ -113,4 +109,11 @@ export const indexLayout: PageLayout = {
113109
Component.DesktopOnly(Component.TableOfContents()),
114110
Component.Backlinks(),
115111
],
112+
afterBody: [
113+
Component.PostListing({
114+
excludeTags: ["private"],
115+
collapsedItemCount: 5,
116+
showEmptyMessage: false,
117+
}),
118+
],
116119
}

quartz/layouts/tags.layout.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ export const tagsLayout: PageLayout = {
1111
Component.Breadcrumbs(),
1212
Component.ArticleTitle(),
1313
Component.ContentMeta(),
14-
Component.PostListing({
15-
excludeTags: ["private"],
16-
showEmptyMessage: true,
17-
}),
1814
],
1915
left: [
2016
Component.PageTitle(),
@@ -41,4 +37,12 @@ export const tagsLayout: PageLayout = {
4137
}),
4238
],
4339
right: [],
40+
afterBody: [
41+
Component.PostListing({
42+
excludeTags: ["private"],
43+
filterToCurrentTag: true,
44+
collapsedItemCount: 10,
45+
showEmptyMessage: true,
46+
}),
47+
],
4448
}

0 commit comments

Comments
 (0)