mirror of
https://github.com/alrayyes/wiki.git
synced 2024-11-22 03:26:22 +00:00
Merge branch 'v4' of https://github.com/jackyzha0/quartz into v4
This commit is contained in:
commit
1783300c87
23 changed files with 237 additions and 167 deletions
|
@ -260,11 +260,11 @@ export const ContentPage: QuartzEmitterPlugin = () => {
|
||||||
...defaultContentPageLayout,
|
...defaultContentPageLayout,
|
||||||
pageBody: Content(),
|
pageBody: Content(),
|
||||||
}
|
}
|
||||||
const { head, header, beforeBody, pageBody, left, right, footer } = layout
|
const { head, header, beforeBody, pageBody, afterBody, left, right, footer } = layout
|
||||||
return {
|
return {
|
||||||
name: "ContentPage",
|
name: "ContentPage",
|
||||||
getQuartzComponents() {
|
getQuartzComponents() {
|
||||||
return [head, ...header, ...beforeBody, pageBody, ...left, ...right, footer]
|
return [head, ...header, ...beforeBody, pageBody, ...afterBody, ...left, ...right, footer]
|
||||||
},
|
},
|
||||||
async emit(ctx, content, resources, emit): Promise<FilePath[]> {
|
async emit(ctx, content, resources, emit): Promise<FilePath[]> {
|
||||||
const cfg = ctx.cfg.configuration
|
const cfg = ctx.cfg.configuration
|
||||||
|
|
|
@ -53,6 +53,7 @@ This part of the configuration concerns anything that can affect the whole site.
|
||||||
- `secondary`: link colour, current [[graph view|graph]] node
|
- `secondary`: link colour, current [[graph view|graph]] node
|
||||||
- `tertiary`: hover states and visited [[graph view|graph]] nodes
|
- `tertiary`: hover states and visited [[graph view|graph]] nodes
|
||||||
- `highlight`: internal link background, highlighted text, [[syntax highlighting|highlighted lines of code]]
|
- `highlight`: internal link background, highlighted text, [[syntax highlighting|highlighted lines of code]]
|
||||||
|
- `textHighlight`: markdown highlighted text background
|
||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ As with folder listings, you can also provide a description and title for a tag
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
The folder listings are a functionality of the [[FolderPage]] plugin, the tag listings of the [[TagPage]] plugin. See the plugin pages for customization options.
|
Quartz allows you to define a custom sort ordering for content on both page types. The folder listings are a functionality of the [[FolderPage]] plugin, the tag listings of the [[TagPage]] plugin. See the plugin pages for customization options.
|
||||||
|
|
|
@ -2,22 +2,12 @@
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
## high priority backlog
|
|
||||||
|
|
||||||
- static dead link detection
|
|
||||||
- block links: https://help.obsidian.md/Linking+notes+and+files/Internal+links#Link+to+a+block+in+a+note
|
|
||||||
- note/header/block transcludes: https://help.obsidian.md/Linking+notes+and+files/Embedding+files
|
|
||||||
- docker support
|
|
||||||
|
|
||||||
## misc backlog
|
## misc backlog
|
||||||
|
|
||||||
- breadcrumbs component
|
- static dead link detection
|
||||||
- cursor chat extension
|
- cursor chat extension
|
||||||
- https://giscus.app/ extension
|
- https://giscus.app/ extension
|
||||||
- sidenotes? https://github.com/capnfabs/paperesque
|
- sidenotes? https://github.com/capnfabs/paperesque
|
||||||
- direct match in search using double quotes
|
- direct match in search using double quotes
|
||||||
- https://help.obsidian.md/Advanced+topics/Using+Obsidian+URI
|
- https://help.obsidian.md/Advanced+topics/Using+Obsidian+URI
|
||||||
- audio/video embed styling
|
|
||||||
- Canvas
|
- Canvas
|
||||||
- parse all images in page: use this for page lists if applicable?
|
|
||||||
- CV mode? with print stylesheet
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 65 KiB |
|
@ -12,6 +12,7 @@ export interface FullPageLayout {
|
||||||
header: QuartzComponent[] // laid out horizontally
|
header: QuartzComponent[] // laid out horizontally
|
||||||
beforeBody: QuartzComponent[] // laid out vertically
|
beforeBody: QuartzComponent[] // laid out vertically
|
||||||
pageBody: QuartzComponent // single component
|
pageBody: QuartzComponent // single component
|
||||||
|
afterBody: QuartzComponent[] // laid out vertically
|
||||||
left: QuartzComponent[] // vertical on desktop, horizontal on mobile
|
left: QuartzComponent[] // vertical on desktop, horizontal on mobile
|
||||||
right: QuartzComponent[] // vertical on desktop, horizontal on mobile
|
right: QuartzComponent[] // vertical on desktop, horizontal on mobile
|
||||||
footer: QuartzComponent // single component
|
footer: QuartzComponent // single component
|
||||||
|
|
|
@ -11,10 +11,12 @@ Example: [[advanced/|Advanced]]
|
||||||
> [!note]
|
> [!note]
|
||||||
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
|
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
|
||||||
|
|
||||||
This plugin has no configuration options.
|
|
||||||
|
|
||||||
The pages are displayed using the `defaultListPageLayout` in `quartz.layouts.ts`. For the content, the `FolderContent` component is used. If you want to modify the layout, you must edit it directly (`quartz/components/pages/FolderContent.tsx`).
|
The pages are displayed using the `defaultListPageLayout` in `quartz.layouts.ts`. For the content, the `FolderContent` component is used. If you want to modify the layout, you must edit it directly (`quartz/components/pages/FolderContent.tsx`).
|
||||||
|
|
||||||
|
This plugin accepts the following configuration options:
|
||||||
|
|
||||||
|
- `sort`: A function of type `(f1: QuartzPluginData, f2: QuartzPluginData) => number{:ts}` used to sort entries. Defaults to sorting by date and tie-breaking on lexographical order.
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
- Category: Emitter
|
- Category: Emitter
|
||||||
|
|
|
@ -9,10 +9,12 @@ This plugin emits dedicated pages for each tag used in the content. See [[folder
|
||||||
> [!note]
|
> [!note]
|
||||||
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
|
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
|
||||||
|
|
||||||
This plugin has no configuration options.
|
|
||||||
|
|
||||||
The pages are displayed using the `defaultListPageLayout` in `quartz.layouts.ts`. For the content, the `TagContent` component is used. If you want to modify the layout, you must edit it directly (`quartz/components/pages/TagContent.tsx`).
|
The pages are displayed using the `defaultListPageLayout` in `quartz.layouts.ts`. For the content, the `TagContent` component is used. If you want to modify the layout, you must edit it directly (`quartz/components/pages/TagContent.tsx`).
|
||||||
|
|
||||||
|
This plugin accepts the following configuration options:
|
||||||
|
|
||||||
|
- `sort`: A function of type `(f1: QuartzPluginData, f2: QuartzPluginData) => number{:ts}` used to sort entries. Defaults to sorting by date and tie-breaking on lexographical order.
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
- Category: Emitter
|
- Category: Emitter
|
||||||
|
|
|
@ -34,6 +34,7 @@ const config: QuartzConfig = {
|
||||||
secondary: "#284b63",
|
secondary: "#284b63",
|
||||||
tertiary: "#84a59d",
|
tertiary: "#84a59d",
|
||||||
highlight: "rgba(143, 159, 169, 0.15)",
|
highlight: "rgba(143, 159, 169, 0.15)",
|
||||||
|
textHighlight: "#fff23688",
|
||||||
},
|
},
|
||||||
darkMode: {
|
darkMode: {
|
||||||
light: "#161618",
|
light: "#161618",
|
||||||
|
@ -44,6 +45,7 @@ const config: QuartzConfig = {
|
||||||
secondary: "#7b97aa",
|
secondary: "#7b97aa",
|
||||||
tertiary: "#84a59d",
|
tertiary: "#84a59d",
|
||||||
highlight: "rgba(143, 159, 169, 0.15)",
|
highlight: "rgba(143, 159, 169, 0.15)",
|
||||||
|
textHighlight: "#b3aa0288",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@ import * as Component from "./quartz/components"
|
||||||
export const sharedPageComponents: SharedLayout = {
|
export const sharedPageComponents: SharedLayout = {
|
||||||
head: Component.Head(),
|
head: Component.Head(),
|
||||||
header: [],
|
header: [],
|
||||||
|
afterBody: [],
|
||||||
footer: Component.Footer({
|
footer: Component.Footer({
|
||||||
links: {
|
links: {
|
||||||
"Ryan's Namepage": "https://ryankes.eu",
|
"Ryan's Namepage": "https://ryankes.eu",
|
||||||
|
|
|
@ -77,10 +77,11 @@ export interface FullPageLayout {
|
||||||
header: QuartzComponent[]
|
header: QuartzComponent[]
|
||||||
beforeBody: QuartzComponent[]
|
beforeBody: QuartzComponent[]
|
||||||
pageBody: QuartzComponent
|
pageBody: QuartzComponent
|
||||||
|
afterBody: QuartzComponent[]
|
||||||
left: QuartzComponent[]
|
left: QuartzComponent[]
|
||||||
right: QuartzComponent[]
|
right: QuartzComponent[]
|
||||||
footer: QuartzComponent
|
footer: QuartzComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PageLayout = Pick<FullPageLayout, "beforeBody" | "left" | "right">
|
export type PageLayout = Pick<FullPageLayout, "beforeBody" | "left" | "right">
|
||||||
export type SharedLayout = Pick<FullPageLayout, "head" | "header" | "footer">
|
export type SharedLayout = Pick<FullPageLayout, "head" | "header" | "footer" | "afterBody">
|
||||||
|
|
|
@ -13,7 +13,6 @@ export default ((opts?: Options) => {
|
||||||
const links = opts?.links ?? []
|
const links = opts?.links ?? []
|
||||||
return (
|
return (
|
||||||
<footer class={`${displayClass ?? ""}`}>
|
<footer class={`${displayClass ?? ""}`}>
|
||||||
<hr />
|
|
||||||
<p>
|
<p>
|
||||||
{i18n(cfg.locale).components.footer.createdWith}{" "}
|
{i18n(cfg.locale).components.footer.createdWith}{" "}
|
||||||
<a href="https://quartz.jzhao.xyz/">Quartz v{version}</a> © {year}
|
<a href="https://quartz.jzhao.xyz/">Quartz v{version}</a> © {year}
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { Date, getDate } from "./Date"
|
||||||
import { QuartzComponent, QuartzComponentProps } from "./types"
|
import { QuartzComponent, QuartzComponentProps } from "./types"
|
||||||
import { GlobalConfiguration } from "../cfg"
|
import { GlobalConfiguration } from "../cfg"
|
||||||
|
|
||||||
export function byDateAndAlphabetical(
|
export type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number
|
||||||
cfg: GlobalConfiguration,
|
|
||||||
): (f1: QuartzPluginData, f2: QuartzPluginData) => number {
|
export function byDateAndAlphabetical(cfg: GlobalConfiguration): SortFn {
|
||||||
return (f1, f2) => {
|
return (f1, f2) => {
|
||||||
if (f1.dates && f2.dates) {
|
if (f1.dates && f2.dates) {
|
||||||
// sort descending
|
// sort descending
|
||||||
|
@ -27,10 +27,12 @@ export function byDateAndAlphabetical(
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
limit?: number
|
limit?: number
|
||||||
|
sort?: SortFn
|
||||||
} & QuartzComponentProps
|
} & QuartzComponentProps
|
||||||
|
|
||||||
export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit }: Props) => {
|
export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit, sort }: Props) => {
|
||||||
let list = allFiles.sort(byDateAndAlphabetical(cfg))
|
const sorter = sort ?? byDateAndAlphabetical(cfg)
|
||||||
|
let list = allFiles.sort(sorter)
|
||||||
if (limit) {
|
if (limit) {
|
||||||
list = list.slice(0, limit)
|
list = list.slice(0, limit)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } fro
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
import style from "../styles/listPage.scss"
|
import style from "../styles/listPage.scss"
|
||||||
import { PageList } from "../PageList"
|
import { PageList, SortFn } from "../PageList"
|
||||||
import { stripSlashes, simplifySlug } from "../../util/path"
|
import { stripSlashes, simplifySlug } from "../../util/path"
|
||||||
import { Root } from "hast"
|
import { Root } from "hast"
|
||||||
import { htmlToJsx } from "../../util/jsx"
|
import { htmlToJsx } from "../../util/jsx"
|
||||||
|
@ -13,6 +13,7 @@ interface FolderContentOptions {
|
||||||
* Whether to display number of folders
|
* Whether to display number of folders
|
||||||
*/
|
*/
|
||||||
showFolderCount: boolean
|
showFolderCount: boolean
|
||||||
|
sort?: SortFn
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: FolderContentOptions = {
|
const defaultOptions: FolderContentOptions = {
|
||||||
|
@ -37,6 +38,7 @@ export default ((opts?: Partial<FolderContentOptions>) => {
|
||||||
const classes = ["popover-hint", ...cssClasses].join(" ")
|
const classes = ["popover-hint", ...cssClasses].join(" ")
|
||||||
const listProps = {
|
const listProps = {
|
||||||
...props,
|
...props,
|
||||||
|
sort: options.sort,
|
||||||
allFiles: allPagesInFolder,
|
allFiles: allPagesInFolder,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,113 +1,127 @@
|
||||||
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types"
|
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types"
|
||||||
import style from "../styles/listPage.scss"
|
import style from "../styles/listPage.scss"
|
||||||
import { PageList } from "../PageList"
|
import { PageList, SortFn } from "../PageList"
|
||||||
import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path"
|
import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path"
|
||||||
import { QuartzPluginData } from "../../plugins/vfile"
|
import { QuartzPluginData } from "../../plugins/vfile"
|
||||||
import { Root } from "hast"
|
import { Root } from "hast"
|
||||||
import { htmlToJsx } from "../../util/jsx"
|
import { htmlToJsx } from "../../util/jsx"
|
||||||
import { i18n } from "../../i18n"
|
import { i18n } from "../../i18n"
|
||||||
|
|
||||||
const numPages = 10
|
interface TagContentOptions {
|
||||||
const TagContent: QuartzComponent = (props: QuartzComponentProps) => {
|
sort?: SortFn
|
||||||
const { tree, fileData, allFiles, cfg } = props
|
numPages: number
|
||||||
const slug = fileData.slug
|
|
||||||
|
|
||||||
if (!(slug?.startsWith("tags/") || slug === "tags")) {
|
|
||||||
throw new Error(`Component "TagContent" tried to render a non-tag page: ${slug}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const tag = simplifySlug(slug.slice("tags/".length) as FullSlug)
|
|
||||||
const allPagesWithTag = (tag: string) =>
|
|
||||||
allFiles.filter((file) =>
|
|
||||||
(file.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes).includes(tag),
|
|
||||||
)
|
|
||||||
|
|
||||||
const content =
|
|
||||||
(tree as Root).children.length === 0
|
|
||||||
? fileData.description
|
|
||||||
: htmlToJsx(fileData.filePath!, tree)
|
|
||||||
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
|
|
||||||
const classes = ["popover-hint", ...cssClasses].join(" ")
|
|
||||||
if (tag === "/") {
|
|
||||||
const tags = [
|
|
||||||
...new Set(
|
|
||||||
allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
|
|
||||||
),
|
|
||||||
].sort((a, b) => a.localeCompare(b))
|
|
||||||
const tagItemMap: Map<string, QuartzPluginData[]> = new Map()
|
|
||||||
for (const tag of tags) {
|
|
||||||
tagItemMap.set(tag, allPagesWithTag(tag))
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div class={classes}>
|
|
||||||
<article>
|
|
||||||
<p>{content}</p>
|
|
||||||
</article>
|
|
||||||
<p>{i18n(cfg.locale).pages.tagContent.totalTags({ count: tags.length })}</p>
|
|
||||||
<div>
|
|
||||||
{tags.map((tag) => {
|
|
||||||
const pages = tagItemMap.get(tag)!
|
|
||||||
const listProps = {
|
|
||||||
...props,
|
|
||||||
allFiles: pages,
|
|
||||||
}
|
|
||||||
|
|
||||||
const contentPage = allFiles.filter((file) => file.slug === `tags/${tag}`).at(0)
|
|
||||||
|
|
||||||
const root = contentPage?.htmlAst
|
|
||||||
const content =
|
|
||||||
!root || root?.children.length === 0
|
|
||||||
? contentPage?.description
|
|
||||||
: htmlToJsx(contentPage.filePath!, root)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h2>
|
|
||||||
<a class="internal tag-link" href={`../tags/${tag}`}>
|
|
||||||
{tag}
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
{content && <p>{content}</p>}
|
|
||||||
<div class="page-listing">
|
|
||||||
<p>
|
|
||||||
{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}
|
|
||||||
{pages.length > numPages && (
|
|
||||||
<>
|
|
||||||
{" "}
|
|
||||||
<span>
|
|
||||||
{i18n(cfg.locale).pages.tagContent.showingFirst({ count: numPages })}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<PageList limit={numPages} {...listProps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
const pages = allPagesWithTag(tag)
|
|
||||||
const listProps = {
|
|
||||||
...props,
|
|
||||||
allFiles: pages,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class={classes}>
|
|
||||||
<article>{content}</article>
|
|
||||||
<div class="page-listing">
|
|
||||||
<p>{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}</p>
|
|
||||||
<div>
|
|
||||||
<PageList {...listProps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TagContent.css = style + PageList.css
|
const defaultOptions: TagContentOptions = {
|
||||||
export default (() => TagContent) satisfies QuartzComponentConstructor
|
numPages: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ((opts?: Partial<TagContentOptions>) => {
|
||||||
|
const options: TagContentOptions = { ...defaultOptions, ...opts }
|
||||||
|
|
||||||
|
const TagContent: QuartzComponent = (props: QuartzComponentProps) => {
|
||||||
|
const { tree, fileData, allFiles, cfg } = props
|
||||||
|
const slug = fileData.slug
|
||||||
|
|
||||||
|
if (!(slug?.startsWith("tags/") || slug === "tags")) {
|
||||||
|
throw new Error(`Component "TagContent" tried to render a non-tag page: ${slug}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tag = simplifySlug(slug.slice("tags/".length) as FullSlug)
|
||||||
|
const allPagesWithTag = (tag: string) =>
|
||||||
|
allFiles.filter((file) =>
|
||||||
|
(file.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes).includes(tag),
|
||||||
|
)
|
||||||
|
|
||||||
|
const content =
|
||||||
|
(tree as Root).children.length === 0
|
||||||
|
? fileData.description
|
||||||
|
: htmlToJsx(fileData.filePath!, tree)
|
||||||
|
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
|
||||||
|
const classes = ["popover-hint", ...cssClasses].join(" ")
|
||||||
|
if (tag === "/") {
|
||||||
|
const tags = [
|
||||||
|
...new Set(
|
||||||
|
allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
|
||||||
|
),
|
||||||
|
].sort((a, b) => a.localeCompare(b))
|
||||||
|
const tagItemMap: Map<string, QuartzPluginData[]> = new Map()
|
||||||
|
for (const tag of tags) {
|
||||||
|
tagItemMap.set(tag, allPagesWithTag(tag))
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div class={classes}>
|
||||||
|
<article>
|
||||||
|
<p>{content}</p>
|
||||||
|
</article>
|
||||||
|
<p>{i18n(cfg.locale).pages.tagContent.totalTags({ count: tags.length })}</p>
|
||||||
|
<div>
|
||||||
|
{tags.map((tag) => {
|
||||||
|
const pages = tagItemMap.get(tag)!
|
||||||
|
const listProps = {
|
||||||
|
...props,
|
||||||
|
allFiles: pages,
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentPage = allFiles.filter((file) => file.slug === `tags/${tag}`).at(0)
|
||||||
|
|
||||||
|
const root = contentPage?.htmlAst
|
||||||
|
const content =
|
||||||
|
!root || root?.children.length === 0
|
||||||
|
? contentPage?.description
|
||||||
|
: htmlToJsx(contentPage.filePath!, root)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>
|
||||||
|
<a class="internal tag-link" href={`../tags/${tag}`}>
|
||||||
|
{tag}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{content && <p>{content}</p>}
|
||||||
|
<div class="page-listing">
|
||||||
|
<p>
|
||||||
|
{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}
|
||||||
|
{pages.length > options.numPages && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<span>
|
||||||
|
{i18n(cfg.locale).pages.tagContent.showingFirst({
|
||||||
|
count: options.numPages,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<PageList limit={options.numPages} {...listProps} sort={opts?.sort} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const pages = allPagesWithTag(tag)
|
||||||
|
const listProps = {
|
||||||
|
...props,
|
||||||
|
allFiles: pages,
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={classes}>
|
||||||
|
<article>{content}</article>
|
||||||
|
<div class="page-listing">
|
||||||
|
<p>{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}</p>
|
||||||
|
<div>
|
||||||
|
<PageList {...listProps} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TagContent.css = style + PageList.css
|
||||||
|
return TagContent
|
||||||
|
}) satisfies QuartzComponentConstructor
|
||||||
|
|
|
@ -14,6 +14,7 @@ interface RenderComponents {
|
||||||
header: QuartzComponent[]
|
header: QuartzComponent[]
|
||||||
beforeBody: QuartzComponent[]
|
beforeBody: QuartzComponent[]
|
||||||
pageBody: QuartzComponent
|
pageBody: QuartzComponent
|
||||||
|
afterBody: QuartzComponent[]
|
||||||
left: QuartzComponent[]
|
left: QuartzComponent[]
|
||||||
right: QuartzComponent[]
|
right: QuartzComponent[]
|
||||||
footer: QuartzComponent
|
footer: QuartzComponent
|
||||||
|
@ -187,6 +188,7 @@ export function renderPage(
|
||||||
header,
|
header,
|
||||||
beforeBody,
|
beforeBody,
|
||||||
pageBody: Content,
|
pageBody: Content,
|
||||||
|
afterBody,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
footer: Footer,
|
footer: Footer,
|
||||||
|
@ -232,6 +234,12 @@ export function renderPage(
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Content {...componentData} />
|
<Content {...componentData} />
|
||||||
|
<hr />
|
||||||
|
<div class="page-footer">
|
||||||
|
{afterBody.map((BodyComponent) => (
|
||||||
|
<BodyComponent {...componentData} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{RightComponent}
|
{RightComponent}
|
||||||
</Body>
|
</Body>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { normalizeRelativeURLs } from "../../util/path"
|
||||||
|
|
||||||
const p = new DOMParser()
|
const p = new DOMParser()
|
||||||
async function mouseEnterHandler(
|
async function mouseEnterHandler(
|
||||||
this: HTMLLinkElement,
|
this: HTMLAnchorElement,
|
||||||
{ clientX, clientY }: { clientX: number; clientY: number },
|
{ clientX, clientY }: { clientX: number; clientY: number },
|
||||||
) {
|
) {
|
||||||
const link = this
|
const link = this
|
||||||
|
@ -33,7 +33,7 @@ async function mouseEnterHandler(
|
||||||
thisUrl.hash = ""
|
thisUrl.hash = ""
|
||||||
thisUrl.search = ""
|
thisUrl.search = ""
|
||||||
const targetUrl = new URL(link.href)
|
const targetUrl = new URL(link.href)
|
||||||
const hash = targetUrl.hash
|
const hash = decodeURIComponent(targetUrl.hash)
|
||||||
targetUrl.hash = ""
|
targetUrl.hash = ""
|
||||||
targetUrl.search = ""
|
targetUrl.search = ""
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ async function mouseEnterHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("nav", () => {
|
document.addEventListener("nav", () => {
|
||||||
const links = [...document.getElementsByClassName("internal")] as HTMLLinkElement[]
|
const links = [...document.getElementsByClassName("internal")] as HTMLAnchorElement[]
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
link.addEventListener("mouseenter", mouseEnterHandler)
|
link.addEventListener("mouseenter", mouseEnterHandler)
|
||||||
window.addCleanup(() => link.removeEventListener("mouseenter", mouseEnterHandler))
|
window.addCleanup(() => link.removeEventListener("mouseenter", mouseEnterHandler))
|
||||||
|
|
|
@ -59,14 +59,25 @@ export const ContentPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOp
|
||||||
...userOpts,
|
...userOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
|
const { head: Head, header, beforeBody, pageBody, afterBody, left, right, footer: Footer } = opts
|
||||||
const Header = HeaderConstructor()
|
const Header = HeaderConstructor()
|
||||||
const Body = BodyConstructor()
|
const Body = BodyConstructor()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "ContentPage",
|
name: "ContentPage",
|
||||||
getQuartzComponents() {
|
getQuartzComponents() {
|
||||||
return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
|
return [
|
||||||
|
Head,
|
||||||
|
Header,
|
||||||
|
Body,
|
||||||
|
...header,
|
||||||
|
...beforeBody,
|
||||||
|
pageBody,
|
||||||
|
...afterBody,
|
||||||
|
...left,
|
||||||
|
...right,
|
||||||
|
Footer,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
async getDependencyGraph(ctx, content, _resources) {
|
async getDependencyGraph(ctx, content, _resources) {
|
||||||
const graph = new DepGraph<FilePath>()
|
const graph = new DepGraph<FilePath>()
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { QuartzComponentProps } from "../../components/types"
|
||||||
import HeaderConstructor from "../../components/Header"
|
import HeaderConstructor from "../../components/Header"
|
||||||
import BodyConstructor from "../../components/Body"
|
import BodyConstructor from "../../components/Body"
|
||||||
import { pageResources, renderPage } from "../../components/renderPage"
|
import { pageResources, renderPage } from "../../components/renderPage"
|
||||||
import { ProcessedContent, defaultProcessedContent } from "../vfile"
|
import { ProcessedContent, QuartzPluginData, defaultProcessedContent } from "../vfile"
|
||||||
import { FullPageLayout } from "../../cfg"
|
import { FullPageLayout } from "../../cfg"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import {
|
import {
|
||||||
|
@ -21,22 +21,37 @@ import { write } from "./helpers"
|
||||||
import { i18n } from "../../i18n"
|
import { i18n } from "../../i18n"
|
||||||
import DepGraph from "../../depgraph"
|
import DepGraph from "../../depgraph"
|
||||||
|
|
||||||
export const FolderPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOpts) => {
|
interface FolderPageOptions extends FullPageLayout {
|
||||||
|
sort?: (f1: QuartzPluginData, f2: QuartzPluginData) => number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FolderPage: QuartzEmitterPlugin<Partial<FolderPageOptions>> = (userOpts) => {
|
||||||
const opts: FullPageLayout = {
|
const opts: FullPageLayout = {
|
||||||
...sharedPageComponents,
|
...sharedPageComponents,
|
||||||
...defaultListPageLayout,
|
...defaultListPageLayout,
|
||||||
pageBody: FolderContent(),
|
pageBody: FolderContent({ sort: userOpts?.sort }),
|
||||||
...userOpts,
|
...userOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
|
const { head: Head, header, beforeBody, pageBody, afterBody, left, right, footer: Footer } = opts
|
||||||
const Header = HeaderConstructor()
|
const Header = HeaderConstructor()
|
||||||
const Body = BodyConstructor()
|
const Body = BodyConstructor()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "FolderPage",
|
name: "FolderPage",
|
||||||
getQuartzComponents() {
|
getQuartzComponents() {
|
||||||
return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
|
return [
|
||||||
|
Head,
|
||||||
|
Header,
|
||||||
|
Body,
|
||||||
|
...header,
|
||||||
|
...beforeBody,
|
||||||
|
pageBody,
|
||||||
|
...afterBody,
|
||||||
|
...left,
|
||||||
|
...right,
|
||||||
|
Footer,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
async getDependencyGraph(_ctx, content, _resources) {
|
async getDependencyGraph(_ctx, content, _resources) {
|
||||||
// Example graph:
|
// Example graph:
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { QuartzComponentProps } from "../../components/types"
|
||||||
import HeaderConstructor from "../../components/Header"
|
import HeaderConstructor from "../../components/Header"
|
||||||
import BodyConstructor from "../../components/Body"
|
import BodyConstructor from "../../components/Body"
|
||||||
import { pageResources, renderPage } from "../../components/renderPage"
|
import { pageResources, renderPage } from "../../components/renderPage"
|
||||||
import { ProcessedContent, defaultProcessedContent } from "../vfile"
|
import { ProcessedContent, QuartzPluginData, defaultProcessedContent } from "../vfile"
|
||||||
import { FullPageLayout } from "../../cfg"
|
import { FullPageLayout } from "../../cfg"
|
||||||
import {
|
import {
|
||||||
FilePath,
|
FilePath,
|
||||||
|
@ -18,22 +18,37 @@ import { write } from "./helpers"
|
||||||
import { i18n } from "../../i18n"
|
import { i18n } from "../../i18n"
|
||||||
import DepGraph from "../../depgraph"
|
import DepGraph from "../../depgraph"
|
||||||
|
|
||||||
export const TagPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOpts) => {
|
interface TagPageOptions extends FullPageLayout {
|
||||||
|
sort?: (f1: QuartzPluginData, f2: QuartzPluginData) => number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TagPage: QuartzEmitterPlugin<Partial<TagPageOptions>> = (userOpts) => {
|
||||||
const opts: FullPageLayout = {
|
const opts: FullPageLayout = {
|
||||||
...sharedPageComponents,
|
...sharedPageComponents,
|
||||||
...defaultListPageLayout,
|
...defaultListPageLayout,
|
||||||
pageBody: TagContent(),
|
pageBody: TagContent({ sort: userOpts?.sort }),
|
||||||
...userOpts,
|
...userOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
|
const { head: Head, header, beforeBody, pageBody, afterBody, left, right, footer: Footer } = opts
|
||||||
const Header = HeaderConstructor()
|
const Header = HeaderConstructor()
|
||||||
const Body = BodyConstructor()
|
const Body = BodyConstructor()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "TagPage",
|
name: "TagPage",
|
||||||
getQuartzComponents() {
|
getQuartzComponents() {
|
||||||
return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
|
return [
|
||||||
|
Head,
|
||||||
|
Header,
|
||||||
|
Body,
|
||||||
|
...header,
|
||||||
|
...beforeBody,
|
||||||
|
pageBody,
|
||||||
|
...afterBody,
|
||||||
|
...left,
|
||||||
|
...right,
|
||||||
|
Footer,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
async getDependencyGraph(ctx, content, _resources) {
|
async getDependencyGraph(ctx, content, _resources) {
|
||||||
const graph = new DepGraph<FilePath>()
|
const graph = new DepGraph<FilePath>()
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { QuartzTransformerPlugin } from "../types"
|
||||||
import { Root, Html, BlockContent, DefinitionContent, Paragraph, Code } from "mdast"
|
import { Root, Html, BlockContent, DefinitionContent, Paragraph, Code } from "mdast"
|
||||||
import { Element, Literal, Root as HtmlRoot } from "hast"
|
import { Element, Literal, Root as HtmlRoot } from "hast"
|
||||||
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
|
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
|
||||||
import { slug as slugAnchor } from "github-slugger"
|
|
||||||
import rehypeRaw from "rehype-raw"
|
import rehypeRaw from "rehype-raw"
|
||||||
import { SKIP, visit } from "unist-util-visit"
|
import { SKIP, visit } from "unist-util-visit"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
@ -98,7 +97,7 @@ function canonicalizeCallout(calloutName: string): keyof typeof calloutMapping {
|
||||||
|
|
||||||
export const externalLinkRegex = /^https?:\/\//i
|
export const externalLinkRegex = /^https?:\/\//i
|
||||||
|
|
||||||
export const arrowRegex = new RegExp(/(-{1,2}>|={1,2}>|<-{1,2}|<={1,2})/, "g")
|
export const arrowRegex = new RegExp(/(-{1,2}>|={1,2}>|<-{1,2}|<={1,2})/g)
|
||||||
|
|
||||||
// !? -> optional embedding
|
// !? -> optional embedding
|
||||||
// \[\[ -> open brace
|
// \[\[ -> open brace
|
||||||
|
@ -106,35 +105,30 @@ export const arrowRegex = new RegExp(/(-{1,2}>|={1,2}>|<-{1,2}|<={1,2})/, "g")
|
||||||
// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
|
// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
|
||||||
// (\\?\|[^\[\]\#]+)? -> optional escape \ then | then one or more non-special characters (alias)
|
// (\\?\|[^\[\]\#]+)? -> optional escape \ then | then one or more non-special characters (alias)
|
||||||
export const wikilinkRegex = new RegExp(
|
export const wikilinkRegex = new RegExp(
|
||||||
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]/,
|
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]/g,
|
||||||
"g",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ^\|([^\n])+\|\n(\|) -> matches the header row
|
// ^\|([^\n])+\|\n(\|) -> matches the header row
|
||||||
// ( ?:?-{3,}:? ?\|)+ -> matches the header row separator
|
// ( ?:?-{3,}:? ?\|)+ -> matches the header row separator
|
||||||
// (\|([^\n])+\|\n)+ -> matches the body rows
|
// (\|([^\n])+\|\n)+ -> matches the body rows
|
||||||
export const tableRegex = new RegExp(
|
export const tableRegex = new RegExp(/^\|([^\n])+\|\n(\|)( ?:?-{3,}:? ?\|)+\n(\|([^\n])+\|\n?)+/gm)
|
||||||
/^\|([^\n])+\|\n(\|)( ?:?-{3,}:? ?\|)+\n(\|([^\n])+\|\n?)+/,
|
|
||||||
"gm",
|
|
||||||
)
|
|
||||||
|
|
||||||
// matches any wikilink, only used for escaping wikilinks inside tables
|
// matches any wikilink, only used for escaping wikilinks inside tables
|
||||||
export const tableWikilinkRegex = new RegExp(/(!?\[\[[^\]]*?\]\])/, "g")
|
export const tableWikilinkRegex = new RegExp(/(!?\[\[[^\]]*?\]\])/g)
|
||||||
|
|
||||||
const highlightRegex = new RegExp(/==([^=]+)==/, "g")
|
const highlightRegex = new RegExp(/==([^=]+)==/g)
|
||||||
const commentRegex = new RegExp(/%%[\s\S]*?%%/, "g")
|
const commentRegex = new RegExp(/%%[\s\S]*?%%/g)
|
||||||
// from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
|
// from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
|
||||||
const calloutRegex = new RegExp(/^\[\!(\w+)\|?(.+?)?\]([+-]?)/)
|
const calloutRegex = new RegExp(/^\[\!(\w+)\|?(.+?)?\]([+-]?)/)
|
||||||
const calloutLineRegex = new RegExp(/^> *\[\!\w+\|?.*?\][+-]?.*$/, "gm")
|
const calloutLineRegex = new RegExp(/^> *\[\!\w+\|?.*?\][+-]?.*$/gm)
|
||||||
// (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line
|
// (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line
|
||||||
// #(...) -> capturing group, tag itself must start with #
|
// #(...) -> capturing group, tag itself must start with #
|
||||||
// (?:[-_\p{L}\d\p{Z}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters and symbols, hyphens and/or underscores
|
// (?:[-_\p{L}\d\p{Z}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters and symbols, hyphens and/or underscores
|
||||||
// (?:\/[-_\p{L}\d\p{Z}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/"
|
// (?:\/[-_\p{L}\d\p{Z}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/"
|
||||||
const tagRegex = new RegExp(
|
const tagRegex = new RegExp(
|
||||||
/(?:^| )#((?:[-_\p{L}\p{Emoji}\p{M}\d])+(?:\/[-_\p{L}\p{Emoji}\p{M}\d]+)*)/,
|
/(?:^| )#((?:[-_\p{L}\p{Emoji}\p{M}\d])+(?:\/[-_\p{L}\p{Emoji}\p{M}\d]+)*)/gu,
|
||||||
"gu",
|
|
||||||
)
|
)
|
||||||
const blockReferenceRegex = new RegExp(/\^([-_A-Za-z0-9]+)$/, "g")
|
const blockReferenceRegex = new RegExp(/\^([-_A-Za-z0-9]+)$/g)
|
||||||
const ytLinkRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
|
const ytLinkRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
|
||||||
const ytPlaylistLinkRegex = /[?&]list=([^#?&]*)/
|
const ytPlaylistLinkRegex = /[?&]list=([^#?&]*)/
|
||||||
const videoExtensionRegex = new RegExp(/\.(mp4|webm|ogg|avi|mov|flv|wmv|mkv|mpg|mpeg|3gp|m4v)$/)
|
const videoExtensionRegex = new RegExp(/\.(mp4|webm|ogg|avi|mov|flv|wmv|mkv|mpg|mpeg|3gp|m4v)$/)
|
||||||
|
@ -185,8 +179,8 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
|
||||||
// replace all wikilinks inside a table first
|
// replace all wikilinks inside a table first
|
||||||
src = src.replace(tableRegex, (value) => {
|
src = src.replace(tableRegex, (value) => {
|
||||||
// escape all aliases and headers in wikilinks inside a table
|
// escape all aliases and headers in wikilinks inside a table
|
||||||
return value.replace(tableWikilinkRegex, (value, ...capture) => {
|
return value.replace(tableWikilinkRegex, (_value, raw) => {
|
||||||
const [raw]: (string | undefined)[] = capture
|
// const [raw]: (string | undefined)[] = capture
|
||||||
let escaped = raw ?? ""
|
let escaped = raw ?? ""
|
||||||
escaped = escaped.replace("#", "\\#")
|
escaped = escaped.replace("#", "\\#")
|
||||||
// escape pipe characters if they are not already escaped
|
// escape pipe characters if they are not already escaped
|
||||||
|
@ -201,7 +195,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
|
||||||
const [rawFp, rawHeader, rawAlias]: (string | undefined)[] = capture
|
const [rawFp, rawHeader, rawAlias]: (string | undefined)[] = capture
|
||||||
|
|
||||||
const [fp, anchor] = splitAnchor(`${rawFp ?? ""}${rawHeader ?? ""}`)
|
const [fp, anchor] = splitAnchor(`${rawFp ?? ""}${rawHeader ?? ""}`)
|
||||||
const blockRef = Boolean(anchor?.startsWith("^")) ? "^" : ""
|
const blockRef = Boolean(rawHeader?.match(/^#?\^/)) ? "^" : ""
|
||||||
const displayAnchor = anchor ? `#${blockRef}${anchor.trim().replace(/^#+/, "")}` : ""
|
const displayAnchor = anchor ? `#${blockRef}${anchor.trim().replace(/^#+/, "")}` : ""
|
||||||
const displayAlias = rawAlias ?? rawHeader?.replace("#", "|") ?? ""
|
const displayAlias = rawAlias ?? rawHeader?.replace("#", "|") ?? ""
|
||||||
const embedDisplay = value.startsWith("!") ? "!" : ""
|
const embedDisplay = value.startsWith("!") ? "!" : ""
|
||||||
|
@ -276,7 +270,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
|
||||||
return {
|
return {
|
||||||
type: "html",
|
type: "html",
|
||||||
data: { hProperties: { transclude: true } },
|
data: { hProperties: { transclude: true } },
|
||||||
value: `<blockquote class="transclude" data-url="${url}" data-block="${block}"><a href="${
|
value: `<blockquote class="transclude" data-url="${url}" data-block="${block}" data-embed-alias="${alias}"><a href="${
|
||||||
url + anchor
|
url + anchor
|
||||||
}" class="transclude-inner">Transclude of ${url}${block}</a></blockquote>`,
|
}" class="transclude-inner">Transclude of ${url}${block}</a></blockquote>`,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,10 @@ section {
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-highlight {
|
.text-highlight {
|
||||||
background-color: #fff23688;
|
background-color: var(--textHighlight);
|
||||||
padding: 0 0.1rem;
|
padding: 0 0.1rem;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: color-mix(in srgb, var(--tertiary) 60%, rgba(255, 255, 255, 0));
|
background: color-mix(in srgb, var(--tertiary) 60%, rgba(255, 255, 255, 0));
|
||||||
color: var(--darkgray);
|
color: var(--darkgray);
|
||||||
|
@ -202,11 +201,19 @@ a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& .page-header {
|
& .page-header,
|
||||||
|
& .page-footer {
|
||||||
width: $pageWidth;
|
width: $pageWidth;
|
||||||
margin: $topSpacing auto 0 auto;
|
margin-top: 1rem;
|
||||||
|
|
||||||
@media all and (max-width: $fullPageWidth) {
|
@media all and (max-width: $fullPageWidth) {
|
||||||
width: initial;
|
width: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .page-header {
|
||||||
|
margin: $topSpacing auto 0 auto;
|
||||||
|
@media all and (max-width: $fullPageWidth) {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ export interface ColorScheme {
|
||||||
secondary: string
|
secondary: string
|
||||||
tertiary: string
|
tertiary: string
|
||||||
highlight: string
|
highlight: string
|
||||||
|
textHighlight: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Colors {
|
interface Colors {
|
||||||
|
@ -49,6 +50,7 @@ ${stylesheet.join("\n\n")}
|
||||||
--secondary: ${theme.colors.lightMode.secondary};
|
--secondary: ${theme.colors.lightMode.secondary};
|
||||||
--tertiary: ${theme.colors.lightMode.tertiary};
|
--tertiary: ${theme.colors.lightMode.tertiary};
|
||||||
--highlight: ${theme.colors.lightMode.highlight};
|
--highlight: ${theme.colors.lightMode.highlight};
|
||||||
|
--textHighlight: ${theme.colors.lightMode.textHighlight};
|
||||||
|
|
||||||
--headerFont: "${theme.typography.header}", ${DEFAULT_SANS_SERIF};
|
--headerFont: "${theme.typography.header}", ${DEFAULT_SANS_SERIF};
|
||||||
--bodyFont: "${theme.typography.body}", ${DEFAULT_SANS_SERIF};
|
--bodyFont: "${theme.typography.body}", ${DEFAULT_SANS_SERIF};
|
||||||
|
@ -64,6 +66,7 @@ ${stylesheet.join("\n\n")}
|
||||||
--secondary: ${theme.colors.darkMode.secondary};
|
--secondary: ${theme.colors.darkMode.secondary};
|
||||||
--tertiary: ${theme.colors.darkMode.tertiary};
|
--tertiary: ${theme.colors.darkMode.tertiary};
|
||||||
--highlight: ${theme.colors.darkMode.highlight};
|
--highlight: ${theme.colors.darkMode.highlight};
|
||||||
|
--textHighlight: ${theme.colors.darkMode.textHighlight};
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue