mirror of
https://github.com/ChenQihan666/MyBlog-Next.git
synced 2026-08-13 23:31:07 +08:00
feat: add callout support (#655)
* feat: toggle .dark class on theme change * feat: add callouts with rehype-callouts plugin * docs: update blog posts with callouts
This commit is contained in:
@@ -10,6 +10,7 @@ import sitemap from "@astrojs/sitemap";
|
|||||||
import { unified } from "@astrojs/markdown-remark";
|
import { unified } from "@astrojs/markdown-remark";
|
||||||
import remarkToc from "remark-toc";
|
import remarkToc from "remark-toc";
|
||||||
import remarkCollapse from "remark-collapse";
|
import remarkCollapse from "remark-collapse";
|
||||||
|
import rehypeCallouts from "rehype-callouts";
|
||||||
import {
|
import {
|
||||||
transformerNotationDiff,
|
transformerNotationDiff,
|
||||||
transformerNotationHighlight,
|
transformerNotationHighlight,
|
||||||
@@ -40,6 +41,7 @@ export default defineConfig({
|
|||||||
remarkToc,
|
remarkToc,
|
||||||
[remarkCollapse, { test: "Table of contents" }],
|
[remarkCollapse, { test: "Table of contents" }],
|
||||||
],
|
],
|
||||||
|
rehypePlugins: [rehypeCallouts],
|
||||||
}),
|
}),
|
||||||
shikiConfig: {
|
shikiConfig: {
|
||||||
themes: { light: "min-light", dark: "night-owl" },
|
themes: { light: "min-light", dark: "night-owl" },
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"astro": "^6.4.2",
|
"astro": "^6.4.2",
|
||||||
"dayjs": "^1.11.21",
|
"dayjs": "^1.11.21",
|
||||||
"lodash.kebabcase": "^4.1.1",
|
"lodash.kebabcase": "^4.1.1",
|
||||||
|
"rehype-callouts": "^2.1.2",
|
||||||
"remark-collapse": "^0.1.2",
|
"remark-collapse": "^0.1.2",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
"satori": "^0.26.0",
|
"satori": "^0.26.0",
|
||||||
|
|||||||
Generated
+15
@@ -29,6 +29,9 @@ importers:
|
|||||||
lodash.kebabcase:
|
lodash.kebabcase:
|
||||||
specifier: ^4.1.1
|
specifier: ^4.1.1
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
|
rehype-callouts:
|
||||||
|
specifier: ^2.1.2
|
||||||
|
version: 2.1.2
|
||||||
remark-collapse:
|
remark-collapse:
|
||||||
specifier: ^0.1.2
|
specifier: ^0.1.2
|
||||||
version: 0.1.2
|
version: 0.1.2
|
||||||
@@ -2263,6 +2266,10 @@ packages:
|
|||||||
regex@6.1.0:
|
regex@6.1.0:
|
||||||
resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
|
resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
|
||||||
|
|
||||||
|
rehype-callouts@2.1.2:
|
||||||
|
resolution: {integrity: sha512-ZZWZ6EknUHiSzr4pQ88C7db3su4DElfJRmphZJbXpDdwW3urTwlYZpHckoC9pjEvBmUEEiJAM0uuc2uxyLdTfg==}
|
||||||
|
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||||
|
|
||||||
rehype-parse@9.0.1:
|
rehype-parse@9.0.1:
|
||||||
resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==}
|
resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==}
|
||||||
|
|
||||||
@@ -5341,6 +5348,14 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
regex-utilities: 2.3.0
|
regex-utilities: 2.3.0
|
||||||
|
|
||||||
|
rehype-callouts@2.1.2:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
hast-util-from-html: 2.0.3
|
||||||
|
hast-util-is-element: 3.0.0
|
||||||
|
hastscript: 9.0.1
|
||||||
|
unist-util-visit: 5.1.0
|
||||||
|
|
||||||
rehype-parse@9.0.1:
|
rehype-parse@9.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
author: Sat Naing
|
author: Sat Naing
|
||||||
pubDatetime: 2022-09-23T15:22:00Z
|
pubDatetime: 2022-09-23T15:22:00Z
|
||||||
modDatetime: 2026-05-17T04:47:08.212Z
|
modDatetime: 2026-06-03T00:00:00.000Z
|
||||||
title: Adding new posts in AstroPaper theme
|
title: Adding new posts in AstroPaper theme
|
||||||
slug: adding-new-posts-in-astropaper-theme
|
slug: adding-new-posts-in-astropaper-theme
|
||||||
featured: true
|
featured: true
|
||||||
@@ -44,6 +44,7 @@ src/content/posts/docs/_legacy/how-to.md -> mysite.com/posts/docs/how-to
|
|||||||
src/content/posts/Example Dir/Dummy Post.md -> mysite.com/posts/example-dir/dummy-post
|
src/content/posts/Example Dir/Dummy Post.md -> mysite.com/posts/example-dir/dummy-post
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
> Files and directories prefixed with `_` are excluded from routing. Use them for drafts, shared assets, or internal-only content.
|
> Files and directories prefixed with `_` are excluded from routing. Use them for drafts, shared assets, or internal-only content.
|
||||||
|
|
||||||
## Frontmatter
|
## Frontmatter
|
||||||
@@ -71,7 +72,8 @@ Here is the list of frontmatter properties for each post:
|
|||||||
|
|
||||||
</ResponsiveTable>
|
</ResponsiveTable>
|
||||||
|
|
||||||
> Tip! You can get an ISO 8601 datetime by running `new Date().toISOString()` in the console.
|
> [!TIP]
|
||||||
|
> You can get an ISO 8601 datetime by running `new Date().toISOString()` in the console.
|
||||||
|
|
||||||
Only `title`, `description`, and `pubDatetime` fields in frontmatter must be specified.
|
Only `title`, `description`, and `pubDatetime` fields in frontmatter must be specified.
|
||||||
|
|
||||||
@@ -116,6 +118,65 @@ AstroPaper includes workspace snippets to speed up creating new posts:
|
|||||||
|
|
||||||
These snippets live in `.vscode/astro-paper.code-snippets`. If you use VS Code (or Cursor), they should be available automatically when you open the workspace.
|
These snippets live in `.vscode/astro-paper.code-snippets`. If you use VS Code (or Cursor), they should be available automatically when you open the workspace.
|
||||||
|
|
||||||
|
## Callouts
|
||||||
|
|
||||||
|
AstroPaper started supporting callouts in AstroPaper v6.1. They use a simple blockquote syntax powered by `rehype-callouts` (Obsidian theme).
|
||||||
|
|
||||||
|
Here are the most commonly used types:
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Supplementary information the reader should be aware of.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Helpful advice, shortcuts, or best practices.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Something that could go wrong or have unintended consequences.
|
||||||
|
|
||||||
|
> [!DANGER]
|
||||||
|
> Serious risk of failure, data loss, or incorrect behavior.
|
||||||
|
|
||||||
|
> [!INFO]
|
||||||
|
> Neutral informational context — less urgent than a note.
|
||||||
|
|
||||||
|
> [!SUCCESS]
|
||||||
|
> Confirmation that something worked or is correct.
|
||||||
|
|
||||||
|
The full list of supported types includes: `NOTE`, `ABSTRACT`, `INFO`, `TODO`, `TIP`, `SUCCESS`, `QUESTION`, `WARNING`, `FAILURE`, `DANGER`, `BUG`, `EXAMPLE`, `QUOTE` — each with its own icon and color. Many types also accept aliases (e.g. `HINT` and `IMPORTANT` for `TIP`, `CAUTION` for `WARNING`). See the [rehype-callouts docs](https://github.com/lin-stephanie/rehype-callouts) for the complete reference.
|
||||||
|
|
||||||
|
### Collapsible callouts
|
||||||
|
|
||||||
|
Add `-` after the type to make the callout collapsed by default, or `+` to make it expanded but collapsible:
|
||||||
|
|
||||||
|
> [!WARNING]- Read before proceeding
|
||||||
|
> This content is hidden until the reader expands it. Useful for long caveats that would otherwise interrupt the flow.
|
||||||
|
|
||||||
|
> [!TIP]+ Pro tip (expanded by default)
|
||||||
|
> This starts open but can be collapsed. Great for optional detail you still want visible on first load.
|
||||||
|
|
||||||
|
### Custom titles
|
||||||
|
|
||||||
|
Replace the default type label with any title you like by adding text after the type:
|
||||||
|
|
||||||
|
> [!NOTE] Did you know?
|
||||||
|
> The text after the type becomes the callout's heading. Leave it out and the type name is used automatically.
|
||||||
|
|
||||||
|
### Syntax summary
|
||||||
|
|
||||||
|
```md
|
||||||
|
> [!NOTE]
|
||||||
|
> Supplementary information.
|
||||||
|
|
||||||
|
> [!WARNING]- Collapsed by default
|
||||||
|
> Hidden until expanded.
|
||||||
|
|
||||||
|
> [!TIP]+ Expanded, but collapsible
|
||||||
|
> Starts open.
|
||||||
|
|
||||||
|
> [!DANGER] Custom title
|
||||||
|
> Replaces the default heading.
|
||||||
|
```
|
||||||
|
|
||||||
## Adding table of contents
|
## Adding table of contents
|
||||||
|
|
||||||
By default, a post does not include any table of contents (TOC). To include one, write `Table of contents` as an h2 heading (`##` in Markdown) and place it where you want it to appear:
|
By default, a post does not include any table of contents (TOC). To include one, write `Table of contents` as an h2 heading (`##` in Markdown) and place it where you want it to appear:
|
||||||
@@ -181,7 +242,8 @@ export default defineConfig({
|
|||||||
|
|
||||||
Here are two methods for storing images and using them inside a markdown file.
|
Here are two methods for storing images and using them inside a markdown file.
|
||||||
|
|
||||||
> Note: If you need to style optimized images in markdown, you should [use MDX](https://docs.astro.build/en/guides/images/#images-in-mdx-files).
|
> [!IMPORTANT]
|
||||||
|
> If you need to style optimized images in markdown, you should [use MDX](https://docs.astro.build/en/guides/images/#images-in-mdx-files).
|
||||||
|
|
||||||
### Inside `src/assets/` directory (recommended)
|
### Inside `src/assets/` directory (recommended)
|
||||||
|
|
||||||
@@ -203,6 +265,7 @@ Example: suppose you want to display `example.jpg` whose path is `src/assets/ima
|
|||||||
<!-- ^^ This is wrong -->
|
<!-- ^^ This is wrong -->
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
> Technically, you can store images inside any directory under `src`. `src/assets` is just a recommendation.
|
> Technically, you can store images inside any directory under `src`. `src/assets` is just a recommendation.
|
||||||
|
|
||||||
### Inside `public/` directory
|
### Inside `public/` directory
|
||||||
@@ -225,7 +288,8 @@ Example: assume `example.jpg` is located at `public/assets/images/example.jpg`.
|
|||||||
|
|
||||||
### Image compression
|
### Image compression
|
||||||
|
|
||||||
When putting images in a blog post (especially those in the `public/` directory), it is recommended to compress them. This will affect the overall performance of the website.
|
> [!WARNING]
|
||||||
|
> When putting images in a blog post (especially those in the `public/` directory), compress them first. Unoptimized images significantly hurt page performance.
|
||||||
|
|
||||||
Recommended image compression sites:
|
Recommended image compression sites:
|
||||||
|
|
||||||
@@ -236,4 +300,5 @@ Recommended image compression sites:
|
|||||||
|
|
||||||
The default OG image will be used if a post does not specify one. Though not required, an OG image relevant to the post should be specified in the frontmatter. The recommended size for OG images is **_1200 X 640_** px.
|
The default OG image will be used if a post does not specify one. Though not required, an OG image relevant to the post should be specified in the frontmatter. The recommended size for OG images is **_1200 X 640_** px.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
> Since AstroPaper v1.4.0, OG images are generated automatically if not specified. Check out [the announcement](https://astro-paper.pages.dev/posts/dynamic-og-image-generation-in-astropaper-blog-posts/).
|
> Since AstroPaper v1.4.0, OG images are generated automatically if not specified. Check out [the announcement](https://astro-paper.pages.dev/posts/dynamic-og-image-generation-in-astropaper-blog-posts/).
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
author: Sat Naing
|
author: Sat Naing
|
||||||
pubDatetime: 2022-12-28T04:59:04.866Z
|
pubDatetime: 2022-12-28T04:59:04.866Z
|
||||||
modDatetime: 2026-05-04T00:00:00Z
|
modDatetime: 2026-06-03T00:00:00.000Z
|
||||||
title: Dynamic OG image generation in AstroPaper blog posts
|
title: Dynamic OG image generation in AstroPaper blog posts
|
||||||
slug: dynamic-og-image-generation-in-astropaper-blog-posts
|
slug: dynamic-og-image-generation-in-astropaper-blog-posts
|
||||||
featured: false
|
featured: false
|
||||||
@@ -49,9 +49,8 @@ Dynamic OG images include _the blog post title_, _author name_, and _site title_
|
|||||||
|
|
||||||
### Issue with Non-Latin Characters
|
### Issue with Non-Latin Characters
|
||||||
|
|
||||||
Titles with non-latin characters won't display properly out of the box. In AstroPaper v6, dynamic OG images load font files from Astro's **Fonts** configuration (`astro.config.ts`) and register them with Satori.
|
> [!CAUTION]
|
||||||
|
> Titles with non-latin characters won't display properly out of the box. Switch the Google font family to one that covers your writing system, and include **both** `400` and `700` weights — Satori uses separate buffers for regular and bold, so missing either causes mismatched rendering.
|
||||||
To fix missing glyphs, switch the Google font family to one that covers your writing system, and make sure you include **both** `400` and `700` weights (Satori uses separate buffers for regular + bold).
|
|
||||||
|
|
||||||
```ts file="astro.config.ts"
|
```ts file="astro.config.ts"
|
||||||
import { defineConfig, fontProviders } from "astro/config";
|
import { defineConfig, fontProviders } from "astro/config";
|
||||||
@@ -79,15 +78,8 @@ If you change `cssVariable`, also update the matching key in:
|
|||||||
|
|
||||||
> Check out [this PR](https://github.com/satnaing/astro-paper/pull/318) for more info.
|
> Check out [this PR](https://github.com/satnaing/astro-paper/pull/318) for more info.
|
||||||
|
|
||||||
## Trade-off
|
> [!WARNING] Caveats
|
||||||
|
>
|
||||||
While this is a nice feature to have, there's still a trade-off: AstroPaper generates one PNG per eligible post at build time (when og image is not specified in the frontmatter), so total build time grows with content volume.
|
> - **Build time** grows with content volume — one PNG per eligible post is generated at build time. Generation is faster in v6 (PR [#632](https://github.com/satnaing/astro-paper/pull/632)), but on very large sites you can disable it with `features.dynamicOgImage: false` in `astro-paper.config.ts`.
|
||||||
|
> - **RTL languages** are not supported yet.
|
||||||
In AstroPaper v6, OG image generation is significantly faster (PR [#632](https://github.com/satnaing/astro-paper/pull/632)) than earlier implementations, so the per-image overhead is much lower in practice. If you still want to minimize build time on very large sites, you can disable it by setting `features.dynamicOgImage: false` in `astro-paper.config.ts` (and provide per-post `ogImage` files instead).
|
> - **Emoji** in titles can be tricky — some may not render correctly.
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
At the time of writing this, [Satori](https://github.com/vercel/satori) is fairly new and has not reached major release yet. So, there are still some limitations to this dynamic OG image feature.
|
|
||||||
|
|
||||||
- RTL languages are not supported yet.
|
|
||||||
- [Using emoji](https://github.com/vercel/satori#emojis) in the title might be a little bit tricky.
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
author: Sat Naing
|
author: Sat Naing
|
||||||
pubDatetime: 2022-09-23T04:58:53Z
|
pubDatetime: 2022-09-23T04:58:53Z
|
||||||
modDatetime: 2026-05-17T05:50:08.212Z
|
modDatetime: 2026-06-03T00:00:00.000Z
|
||||||
title: How to configure AstroPaper theme
|
title: How to configure AstroPaper theme
|
||||||
slug: how-to-configure-astropaper-theme
|
slug: how-to-configure-astropaper-theme
|
||||||
featured: true
|
featured: true
|
||||||
@@ -296,7 +296,8 @@ import { Font } from "astro:assets";
|
|||||||
|
|
||||||
The `--font-app` variable is used throughout the theme via the `font-app` Tailwind utility class, so updating this single variable applies your custom font everywhere.
|
The `--font-app` variable is used throughout the theme via the `font-app` Tailwind utility class, so updating this single variable applies your custom font everywhere.
|
||||||
|
|
||||||
> **Note**: Make sure the font name matches exactly as it appears on [Google Fonts](https://fonts.google.com). For other font providers or local fonts, refer to the [Astro Fonts documentation](https://docs.astro.build/en/guides/fonts/).
|
> [!WARNING]
|
||||||
|
> Make sure the font name matches exactly as it appears on [Google Fonts](https://fonts.google.com). For other font providers or local fonts, refer to the [Astro Fonts documentation](https://docs.astro.build/en/guides/fonts/).
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ const rssHref = getRelativeLocaleUrl(
|
|||||||
"(prefers-color-scheme: dark)"
|
"(prefers-color-scheme: dark)"
|
||||||
).matches;
|
).matches;
|
||||||
const theme = stored ?? (prefersDark ? "dark" : "light");
|
const theme = stored ?? (prefersDark ? "dark" : "light");
|
||||||
document.firstElementChild?.setAttribute("data-theme", theme);
|
const root = document.firstElementChild;
|
||||||
|
root?.setAttribute("data-theme", theme);
|
||||||
|
root?.classList.toggle("dark", theme === "dark");
|
||||||
// Expose value so theme.ts can skip re-detection.
|
// Expose value so theme.ts can skip re-detection.
|
||||||
window.__theme = { value: theme };
|
window.__theme = { value: theme };
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ function persist(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reflect(): void {
|
function reflect(): void {
|
||||||
document.firstElementChild?.setAttribute("data-theme", themeValue);
|
const root = document.firstElementChild;
|
||||||
|
root?.setAttribute("data-theme", themeValue);
|
||||||
|
root?.classList.toggle("dark", themeValue === DARK);
|
||||||
document.querySelector("#theme-btn")?.setAttribute("aria-label", themeValue);
|
document.querySelector("#theme-btn")?.setAttribute("aria-label", themeValue);
|
||||||
|
|
||||||
// Fill <meta name="theme-color"> with the computed background colour so
|
// Fill <meta name="theme-color"> with the computed background colour so
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@import "./theme.css";
|
@import "./theme.css";
|
||||||
@import "./typography.css";
|
@import "./typography.css";
|
||||||
|
@import "rehype-callouts/theme/obsidian";
|
||||||
|
|
||||||
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
@apply border-s-accent/80 wrap-break-word opacity-80;
|
@apply border-s-accent/80 wrap-break-word opacity-80;
|
||||||
}
|
}
|
||||||
|
|
||||||
details {
|
details:not(.callout) {
|
||||||
@apply text-foreground inline-block cursor-pointer select-none [&_p]:hidden [&_ul]:my-0!;
|
@apply text-foreground inline-block cursor-pointer select-none [&_p]:hidden [&_ul]:my-0!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user