mirror of
https://github.com/alrayyes/wiki.git
synced 2024-11-21 19:16:23 +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,
|
||||
pageBody: Content(),
|
||||
}
|
||||
const { head, header, beforeBody, pageBody, left, right, footer } = layout
|
||||
const { head, header, beforeBody, pageBody, afterBody, left, right, footer } = layout
|
||||
return {
|
||||
name: "ContentPage",
|
||||
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[]> {
|
||||
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
|
||||
- `tertiary`: hover states and visited [[graph view|graph]] nodes
|
||||
- `highlight`: internal link background, highlighted text, [[syntax highlighting|highlighted lines of code]]
|
||||
- `textHighlight`: markdown highlighted text background
|
||||
|
||||
## Plugins
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ As with folder listings, you can also provide a description and title for a tag
|
|||
|
||||
## 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
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
- breadcrumbs component
|
||||
- static dead link detection
|
||||
- cursor chat extension
|
||||
- https://giscus.app/ extension
|
||||
- sidenotes? https://github.com/capnfabs/paperesque
|
||||
- direct match in search using double quotes
|
||||
- https://help.obsidian.md/Advanced+topics/Using+Obsidian+URI
|
||||
- audio/video embed styling
|
||||
- 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
|
||||
beforeBody: QuartzComponent[] // laid out vertically
|
||||
pageBody: QuartzComponent // single component
|
||||
afterBody: QuartzComponent[] // laid out vertically
|
||||
left: QuartzComponent[] // vertical on desktop, horizontal on mobile
|
||||
right: QuartzComponent[] // vertical on desktop, horizontal on mobile
|
||||
footer: QuartzComponent // single component
|
||||
|
|
|
@ -11,10 +11,12 @@ Example: [[advanced/|Advanced]]
|
|||
> [!note]
|
||||
> 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`).
|
||||
|
||||
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
|
||||
|
||||
- Category: Emitter
|
||||
|
|
|
@ -9,10 +9,12 @@ This plugin emits dedicated pages for each tag used in the content. See [[folder
|
|||
> [!note]
|
||||
> 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`).
|
||||
|
||||
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
|
||||
|
||||
- Category: Emitter
|
||||
|
|
|
@ -34,6 +34,7 @@ const config: QuartzConfig = {
|
|||
secondary: "#284b63",
|
||||
tertiary: "#84a59d",
|
||||
highlight: "rgba(143, 159, 169, 0.15)",
|
||||
textHighlight: "#fff23688",
|
||||
},
|
||||
darkMode: {
|
||||
light: "#161618",
|
||||
|
@ -44,6 +45,7 @@ const config: QuartzConfig = {
|
|||
secondary: "#7b97aa",
|
||||
tertiary: "#84a59d",
|
||||
highlight: "rgba(143, 159, 169, 0.15)",
|
||||
textHighlight: "#b3aa0288",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@ import * as Component from "./quartz/components"
|
|||
export const sharedPageComponents: SharedLayout = {
|
||||
head: Component.Head(),
|
||||
header: [],
|
||||
afterBody: [],
|
||||
footer: Component.Footer({
|
||||
links: {
|
||||
"Ryan's Namepage": "https://ryankes.eu",
|
||||
|
|
|
@ -77,10 +77,11 @@ export interface FullPageLayout {
|
|||
header: QuartzComponent[]
|
||||
beforeBody: QuartzComponent[]
|
||||
pageBody: QuartzComponent
|
||||
afterBody: QuartzComponent[]
|
||||
left: QuartzComponent[]
|
||||
right: QuartzComponent[]
|
||||
footer: QuartzComponent
|
||||
}
|
||||
|
||||
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 ?? []
|
||||
return (
|
||||
<footer class={`${displayClass ?? ""}`}>
|
||||
<hr />
|
||||
<p>
|
||||
{i18n(cfg.locale).components.footer.createdWith}{" "}
|
||||
<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 { GlobalConfiguration } from "../cfg"
|
||||
|
||||
export function byDateAndAlphabetical(
|
||||
cfg: GlobalConfiguration,
|
||||
): (f1: QuartzPluginData, f2: QuartzPluginData) => number {
|
||||
export type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number
|
||||
|
||||
export function byDateAndAlphabetical(cfg: GlobalConfiguration): SortFn {
|
||||
return (f1, f2) => {
|
||||
if (f1.dates && f2.dates) {
|
||||
// sort descending
|
||||
|
@ -27,10 +27,12 @@ export function byDateAndAlphabetical(
|
|||
|
||||
type Props = {
|
||||
limit?: number
|
||||
sort?: SortFn
|
||||
} & QuartzComponentProps
|
||||
|
||||
export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit }: Props) => {
|
||||
let list = allFiles.sort(byDateAndAlphabetical(cfg))
|
||||
export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit, sort }: Props) => {
|
||||
const sorter = sort ?? byDateAndAlphabetical(cfg)
|
||||
let list = allFiles.sort(sorter)
|
||||
if (limit) {
|
||||
list = list.slice(0, limit)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } fro
|
|||
import path from "path"
|
||||
|
||||
import style from "../styles/listPage.scss"
|
||||
import { PageList } from "../PageList"
|
||||
import { PageList, SortFn } from "../PageList"
|
||||
import { stripSlashes, simplifySlug } from "../../util/path"
|
||||
import { Root } from "hast"
|
||||
import { htmlToJsx } from "../../util/jsx"
|
||||
|
@ -13,6 +13,7 @@ interface FolderContentOptions {
|
|||
* Whether to display number of folders
|
||||
*/
|
||||
showFolderCount: boolean
|
||||
sort?: SortFn
|
||||
}
|
||||
|
||||
const defaultOptions: FolderContentOptions = {
|
||||
|
@ -37,6 +38,7 @@ export default ((opts?: Partial<FolderContentOptions>) => {
|
|||
const classes = ["popover-hint", ...cssClasses].join(" ")
|
||||
const listProps = {
|
||||
...props,
|
||||
sort: options.sort,
|
||||
allFiles: allPagesInFolder,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types"
|
||||
import style from "../styles/listPage.scss"
|
||||
import { PageList } from "../PageList"
|
||||
import { PageList, SortFn } from "../PageList"
|
||||
import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path"
|
||||
import { QuartzPluginData } from "../../plugins/vfile"
|
||||
import { Root } from "hast"
|
||||
import { htmlToJsx } from "../../util/jsx"
|
||||
import { i18n } from "../../i18n"
|
||||
|
||||
const numPages = 10
|
||||
const TagContent: QuartzComponent = (props: QuartzComponentProps) => {
|
||||
interface TagContentOptions {
|
||||
sort?: SortFn
|
||||
numPages: number
|
||||
}
|
||||
|
||||
const defaultOptions: TagContentOptions = {
|
||||
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
|
||||
|
||||
|
@ -71,16 +82,18 @@ const TagContent: QuartzComponent = (props: QuartzComponentProps) => {
|
|||
<div class="page-listing">
|
||||
<p>
|
||||
{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}
|
||||
{pages.length > numPages && (
|
||||
{pages.length > options.numPages && (
|
||||
<>
|
||||
{" "}
|
||||
<span>
|
||||
{i18n(cfg.locale).pages.tagContent.showingFirst({ count: numPages })}
|
||||
{i18n(cfg.locale).pages.tagContent.showingFirst({
|
||||
count: options.numPages,
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
<PageList limit={numPages} {...listProps} />
|
||||
<PageList limit={options.numPages} {...listProps} sort={opts?.sort} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -107,7 +120,8 @@ const TagContent: QuartzComponent = (props: QuartzComponentProps) => {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TagContent.css = style + PageList.css
|
||||
export default (() => TagContent) satisfies QuartzComponentConstructor
|
||||
TagContent.css = style + PageList.css
|
||||
return TagContent
|
||||
}) satisfies QuartzComponentConstructor
|
||||
|
|
|
@ -14,6 +14,7 @@ interface RenderComponents {
|
|||
header: QuartzComponent[]
|
||||
beforeBody: QuartzComponent[]
|
||||
pageBody: QuartzComponent
|
||||
afterBody: QuartzComponent[]
|
||||
left: QuartzComponent[]
|
||||
right: QuartzComponent[]
|
||||
footer: QuartzComponent
|
||||
|
@ -187,6 +188,7 @@ export function renderPage(
|
|||
header,
|
||||
beforeBody,
|
||||
pageBody: Content,
|
||||
afterBody,
|
||||
left,
|
||||
right,
|
||||
footer: Footer,
|
||||
|
@ -232,6 +234,12 @@ export function renderPage(
|
|||
</div>
|
||||
</div>
|
||||
<Content {...componentData} />
|
||||
<hr />
|
||||
<div class="page-footer">
|
||||
{afterBody.map((BodyComponent) => (
|
||||
<BodyComponent {...componentData} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{RightComponent}
|
||||
</Body>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { normalizeRelativeURLs } from "../../util/path"
|
|||
|
||||
const p = new DOMParser()
|
||||
async function mouseEnterHandler(
|
||||
this: HTMLLinkElement,
|
||||
this: HTMLAnchorElement,
|
||||
{ clientX, clientY }: { clientX: number; clientY: number },
|
||||
) {
|
||||
const link = this
|
||||
|
@ -33,7 +33,7 @@ async function mouseEnterHandler(
|
|||
thisUrl.hash = ""
|
||||
thisUrl.search = ""
|
||||
const targetUrl = new URL(link.href)
|
||||
const hash = targetUrl.hash
|
||||
const hash = decodeURIComponent(targetUrl.hash)
|
||||
targetUrl.hash = ""
|
||||
targetUrl.search = ""
|
||||
|
||||
|
@ -100,7 +100,7 @@ async function mouseEnterHandler(
|
|||
}
|
||||
|
||||
document.addEventListener("nav", () => {
|
||||
const links = [...document.getElementsByClassName("internal")] as HTMLLinkElement[]
|
||||
const links = [...document.getElementsByClassName("internal")] as HTMLAnchorElement[]
|
||||
for (const link of links) {
|
||||
link.addEventListener("mouseenter", mouseEnterHandler)
|
||||
window.addCleanup(() => link.removeEventListener("mouseenter", mouseEnterHandler))
|
||||
|
|
|
@ -59,14 +59,25 @@ export const ContentPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOp
|
|||
...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 Body = BodyConstructor()
|
||||
|
||||
return {
|
||||
name: "ContentPage",
|
||||
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) {
|
||||
const graph = new DepGraph<FilePath>()
|
||||
|
|
|
@ -3,7 +3,7 @@ import { QuartzComponentProps } from "../../components/types"
|
|||
import HeaderConstructor from "../../components/Header"
|
||||
import BodyConstructor from "../../components/Body"
|
||||
import { pageResources, renderPage } from "../../components/renderPage"
|
||||
import { ProcessedContent, defaultProcessedContent } from "../vfile"
|
||||
import { ProcessedContent, QuartzPluginData, defaultProcessedContent } from "../vfile"
|
||||
import { FullPageLayout } from "../../cfg"
|
||||
import path from "path"
|
||||
import {
|
||||
|
@ -21,22 +21,37 @@ import { write } from "./helpers"
|
|||
import { i18n } from "../../i18n"
|
||||
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 = {
|
||||
...sharedPageComponents,
|
||||
...defaultListPageLayout,
|
||||
pageBody: FolderContent(),
|
||||
pageBody: FolderContent({ sort: userOpts?.sort }),
|
||||
...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 Body = BodyConstructor()
|
||||
|
||||
return {
|
||||
name: "FolderPage",
|
||||
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) {
|
||||
// Example graph:
|
||||
|
|
|
@ -3,7 +3,7 @@ import { QuartzComponentProps } from "../../components/types"
|
|||
import HeaderConstructor from "../../components/Header"
|
||||
import BodyConstructor from "../../components/Body"
|
||||
import { pageResources, renderPage } from "../../components/renderPage"
|
||||
import { ProcessedContent, defaultProcessedContent } from "../vfile"
|
||||
import { ProcessedContent, QuartzPluginData, defaultProcessedContent } from "../vfile"
|
||||
import { FullPageLayout } from "../../cfg"
|
||||
import {
|
||||
FilePath,
|
||||
|
@ -18,22 +18,37 @@ import { write } from "./helpers"
|
|||
import { i18n } from "../../i18n"
|
||||
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 = {
|
||||
...sharedPageComponents,
|
||||
...defaultListPageLayout,
|
||||
pageBody: TagContent(),
|
||||
pageBody: TagContent({ sort: userOpts?.sort }),
|
||||
...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 Body = BodyConstructor()
|
||||
|
||||
return {
|
||||
name: "TagPage",
|
||||
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) {
|
||||
const graph = new DepGraph<FilePath>()
|
||||
|
|
|
@ -2,7 +2,6 @@ import { QuartzTransformerPlugin } from "../types"
|
|||
import { Root, Html, BlockContent, DefinitionContent, Paragraph, Code } from "mdast"
|
||||
import { Element, Literal, Root as HtmlRoot } from "hast"
|
||||
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
|
||||
import { slug as slugAnchor } from "github-slugger"
|
||||
import rehypeRaw from "rehype-raw"
|
||||
import { SKIP, visit } from "unist-util-visit"
|
||||
import path from "path"
|
||||
|
@ -98,7 +97,7 @@ function canonicalizeCallout(calloutName: string): keyof typeof calloutMapping {
|
|||
|
||||
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
|
||||
// \[\[ -> 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)
|
||||
// (\\?\|[^\[\]\#]+)? -> optional escape \ then | then one or more non-special characters (alias)
|
||||
export const wikilinkRegex = new RegExp(
|
||||
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]/,
|
||||
"g",
|
||||
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]/g,
|
||||
)
|
||||
|
||||
// ^\|([^\n])+\|\n(\|) -> matches the header row
|
||||
// ( ?:?-{3,}:? ?\|)+ -> matches the header row separator
|
||||
// (\|([^\n])+\|\n)+ -> matches the body rows
|
||||
export const tableRegex = new RegExp(
|
||||
/^\|([^\n])+\|\n(\|)( ?:?-{3,}:? ?\|)+\n(\|([^\n])+\|\n?)+/,
|
||||
"gm",
|
||||
)
|
||||
export const tableRegex = new RegExp(/^\|([^\n])+\|\n(\|)( ?:?-{3,}:? ?\|)+\n(\|([^\n])+\|\n?)+/gm)
|
||||
|
||||
// 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 commentRegex = new RegExp(/%%[\s\S]*?%%/, "g")
|
||||
const highlightRegex = new RegExp(/==([^=]+)==/g)
|
||||
const commentRegex = new RegExp(/%%[\s\S]*?%%/g)
|
||||
// from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
|
||||
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
|
||||
// #(...) -> 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, matches an arbitrary number of tag strings separated by "/"
|
||||
const tagRegex = new RegExp(
|
||||
/(?:^| )#((?:[-_\p{L}\p{Emoji}\p{M}\d])+(?:\/[-_\p{L}\p{Emoji}\p{M}\d]+)*)/,
|
||||
"gu",
|
||||
/(?:^| )#((?:[-_\p{L}\p{Emoji}\p{M}\d])+(?:\/[-_\p{L}\p{Emoji}\p{M}\d]+)*)/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 ytPlaylistLinkRegex = /[?&]list=([^#?&]*)/
|
||||
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
|
||||
src = src.replace(tableRegex, (value) => {
|
||||
// escape all aliases and headers in wikilinks inside a table
|
||||
return value.replace(tableWikilinkRegex, (value, ...capture) => {
|
||||
const [raw]: (string | undefined)[] = capture
|
||||
return value.replace(tableWikilinkRegex, (_value, raw) => {
|
||||
// const [raw]: (string | undefined)[] = capture
|
||||
let escaped = raw ?? ""
|
||||
escaped = escaped.replace("#", "\\#")
|
||||
// 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 [fp, anchor] = splitAnchor(`${rawFp ?? ""}${rawHeader ?? ""}`)
|
||||
const blockRef = Boolean(anchor?.startsWith("^")) ? "^" : ""
|
||||
const blockRef = Boolean(rawHeader?.match(/^#?\^/)) ? "^" : ""
|
||||
const displayAnchor = anchor ? `#${blockRef}${anchor.trim().replace(/^#+/, "")}` : ""
|
||||
const displayAlias = rawAlias ?? rawHeader?.replace("#", "|") ?? ""
|
||||
const embedDisplay = value.startsWith("!") ? "!" : ""
|
||||
|
@ -276,7 +270,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
|
|||
return {
|
||||
type: "html",
|
||||
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
|
||||
}" class="transclude-inner">Transclude of ${url}${block}</a></blockquote>`,
|
||||
}
|
||||
|
|
|
@ -20,11 +20,10 @@ section {
|
|||
}
|
||||
|
||||
.text-highlight {
|
||||
background-color: #fff23688;
|
||||
background-color: var(--textHighlight);
|
||||
padding: 0 0.1rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: color-mix(in srgb, var(--tertiary) 60%, rgba(255, 255, 255, 0));
|
||||
color: var(--darkgray);
|
||||
|
@ -202,11 +201,19 @@ a {
|
|||
}
|
||||
}
|
||||
|
||||
& .page-header {
|
||||
& .page-header,
|
||||
& .page-footer {
|
||||
width: $pageWidth;
|
||||
margin: $topSpacing auto 0 auto;
|
||||
margin-top: 1rem;
|
||||
|
||||
@media all and (max-width: $fullPageWidth) {
|
||||
width: initial;
|
||||
}
|
||||
}
|
||||
|
||||
& .page-header {
|
||||
margin: $topSpacing auto 0 auto;
|
||||
@media all and (max-width: $fullPageWidth) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ export interface ColorScheme {
|
|||
secondary: string
|
||||
tertiary: string
|
||||
highlight: string
|
||||
textHighlight: string
|
||||
}
|
||||
|
||||
interface Colors {
|
||||
|
@ -49,6 +50,7 @@ ${stylesheet.join("\n\n")}
|
|||
--secondary: ${theme.colors.lightMode.secondary};
|
||||
--tertiary: ${theme.colors.lightMode.tertiary};
|
||||
--highlight: ${theme.colors.lightMode.highlight};
|
||||
--textHighlight: ${theme.colors.lightMode.textHighlight};
|
||||
|
||||
--headerFont: "${theme.typography.header}", ${DEFAULT_SANS_SERIF};
|
||||
--bodyFont: "${theme.typography.body}", ${DEFAULT_SANS_SERIF};
|
||||
|
@ -64,6 +66,7 @@ ${stylesheet.join("\n\n")}
|
|||
--secondary: ${theme.colors.darkMode.secondary};
|
||||
--tertiary: ${theme.colors.darkMode.tertiary};
|
||||
--highlight: ${theme.colors.darkMode.highlight};
|
||||
--textHighlight: ${theme.colors.darkMode.textHighlight};
|
||||
}
|
||||
`
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue