Skip to content

Commit

Permalink
Refactor remark plugins (#270)
Browse files Browse the repository at this point in the history
* Remove dateLink remark plugin

* Add date icon to NoteFavicon component

* Rename noteLink to wikilink

* Rename tagLink to tag

* Rename noteEmbed to embed

* Update tests
  • Loading branch information
colebemis committed Feb 25, 2024
1 parent 87ef4a8 commit 4c71617
Show file tree
Hide file tree
Showing 15 changed files with 244 additions and 602 deletions.
34 changes: 19 additions & 15 deletions docs/markdown-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Lumen supports [GitHub Flavored Markdown](https://github.github.com/gfm/) with the following syntax extensions:

## Note links
## Wikilinks

Link to another note using its ID.

Expand All @@ -14,39 +14,43 @@ Link to another note using its ID.
| :-------------------------------- | :------------------------------------------ |
| `[[1652342106359\|Randie Bemis]]` | `<a href="/1652342106359">Randie Bemis</a>` |

## Note embeds
### Dates

Embed the contents of another note using its ID.
You can also use wikilink syntax to reference a date.

```
![[<note-id>]]
[[YYYY-MM-DD]]
```

| Example | Rendered HTML |
| :------------------- | :----------------------------- |
| `![[1652342106359]]` | Contents of note 1652342106359 |
| Example | Rendered HTML |
| :--------------- | :-------------------------------------------- |
| `[[2021-07-11]]` | `<a href="/2021-07-11">Sun, Jul 11, 2021</a>` |

## Date links
> [!TIP]
> Lumen uses [Chrono](https://github.com/wanasit/chrono) to convert natural language dates into ISO format (YYYY-MM-DD). Try typing `[[yesterday]]` or `[[next monday]]` in a note editor to see it in action.
Link to all other notes that reference the same date.
## Embeds

Embed the contents of another note using its ID.

```
[[YYYY-MM-DD]]
![[<note-id>]]
```

| Example | Rendered HTML |
| :--------------- | :-------------------------------------------- |
| `[[2021-07-11]]` | `<a href="/2021-07-11">Sun, Jul 11, 2021</a>` |
| Example | Rendered HTML |
| :------------------- | :----------------------------- |
| `![[1652342106359]]` | Contents of note 1652342106359 |

## Tag links
## Tags

Link to all other notes with the same tag.

```
#<tag-name>
```

> **Note**: Tag names must start with a letter and can contain letters, numbers, hyphens, underscores, and forward slashes.
> [!NOTE]
> Tag names must start with a letter and can contain letters, numbers, hyphens, underscores, and forward slashes.
| Example | Rendered HTML |
| :-------- | :----------------------------------- |
Expand Down
28 changes: 10 additions & 18 deletions scripts/benchmark.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import Benchmark from "benchmark"
import { fromMarkdown } from "mdast-util-from-markdown"
import { dateLink, dateLinkFromMarkdown } from "../src/remark-plugins/date-link"
import { noteLink, noteLinkFromMarkdown } from "../src/remark-plugins/note-link"
import { tagLink, tagLinkFromMarkdown } from "../src/remark-plugins/tag-link"
import { wikilink, wikilinkFromMarkdown } from "../src/remark-plugins/wikilink"
import { tag, tagFromMarkdown } from "../src/remark-plugins/tag"

const markdown = `
# Heading 1
Expand Down Expand Up @@ -51,31 +50,24 @@ suite.add("Without syntax extensions", () => {
fromMarkdown(markdown)
})

suite.add("With tag link syntax", () => {
suite.add("With tag syntax", () => {
fromMarkdown(markdown, {
extensions: [tagLink()],
mdastExtensions: [tagLinkFromMarkdown()],
extensions: [tag()],
mdastExtensions: [tagFromMarkdown()],
})
})

suite.add("With note link syntax", () => {
suite.add("With wikilink syntax", () => {
fromMarkdown(markdown, {
extensions: [noteLink()],
mdastExtensions: [noteLinkFromMarkdown()],
})
})

suite.add("With date link syntax", () => {
fromMarkdown(markdown, {
extensions: [dateLink()],
mdastExtensions: [dateLinkFromMarkdown()],
extensions: [wikilink()],
mdastExtensions: [wikilinkFromMarkdown()],
})
})

suite.add("With all syntax extensions", () => {
fromMarkdown(markdown, {
extensions: [noteLink(), tagLink(), dateLink()],
mdastExtensions: [noteLinkFromMarkdown(), tagLinkFromMarkdown(), dateLinkFromMarkdown()],
extensions: [wikilink(), tag()],
mdastExtensions: [wikilinkFromMarkdown(), tagFromMarkdown()],
})
})

Expand Down
50 changes: 23 additions & 27 deletions src/components/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import qs from "qs"
import React from "react"
import ReactMarkdown from "react-markdown"
import { CodeProps, LiProps, Position } from "react-markdown/lib/ast-to-react"
// import remarkEmoji from "remark-emoji"
import { useNetworkState } from "react-use"
import rehypeKatex from "rehype-katex"
import remarkGfm from "remark-gfm"
Expand All @@ -14,17 +13,17 @@ import { z } from "zod"
import { UPLOADS_DIR } from "../hooks/attach-file"
import { useNoteById } from "../hooks/note"
import { useSearchNotes } from "../hooks/search"
import { remarkDateLink } from "../remark-plugins/date-link"
import { remarkNoteEmbed } from "../remark-plugins/note-embed"
import { remarkNoteLink } from "../remark-plugins/note-link"
import { remarkTagLink } from "../remark-plugins/tag-link"
import { remarkEmbed } from "../remark-plugins/embed"
import { remarkWikilink } from "../remark-plugins/wikilink"
import { remarkTag } from "../remark-plugins/tag"
import { templateSchema } from "../schema"
import { cx } from "../utils/cx"
import {
MONTH_NAMES,
formatDate,
formatDateDistance,
getNextBirthday,
isValidDateString,
toDateString,
toDateStringUtc,
} from "../utils/date"
Expand Down Expand Up @@ -162,10 +161,9 @@ function MarkdownContent({ children, className }: { children: string; className?
remarkPlugins={[
remarkGfm,
// remarkEmoji,
remarkNoteLink,
remarkNoteEmbed,
remarkTagLink,
remarkDateLink,
remarkWikilink,
remarkEmbed,
remarkTag,
remarkMath,
]}
rehypePlugins={[rehypeKatex]}
Expand All @@ -177,28 +175,23 @@ function MarkdownContent({ children, className }: { children: string; className?
output: "mathml",
})
},
noteLink(h, node) {
return h(node, "noteLink", {
wikilink(h, node) {
return h(node, "wikilink", {
id: node.data.id,
text: node.data.text,
})
},
noteEmbed(h, node) {
return h(node, "noteEmbed", {
embed(h, node) {
return h(node, "embed", {
id: node.data.id,
text: node.data.text,
})
},
tagLink(h, node) {
return h(node, "tagLink", {
tag(h, node) {
return h(node, "tag", {
name: node.data.name,
})
},
dateLink(h, node) {
return h(node, "dateLink", {
date: node.data.date,
})
},
},
}}
components={{
Expand All @@ -210,13 +203,11 @@ function MarkdownContent({ children, className }: { children: string; className?
pre: ({ children }) => <>{children}</>,
code: Code,
// @ts-ignore I don't know how to extend the list of accepted component keys
noteLink: NoteLink,
// @ts-ignore
noteEmbed: NoteEmbed,
wikilink: NoteLink,
// @ts-ignore
tagLink: TagLink,
embed: NoteEmbed,
// @ts-ignore
dateLink: DateLink,
tag: TagLink,
}}
>
{children}
Expand Down Expand Up @@ -682,6 +673,10 @@ function NoteLink({ id, text }: NoteLinkProps) {
}
}, [])

if (isValidDateString(id)) {
return <DateLink date={id} text={text} />
}

return (
<HoverCard.Root>
<HoverCard.Trigger asChild>
Expand Down Expand Up @@ -745,15 +740,16 @@ function NoteEmbed({ id }: NoteEmbedProps) {

type DateLinkProps = {
date: string
text?: string
className?: string
}

function DateLink({ date, className }: DateLinkProps) {
function DateLink({ date, text, className }: DateLinkProps) {
return (
<HoverCard.Root>
<HoverCard.Trigger asChild>
<Link className={className} to={`/${date}`} target="_blank">
{formatDate(date)}
{text || formatDate(date)}
</Link>
</HoverCard.Trigger>
<HoverCard.Portal>
Expand Down
2 changes: 1 addition & 1 deletion src/components/note-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ function pasteExtension({
}

function dateCompletion(context: CompletionContext): CompletionResult | null {
const word = context.matchBefore(/(\[\[[^\]|^|]*|\w*)/)
const word = context.matchBefore(/\[\[[^\]|^|]*/)

if (!word) {
return null
Expand Down
8 changes: 7 additions & 1 deletion src/components/note-favicon.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useNetworkState } from "react-use"
import { Note, templateSchema } from "../schema"
import { cx } from "../utils/cx"
import { isValidDateString } from "../utils/date"
import { GitHubAvatar } from "./github-avatar"
import { NoteIcon16, NoteTemplateIcon16 } from "./icons"
import { CalendarIcon16, NoteIcon16, NoteTemplateIcon16 } from "./icons"
import { WebsiteFavicon } from "./website-favicon"

type NoteFaviconProps = React.ComponentPropsWithoutRef<"span"> & {
Expand All @@ -20,6 +21,11 @@ export function NoteFavicon({

let icon = defaultFavicon

// Date
if (isValidDateString(note.id)) {
icon = <CalendarIcon16 date={new Date(note.id).getUTCDate()} />
}

// GitHub
if (typeof note.frontmatter.github === "string" && online) {
icon = <GitHubAvatar data-testid="favicon-github" login={note.frontmatter.github} size={16} />
Expand Down
81 changes: 0 additions & 81 deletions src/remark-plugins/date-link.test.ts

This file was deleted.

Loading

0 comments on commit 4c71617

Please sign in to comment.