Skip to content

Commit d6ea041

Browse files
committed
Fix Markdown action routing and timing
Make the docs Markdown action follow VitePress route changes, avoid DOM work before mount, and handle index-style page paths correctly. This keeps the action pointed at the current page and prevents stale UI state after copy failures. fedify-dev#715 (comment) fedify-dev#715 (comment) fedify-dev#715 (comment) Assisted-by: Codex:gpt-5.4
1 parent c922f39 commit d6ea041

1 file changed

Lines changed: 44 additions & 27 deletions

File tree

docs/.vitepress/theme/components/PageMarkdownActions.vue

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
<script setup lang="ts">
22
import { useRoute } from "vitepress";
33
import { computed, nextTick, onMounted, ref, watch } from "vue";
4-
import { Teleport } from "vue";
54
65
const copied = ref(false);
76
const copyFailed = ref(false);
8-
const path = ref<string | null>(null);
97
const targetReady = ref(false);
108
const isDev = import.meta.env.DEV;
119
const devMessage =
1210
"Markdown actions are not available in the VitePress dev server. Please use the built docs instead.";
1311
const route = useRoute();
14-
15-
onMounted(() => {
16-
const { pathname } = window.location;
17-
path.value = pathname === "/"
18-
? "/index.md"
19-
: `${pathname.replace(/\/+$/, "").replace(/\.html$/, "")}.md`;
12+
let copiedResetTimeout: number | null = null;
13+
let copyFailedResetTimeout: number | null = null;
14+
15+
const markdownPath = computed(() => {
16+
let path = route.path.replace(/\.html$/, "");
17+
if (path === "/") return "/index.md";
18+
if (path.endsWith("/")) return `${path}index.md`;
19+
return `${path.replace(/\/+$/, "")}.md`;
2020
});
2121
2222
function ensureTarget(): void {
@@ -43,22 +43,34 @@ function ensureTarget(): void {
4343
targetReady.value = true;
4444
}
4545
46-
watch(
47-
() => route.path,
48-
async () => {
49-
targetReady.value = false;
50-
await nextTick();
51-
ensureTarget();
52-
},
53-
{ immediate: true },
54-
);
46+
async function updateTarget(): Promise<void> {
47+
targetReady.value = false;
48+
await nextTick();
49+
ensureTarget();
50+
}
51+
52+
onMounted(() => {
53+
void updateTarget();
54+
watch(() => route.path, updateTarget);
55+
});
56+
57+
function resetCopiedState(delay: number): void {
58+
if (copiedResetTimeout != null) window.clearTimeout(copiedResetTimeout);
59+
copiedResetTimeout = window.setTimeout(() => {
60+
copied.value = false;
61+
copiedResetTimeout = null;
62+
}, delay);
63+
}
5564
56-
const markdownPath = computed(() => path.value);
65+
function resetCopyFailedState(delay: number): void {
66+
if (copyFailedResetTimeout != null) window.clearTimeout(copyFailedResetTimeout);
67+
copyFailedResetTimeout = window.setTimeout(() => {
68+
copyFailed.value = false;
69+
copyFailedResetTimeout = null;
70+
}, delay);
71+
}
5772
5873
async function getMarkdown(): Promise<string> {
59-
if (markdownPath.value == null) {
60-
throw new Error("Markdown path is not available yet.");
61-
}
6274
const response = await fetch(markdownPath.value);
6375
if (!response.ok) {
6476
throw new Error(`Failed to load ${markdownPath.value}: ${response.status}`);
@@ -76,14 +88,19 @@ async function copyMarkdown(): Promise<void> {
7688
await navigator.clipboard.writeText(text);
7789
copied.value = true;
7890
copyFailed.value = false;
79-
window.setTimeout(() => {
80-
copied.value = false;
81-
}, 2000);
91+
if (copyFailedResetTimeout != null) {
92+
window.clearTimeout(copyFailedResetTimeout);
93+
copyFailedResetTimeout = null;
94+
}
95+
resetCopiedState(2000);
8296
} catch {
97+
copied.value = false;
8398
copyFailed.value = true;
84-
window.setTimeout(() => {
85-
copyFailed.value = false;
86-
}, 2500);
99+
if (copiedResetTimeout != null) {
100+
window.clearTimeout(copiedResetTimeout);
101+
copiedResetTimeout = null;
102+
}
103+
resetCopyFailedState(2500);
87104
}
88105
}
89106

0 commit comments

Comments
 (0)