Skip to content

Commit 95d37cf

Browse files
feat: New Blogs Page Components and emitter Plugin Support Added
1 parent 1641598 commit 95d37cf

File tree

6 files changed

+200
-2
lines changed

6 files changed

+200
-2
lines changed

quartz.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ const config: QuartzConfig = {
8888
Plugin.Assets(),
8989
Plugin.Static(),
9090
Plugin.NotFoundPage(),
91+
Plugin.ExplorerWithTocPage(),
9192
],
9293
},
9394
}

quartz/components/pages/Blogs.tsx

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { classNames } from "../../util/lang"
12
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types"
2-
import style from "./styles/navigationheader.scss"
3+
import styles from "../styles/blogs.scss"
4+
// @ts-ignore
5+
import script from "../scripts/blogpatterns.inline"
36

47
interface Options {
58
links: Record<string, string>
@@ -8,8 +11,66 @@ interface Options {
811

912
export default ((opts?: Options) => {
1013
const Blogs: QuartzComponent = (props: QuartzComponentProps) => {
11-
return <div>Blogs Page</div>
14+
/**
15+
* Sorts all files in descending order based on their creation date.
16+
*
17+
* @param props - The component props containing the allFiles array.
18+
* @returns An array of sorted files with the most recently created files first.
19+
*/
20+
const allFiles = props.allFiles.sort((a, b) => {
21+
return b.dates?.created.valueOf()! - a.dates?.created.valueOf()!
22+
})
23+
return (
24+
<div class="toc-elements">
25+
{allFiles.map((data, index) => {
26+
return (
27+
<div class={classNames(props.displayClass, "toc")}>
28+
<button
29+
type="button"
30+
id="toc"
31+
class={classNames(
32+
props.displayClass,
33+
!data.collapseToc ? "collapsed" : "",
34+
"toc-button",
35+
)}
36+
aria-controls="toc-content"
37+
aria-expanded={!data.collapseToc}
38+
>
39+
<h3>{data.frontmatter?.title}</h3>
40+
<svg
41+
xmlns="http://www.w3.org/2000/svg"
42+
width="24"
43+
height="24"
44+
viewBox="0 0 24 24"
45+
fill="none"
46+
stroke="currentColor"
47+
stroke-width="2"
48+
stroke-linecap="round"
49+
stroke-linejoin="round"
50+
class="fold"
51+
>
52+
<polyline points="6 9 12 15 18 9"></polyline>
53+
</svg>
54+
</button>
55+
<div id="toc-content" class={!props.fileData.collapseToc ? "collapsed" : ""}>
56+
<ul class="overflow">
57+
{data.toc?.map((tocEntry) => (
58+
<li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
59+
<a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>
60+
{tocEntry.text}
61+
</a>
62+
</li>
63+
))}
64+
</ul>
65+
</div>
66+
</div>
67+
)
68+
})}
69+
</div>
70+
)
1271
}
1372

73+
Blogs.css = styles
74+
Blogs.afterDOMLoaded = script
1475
return Blogs
1576
}) satisfies QuartzComponentConstructor
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
3+
const tocbutton = document.querySelectorAll(".toc-button")
4+
5+
function closeAllToc(exclude: Element) {
6+
tocbutton.forEach((value) => {
7+
if (value !== exclude && !value.classList.contains("collapsed")) {
8+
toggleToc(value)
9+
}
10+
})
11+
}
12+
13+
function toggleToc(value: Element) {
14+
console.log("triggerd")
15+
value.classList.toggle("collapsed")
16+
value.nextElementSibling?.classList.toggle("collapsed")
17+
}
18+
19+
tocbutton.forEach((value) => {
20+
value.addEventListener("click", () => {
21+
closeAllToc(value)
22+
23+
toggleToc(value)
24+
})
25+
})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.toc-elements {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 10px;
5+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { QuartzEmitterPlugin } from "../types"
2+
import { QuartzComponentProps } from "../../components/types"
3+
import HeaderConstructor from "../../components/Header"
4+
import BodyConstructor from "../../components/Body"
5+
import { pageResources, renderPage } from "../../components/renderPage"
6+
import { ProcessedContent, QuartzPluginData, defaultProcessedContent } from "../vfile"
7+
import { FullPageLayout } from "../../cfg"
8+
import {
9+
FilePath,
10+
FullSlug,
11+
getAllSegmentPrefixes,
12+
joinSegments,
13+
pathToRoot,
14+
} from "../../util/path"
15+
import {
16+
defaultContentPageLayout,
17+
defaultListPageLayout,
18+
sharedPageComponents,
19+
} from "../../../quartz.layout"
20+
import { Content, TagContent } from "../../components"
21+
import { write } from "./helpers"
22+
import { i18n } from "../../i18n"
23+
import DepGraph from "../../depgraph"
24+
import Blogs from "../../components/pages/Blogs"
25+
26+
interface ExplorerWithTocPageOptions extends FullPageLayout {
27+
sort?: (f1: QuartzPluginData, f2: QuartzPluginData) => number
28+
}
29+
30+
export const ExplorerWithTocPage: QuartzEmitterPlugin<Partial<ExplorerWithTocPageOptions>> = (
31+
userOpts,
32+
) => {
33+
const opts: FullPageLayout = {
34+
...sharedPageComponents,
35+
...defaultContentPageLayout,
36+
pageBody: Blogs(),
37+
...userOpts,
38+
}
39+
40+
const {
41+
head: Head,
42+
header,
43+
navbar,
44+
beforeBody,
45+
pageBody,
46+
afterBody,
47+
left,
48+
right,
49+
footer: Footer,
50+
} = opts
51+
const Header = HeaderConstructor()
52+
const Body = BodyConstructor()
53+
54+
return {
55+
name: "DesignPatterns",
56+
getQuartzComponents() {
57+
return [
58+
Head,
59+
Header,
60+
...navbar,
61+
Body,
62+
...header,
63+
...beforeBody,
64+
pageBody,
65+
...afterBody,
66+
...left,
67+
...right,
68+
Footer,
69+
]
70+
},
71+
async getDependencyGraph(_ctx, _content, _resources) {
72+
return new DepGraph<FilePath>()
73+
},
74+
async emit(ctx, _content, resources): Promise<FilePath[]> {
75+
const cfg = ctx.cfg.configuration
76+
const allFiles = _content.map((c) => c[1].data)
77+
const slug = "blogs" as FullSlug
78+
const title = "Pattern Blogs"
79+
const [tree, vfile] = defaultProcessedContent({
80+
slug,
81+
text: title,
82+
frontmatter: { title: title, tags: [] },
83+
})
84+
const externalResources = pageResources(pathToRoot(slug), vfile.data, resources)
85+
const componentData: QuartzComponentProps = {
86+
ctx,
87+
fileData: vfile.data,
88+
externalResources,
89+
cfg,
90+
children: [],
91+
tree,
92+
allFiles: allFiles,
93+
}
94+
95+
return [
96+
await write({
97+
ctx,
98+
content: renderPage(cfg, slug, componentData, opts, externalResources),
99+
slug,
100+
ext: ".html",
101+
}),
102+
]
103+
},
104+
}
105+
}

quartz/plugins/emitters/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export { Static } from "./static"
88
export { ComponentResources } from "./componentResources"
99
export { NotFoundPage } from "./404"
1010
export { CNAME } from "./cname"
11+
export { ExplorerWithTocPage } from "./explorerwithtocPage"

0 commit comments

Comments
 (0)