-
Notifications
You must be signed in to change notification settings - Fork 922
feat(client): add onContentUpdated composition API #1620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a2f17b1
36a2670
ee7a5ca
14f8b46
7289707
784a1fc
8c366e1
236ca98
7aef173
c443341
86c0bad
7361efb
da8b238
41bcccc
a3bcfcc
77bcd14
c3e88f8
23d2c6e
577b990
16a93f5
0701e37
a91367a
2d7315c
cd02733
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<script lang="ts" setup> | ||
import { ref, watch } from 'vue' | ||
import { onContentUpdated, useRoutePath } from 'vuepress/client' | ||
|
||
const mounted = ref('') | ||
const beforeUnmount = ref('') | ||
|
||
const mountedCount = ref(0) | ||
const updatedCount = ref(0) | ||
|
||
const routePath = useRoutePath() | ||
|
||
watch(routePath, () => { | ||
updatedCount.value = 0 | ||
}) | ||
|
||
onContentUpdated((reason) => { | ||
switch (reason) { | ||
case 'mounted': | ||
mounted.value = routePath.value | ||
mountedCount.value++ | ||
break | ||
case 'updated': | ||
updatedCount.value++ | ||
break | ||
case 'beforeUnmount': | ||
beforeUnmount.value = routePath.value | ||
break | ||
default: | ||
} | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div class="markdown-content-hooks"> | ||
<h3>markdown content hooks</h3> | ||
<p class="markdown-content-mounted"> | ||
mounted: {{ mounted }} {{ mountedCount }} | ||
</p> | ||
<p class="markdown-content-beforeUnmount"> | ||
beforeUnmount: {{ beforeUnmount }} | ||
</p> | ||
<p class="markdown-content-updated">updatedCount: {{ updatedCount }}</p> | ||
</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## title | ||
|
||
content |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { expect, test } from '@playwright/test' | ||
Check failure on line 1 in e2e/tests/composables/on-content-updated.spec.ts
|
||
import { BUNDLER, IS_DEV } from '../../utils/env' | ||
import { readSourceMarkdown, writeSourceMarkdown } from '../../utils/source' | ||
|
||
const updateMarkdownContent = async (): Promise<void> => { | ||
const content = await readSourceMarkdown('composables/on-content-updated.md') | ||
await writeSourceMarkdown( | ||
'composables/on-content-updated.md', | ||
`${content}\n\nUpdated content`, | ||
) | ||
} | ||
|
||
const restoreMarkdownContent = async (): Promise<void> => { | ||
await writeSourceMarkdown( | ||
'composables/on-content-updated.md', | ||
'## title\n\ncontent\n', | ||
) | ||
} | ||
|
||
test.afterAll(async () => { | ||
await restoreMarkdownContent() | ||
}) | ||
|
||
test('should call content hook on mounted', async ({ page }) => { | ||
await page.goto('composables/on-content-updated.html') | ||
const mountedLocator = page.locator( | ||
'.markdown-content-hooks .markdown-content-mounted', | ||
) | ||
await expect(mountedLocator).toHaveText( | ||
'mounted: /composables/on-content-updated.html 1', | ||
) | ||
|
||
// update content but mounted hook should not be called twice | ||
await updateMarkdownContent() | ||
await expect(mountedLocator).toHaveText( | ||
'mounted: /composables/on-content-updated.html 1', | ||
) | ||
}) | ||
|
||
test('should call content hook on beforeUnmount', async ({ page }) => { | ||
await page.goto('composables/on-content-updated.html') | ||
|
||
const beforeUnmountLocator = page.locator( | ||
'.markdown-content-hooks .markdown-content-beforeUnmount', | ||
) | ||
|
||
await page.locator('.e2e-theme-nav ul > li > a').nth(0).click() | ||
Check failure on line 47 in e2e/tests/composables/on-content-updated.spec.ts
|
||
|
||
await expect(beforeUnmountLocator).toHaveText('beforeUnmount: /') | ||
}) | ||
|
||
/** | ||
* Updated hooks are only supported for use in development environments. | ||
* In CI environments, under both Linux and Windows, using Vite fails to correctly trigger hooks. | ||
*/ | ||
if (IS_DEV && BUNDLER !== 'vite') { | ||
test('should call content hook on updated', async ({ page }) => { | ||
await page.goto('composables/on-content-updated.html') | ||
const updatedLocator = page.locator( | ||
'.markdown-content-hooks .markdown-content-updated', | ||
) | ||
|
||
await updateMarkdownContent() | ||
await expect(updatedLocator).toHaveText(`updatedCount: 1`) | ||
|
||
await updateMarkdownContent() | ||
await expect(updatedLocator).toHaveText(`updatedCount: 2`) | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './clientData.js' | ||
export * from './clientDataUtils.js' | ||
export * from './onContentUpdated.js' | ||
export * from './updateHead.js' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { onUnmounted } from 'vue' | ||
import { contentUpdatedCallbacks } from '../internal/contentUpdatedCallbacks' | ||
import type { ContentUpdatedCallback } from '../types/index.js' | ||
|
||
/** | ||
* Register callback that is called every time the markdown content is updated | ||
* in the DOM. | ||
*/ | ||
export const onContentUpdated = (fn: ContentUpdatedCallback): void => { | ||
contentUpdatedCallbacks.value.push(fn) | ||
onUnmounted(() => { | ||
contentUpdatedCallbacks.value = contentUpdatedCallbacks.value.filter( | ||
(f) => f !== fn, | ||
) | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import type { Ref } from 'vue' | ||
import { shallowRef } from 'vue' | ||
import type { ContentUpdatedCallback } from '../types/index.js' | ||
|
||
/** | ||
* Global content updated callbacks ref | ||
*/ | ||
export const contentUpdatedCallbacks: Ref<ContentUpdatedCallback[]> = | ||
shallowRef([]) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export type * from './clientConfig.js' | ||
export type * from './clientData.js' | ||
export type * from './onContentUpdated.js' | ||
export type * from './createVueAppFunction.js' | ||
export type * from './routes.js' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export type ContentUpdatedReason = 'beforeUnmount' | 'mounted' | 'updated' | ||
|
||
export type ContentUpdatedCallback = (reason: ContentUpdatedReason) => unknown |
Uh oh!
There was an error while loading. Please reload this page.