diff --git a/CHANGES.md b/CHANGES.md
index f44810d85..8f4655411 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -202,6 +202,13 @@ To be released.
### Docs
+ - Added a per-page Markdown action to the docs site so readers can open or
+ copy the LLM-friendly Markdown for the current page without guessing the
+ generated `*.md` path or starting from *llms.txt*. The action is now
+ available directly from each documentation page while *llms.txt* and
+ *llms-full.txt* continue to exclude high-noise pages such as the changelog,
+ contribution guide, *README.md*, and sponsors page. [[#706], [#715]]
+
- Added [*Building a federated blog* tutorial] showing how to layer
ActivityPub federation onto an [Astro] + [Bun] blog: actor setup,
follower management, SQLite persistence, sending `Create`/`Update`/
@@ -226,6 +233,8 @@ To be released.
[#691]: https://github.com/fedify-dev/fedify/issues/691
[#695]: https://github.com/fedify-dev/fedify/pull/695
[#704]: https://github.com/fedify-dev/fedify/issues/704
+[#706]: https://github.com/fedify-dev/fedify/issues/706
+[#715]: https://github.com/fedify-dev/fedify/pull/715
Version 2.1.10
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 6f3f2d2f2..5d3a1b089 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -311,14 +311,20 @@ export default withMermaid(defineConfig({
plugins: [
groupIconVitePlugin(),
llmstxt({
- ignoreFiles: [
- "changelog.md",
- "contribute.md",
- "README.md",
- "security.md",
- "sponsors.md",
- "tutorial.md",
- ],
+ ignoreFilesPerOutput: {
+ llmsTxt: [
+ "changelog.md",
+ "contribute.md",
+ "README.md",
+ "sponsors.md",
+ ],
+ llmsFullTxt: [
+ "changelog.md",
+ "contribute.md",
+ "README.md",
+ "sponsors.md",
+ ],
+ },
}),
],
},
diff --git a/docs/.vitepress/theme/components/PageMarkdownActions.vue b/docs/.vitepress/theme/components/PageMarkdownActions.vue
new file mode 100644
index 000000000..5fc903aaa
--- /dev/null
+++ b/docs/.vitepress/theme/components/PageMarkdownActions.vue
@@ -0,0 +1,330 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
index 5e7ae909f..97c17ba1a 100644
--- a/docs/.vitepress/theme/index.ts
+++ b/docs/.vitepress/theme/index.ts
@@ -1,6 +1,8 @@
import TwoslashFloatingVue from "@shikijs/vitepress-twoslash/client";
import "virtual:group-icons.css";
import type { EnhanceAppContext } from "vitepress";
+import { h } from "vue";
+import PageMarkdownActions from "./components/PageMarkdownActions.vue";
import Theme from "vitepress/theme";
import "@shikijs/vitepress-twoslash/style.css";
@@ -8,7 +10,13 @@ import "./style.css";
export default {
extends: Theme,
+ Layout() {
+ return h(Theme.Layout, null, {
+ "doc-before": () => h(PageMarkdownActions),
+ });
+ },
enhanceApp({ app }: EnhanceAppContext) {
app.use(TwoslashFloatingVue);
+ app.component("PageMarkdownActions", PageMarkdownActions);
},
};
diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css
index 1545b1348..0365402d4 100644
--- a/docs/.vitepress/theme/style.css
+++ b/docs/.vitepress/theme/style.css
@@ -34,3 +34,35 @@ main dl dd {
margin-top: .25rem;
margin-bottom: 1rem;
}
+
+@media (min-width: 960px) {
+ .VPDoc .content-container .page-title-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 1rem;
+ }
+
+ .VPDoc .content-container .page-title-row > h1 {
+ flex: 1 1 auto;
+ min-width: 0;
+ margin: 0;
+ }
+
+ .VPDoc .content-container .page-title-actions-target {
+ flex: none;
+ margin-top: -.8rem;
+ }
+}
+
+@media (max-width: 959px) {
+ .VPDoc .content-container .page-title-row {
+ display: flex;
+ flex-direction: column;
+ gap: .75rem;
+ }
+
+ .VPDoc .content-container .page-title-actions-target {
+ align-self: flex-end;
+ }
+}