diff --git a/docs/.vuepress/configs/navbar/en.ts b/docs/.vuepress/configs/navbar/en.ts index 245a503c5e..8f45b0bc03 100644 --- a/docs/.vuepress/configs/navbar/en.ts +++ b/docs/.vuepress/configs/navbar/en.ts @@ -31,6 +31,7 @@ export const navbarEn: NavbarConfig = [ '/plugins/photo-swipe', '/plugins/redirect', '/plugins/register-components', + '/plugins/watermark', ], }, { diff --git a/docs/.vuepress/configs/navbar/zh.ts b/docs/.vuepress/configs/navbar/zh.ts index ebe3482770..38798500e3 100644 --- a/docs/.vuepress/configs/navbar/zh.ts +++ b/docs/.vuepress/configs/navbar/zh.ts @@ -31,6 +31,7 @@ export const navbarZh: NavbarConfig = [ '/zh/plugins/photo-swipe', '/zh/plugins/redirect', '/zh/plugins/register-components', + '/zh/plugins/watermark', ], }, { diff --git a/docs/.vuepress/configs/sidebar/en.ts b/docs/.vuepress/configs/sidebar/en.ts index 44e58f7b75..d082a4fd45 100644 --- a/docs/.vuepress/configs/sidebar/en.ts +++ b/docs/.vuepress/configs/sidebar/en.ts @@ -16,6 +16,7 @@ export const sidebarEn: SidebarConfig = { '/plugins/photo-swipe', '/plugins/redirect', '/plugins/register-components', + '/plugins/watermark', ], }, { diff --git a/docs/.vuepress/configs/sidebar/zh.ts b/docs/.vuepress/configs/sidebar/zh.ts index 7df99c8007..b1e5298345 100644 --- a/docs/.vuepress/configs/sidebar/zh.ts +++ b/docs/.vuepress/configs/sidebar/zh.ts @@ -16,6 +16,7 @@ export const sidebarZh: SidebarConfig = { '/zh/plugins/photo-swipe', '/zh/plugins/redirect', '/zh/plugins/register-components', + '/zh/plugins/watermark', ], }, { diff --git a/docs/plugins/watermark.md b/docs/plugins/watermark.md new file mode 100644 index 0000000000..5e2f7a83b8 --- /dev/null +++ b/docs/plugins/watermark.md @@ -0,0 +1,133 @@ +# watermark + + + +Integrate [watermark-js-plus](https://github.com/zhensherlock/watermark-js-plus) into VuePress。 + +This plugin can add watermark to the pages, you can choose between add watermark globally or on specific pages. You can also choose between add text watermark or image watermark. + +## Usage + +```sh +npm i -D @vuepress/plugin-watermark@next +``` + +```ts +import { watermarkPlugin } from '@vuepress/plugin-watermark' + +export default { + plugins: [ + watermarkPlugin({ + // options + }), + ], +} +``` + +## Options + +### enabled + +- Type: `boolean | ((page: Page) => boolean)` + +- Default: `false` + +- Details: + + Specify which pages need to have watermarks added. + + Pages with `true` value will have watermarks added. + +### watermarkOptions + +- Type: `WatermarkOptions` + +- Default: `undefined` + +- Details: Please refer to the [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) configuration options. + +#### watermarkOptions.parent + +- Type: `string` + +- Default: `body` + +- Details: Parent element selector for adding watermark. + + By default, it is inserted into the body, but you can specify inserting it into a specific element on the page. + +### delay + +- Type: `number` + +- Default: `500` + +- Details: Delay for adding watermarks. In milliseconds. + + This delay will only take effect when adding watermarks to a specific element on the page. + + A delay is required when the watermark parent is rerendered when switching pages. + +## Frontmatter + +### watermark + +- Type: `boolean | WatermarkOptions` + +- Details: + + When the type is `boolean`, it indicates whether the watermark is enabled. + + When the type is `WatermarkOptions`, it represents the current page's watermark configuration. + + You can refer to [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/). + +```md +--- +watermark: + width: 200 + height: 200 + content: Your content + opacity: 0.5 +--- +``` + +## Client Config + +### defineWatermarkConfig(config) + +- Type: `(config: MaybeRefOrGetter) => void` + +Additional configuration passed to [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/en/config/). + +```ts +import { defineWatermarkConfig } from '@vuepress/plugin-watermark/client' + +defineWatermarkConfig({ + // Set up additional watermark configurations here. +}) +``` + +In most cases, the majority of options should be defined in Node, +but there are some special situations. For example, +it may be necessary to control different watermark opacities, font colors, +etc., in **dark/light mode** , or to pass in callbacks such as `onSuccess`, `extraDrawFunc`, and so on. + +```ts +import { computed } from 'vue' + +export default defineClientConfig({ + setup() { + const isDark = useDarkMode() + + const watermarkConfig = computed(() => ({ + fontColor: isDark.value ? '#fff' : '#000', + onSuccess: () => { + console.log('success') + }, + })) + + defineWatermarkConfig(watermarkConfig) + }, +}) +``` diff --git a/docs/zh/plugins/watermark.md b/docs/zh/plugins/watermark.md new file mode 100644 index 0000000000..25ca0cbf46 --- /dev/null +++ b/docs/zh/plugins/watermark.md @@ -0,0 +1,132 @@ +# watermark + + + +将 [watermark-js-plus](https://github.com/zhensherlock/watermark-js-plus) 到 VuePress 中。 + +此插件可在在页面中添加水印,可以选择为 全局页面 或 部分页面添加水印,还可以选择添加 文字水印 或 图片水印。 + +## 使用 + +```sh +npm i -D @vuepress/plugin-watermark@next +``` + +```ts +import { watermarkPlugin } from '@vuepress/plugin-watermark' + +export default { + plugins: [ + watermarkPlugin({ + // options + }), + ], +} +``` + +## 配置项 + +### enabled + +- 类型: `boolean | ((page: Page) => boolean)` + +- 默认值: `false` + +- 详情: + + 指定哪些页面需要添加水印。 + + 拥有 `true` 值的页面将会被添加水印。 + +### watermarkOptions + +- 类型: `WatermarkOptions` + +- 默认值: `undefined` + +- 详情: 配置项请参考 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/)。 + +#### watermarkOptions.parent + +- 类型: `string` + +- 默认值: `body` + +- 详情:添加水印的父元素选择器。 + + 默认插入到 body 中,可以指定插入到页面的某个元素中。 + +### delay + +- 类型: `number` + +- 默认值: `500` + +- 详情:添加水印的延时。以毫秒为单位。 + + 该延迟仅会在添加水印到页面某个元素时生效。 + + 如果水印的父元素在切换页面时被重新渲染,那么需要延迟一段时间才能重新添加水印。 + +## Frontmatter + +### watermark + +- 类型: `boolean | WatermarkOptions` + +- 详情: + + 当类型为 `boolean` 时,表示是否启用水印。 + + 当类型为 `WatermarkOptions` 时,表示当前页面水印配置。 + + 可以参考 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) 。 + +```md +--- +watermark: + width: 200 + height: 200 + content: Your content + opacity: 0.5 +--- +``` + +## 客户端配置 + +### defineWatermarkConfig(config) + +- 类型: `(config: MaybeRefOrGetter) => void` + +传递给 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) 的额外配置。 + +```ts +import { defineWatermarkConfig } from '@vuepress/plugin-watermark/client' + +defineWatermarkConfig({ + // 在此设置额外的 watermark 配置 +}) +``` + +通常来说,大部分选项应该在 Node 中定义,但存在一些特殊情况。 +比如需要在 **深色/浅色 模式** 下控制不同的 水印 透明度、字体颜色等, +或者需要传入如 `onSuccess`、`extraDrawFunc` 等回调函数。 + +```ts +import { computed } from 'vue' + +export default defineClientConfig({ + setup() { + const isDark = useDarkMode() + + const watermarkConfig = computed(() => ({ + fontColor: isDark.value ? '#fff' : '#000', + onSuccess: () => { + console.log('success') + }, + })) + + defineWatermarkConfig(watermarkConfig) + }, +}) +``` diff --git a/e2e/docs/.vuepress/config.ts b/e2e/docs/.vuepress/config.ts index 9087029387..1722521936 100644 --- a/e2e/docs/.vuepress/config.ts +++ b/e2e/docs/.vuepress/config.ts @@ -7,6 +7,7 @@ import { copyrightPlugin } from '@vuepress/plugin-copyright' import { feedPlugin } from '@vuepress/plugin-feed' import { pwaPlugin } from '@vuepress/plugin-pwa' import { redirectPlugin } from '@vuepress/plugin-redirect' +import { watermarkPlugin } from '@vuepress/plugin-watermark' import { defaultTheme } from '@vuepress/theme-default' import { defineUserConfig } from 'vuepress/cli' import type { UserConfig } from 'vuepress/cli' @@ -223,5 +224,14 @@ export default defineUserConfig({ '/redirect/config/': '/redirect/final.html', }, }), + watermarkPlugin({ + enable: (page) => page.path.startsWith('/watermark/'), + + watermarkOptions: { + content: 'VuePress Watermark', + width: 200, + height: 200, + }, + }), ], }) as UserConfig diff --git a/e2e/docs/watermark/README.md b/e2e/docs/watermark/README.md new file mode 100644 index 0000000000..ca436db062 --- /dev/null +++ b/e2e/docs/watermark/README.md @@ -0,0 +1,5 @@ +--- +watermark: true +--- + +# Default Watermark diff --git a/e2e/docs/watermark/disabled.md b/e2e/docs/watermark/disabled.md new file mode 100644 index 0000000000..b51ef8bac0 --- /dev/null +++ b/e2e/docs/watermark/disabled.md @@ -0,0 +1,5 @@ +--- +watermark: false +--- + +# disabled watermark diff --git a/e2e/package.json b/e2e/package.json index 176a451821..e71464c34d 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -23,6 +23,7 @@ "@vuepress/plugin-feed": "workspace:*", "@vuepress/plugin-pwa": "workspace:*", "@vuepress/plugin-redirect": "workspace:*", + "@vuepress/plugin-watermark": "workspace:*", "@vuepress/theme-default": "workspace:*", "sass": "^1.75.0", "sass-loader": "^14.2.1", diff --git a/e2e/tests/plugin-watermark/watermark.spec.ts b/e2e/tests/plugin-watermark/watermark.spec.ts new file mode 100644 index 0000000000..4aa45563b5 --- /dev/null +++ b/e2e/tests/plugin-watermark/watermark.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from '@playwright/test' + +test.describe('plugin-watermark', () => { + test('enabled watermark', async ({ page }) => { + await page.goto('watermark/') + + expect( + await page.locator('//html/body/div[2]').getAttribute('style'), + ).toContain('z-index: 2147483647 !important;') + + expect( + await page.locator('//html/body/div[2]/div').getAttribute('style'), + ).toContain('background-image: url("data:image/png;base64,') + }) + + test('disabled watermark', async ({ page }) => { + await page.goto('watermark/disabled.html') + + await expect(page.locator('//html/body/div[2]')).not.toBeVisible() + }) +}) diff --git a/plugins/plugin-watermark/CHANGELOG.md b/plugins/plugin-watermark/CHANGELOG.md new file mode 100644 index 0000000000..e4d87c4d45 --- /dev/null +++ b/plugins/plugin-watermark/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/plugins/plugin-watermark/package.json b/plugins/plugin-watermark/package.json new file mode 100644 index 0000000000..a2ec5ce928 --- /dev/null +++ b/plugins/plugin-watermark/package.json @@ -0,0 +1,48 @@ +{ + "name": "@vuepress/plugin-watermark", + "version": "2.0.0-rc.26", + "description": "VuePress plugin - watermark", + "keywords": [ + "vuepress-plugin", + "vuepress", + "plugin", + "watermark" + ], + "homepage": "https://ecosystem.vuejs.press/plugins/watermark.html", + "bugs": { + "url": "https://github.com/vuepress/ecosystem/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vuepress/ecosystem.git", + "directory": "plugins/plugin-watermark" + }, + "license": "MIT", + "author": "pengzhanbo", + "type": "module", + "exports": { + ".": "./lib/node/index.js", + "./client": "./lib/client/index.js", + "./package.json": "./package.json" + }, + "main": "./lib/node/index.js", + "types": "./lib/node/index.d.ts", + "files": [ + "lib" + ], + "scripts": { + "build": "tsc -b tsconfig.build.json", + "clean": "rimraf --glob ./lib ./*.tsbuildinfo" + }, + "dependencies": { + "@vuepress/helper": "workspace:*", + "vue": "^3.4.26", + "watermark-js-plus": "^1.4.22" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.9" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/plugins/plugin-watermark/src/client/composables/index.ts b/plugins/plugin-watermark/src/client/composables/index.ts new file mode 100644 index 0000000000..98d99d05f5 --- /dev/null +++ b/plugins/plugin-watermark/src/client/composables/index.ts @@ -0,0 +1 @@ +export * from './setupWatermark.js' diff --git a/plugins/plugin-watermark/src/client/composables/setupWatermark.ts b/plugins/plugin-watermark/src/client/composables/setupWatermark.ts new file mode 100644 index 0000000000..b14a8f40df --- /dev/null +++ b/plugins/plugin-watermark/src/client/composables/setupWatermark.ts @@ -0,0 +1,79 @@ +import { wait } from '@vuepress/helper/client' +import { + getCurrentInstance, + isRef, + nextTick, + onMounted, + toValue, + watch, +} from 'vue' +import type { MaybeRef, Ref } from 'vue' +import { withBase } from 'vuepress/client' +import { Watermark } from 'watermark-js-plus' +import type { WatermarkOptions } from '../helper/index.js' + +export const setupWatermark = ( + options: MaybeRef, + enabled: Ref, + delay = 500, +): void => { + const isInsideApp = (target?: string | Element): boolean => { + const el = + typeof target === 'string' ? document.querySelector(target) : target + + return Boolean( + el && + (getCurrentInstance()?.appContext.app._container as Element).contains?.( + el, + ), + ) + } + + onMounted(() => { + const watermark = new Watermark() + + const updateWaterMark = ( + // shadow clone options object so that we can modify later + { ...options }: WatermarkOptions, + ): void => { + // Blind mode default alpha is 0.005 + if (options.mode === 'blind' && !options.globalAlpha) { + options.globalAlpha = 0.005 + } + + if (options.image?.startsWith('/')) { + options.image = withBase(options.image) + } + + if (toValue(enabled)) + nextTick(() => watermark.changeOptions(options, 'overwrite')) + else watermark.changeOptions(options, 'overwrite', false) + } + + if (isRef(options)) + watch( + () => options, + () => { + updateWaterMark(options.value) + }, + { immediate: true }, + ) + else updateWaterMark(options) + + watch(enabled, () => + nextTick(() => { + if (enabled.value) { + if (isInsideApp(toValue(options).parent)) { + wait(delay).then(() => { + watermark.create() + }) + } else { + watermark.create() + } + } else { + watermark.destroy() + } + }), + ) + }) +} diff --git a/plugins/plugin-watermark/src/client/config.ts b/plugins/plugin-watermark/src/client/config.ts new file mode 100644 index 0000000000..5482516235 --- /dev/null +++ b/plugins/plugin-watermark/src/client/config.ts @@ -0,0 +1,32 @@ +import { computed } from 'vue' +import { defineClientConfig, usePageFrontmatter } from 'vuepress/client' +import type { ClientConfig } from 'vuepress/client' +import type { WatermarkPluginFrontmatter } from '../shared/options.js' +import { setupWatermark } from './composables/index.js' +import { injectWatermarkConfig, useWatermarkOptions } from './helper/index.js' +import type { WatermarkOptions } from './helper/index.js' + +declare const __WM_DELAY__: number +declare const __WM_GLOBAL__: boolean +declare const __WM_OPTIONS__: WatermarkOptions + +export default defineClientConfig({ + enhance({ app }) { + injectWatermarkConfig(app) + }, + + setup() { + if (__VUEPRESS_SSR__) return + + const frontmatter = usePageFrontmatter() + const watermarkOptions = useWatermarkOptions(__WM_OPTIONS__) + + const enabled = computed(() => { + const watermark = frontmatter.value.watermark + + return Boolean(watermark ?? __WM_GLOBAL__ ?? false) + }) + + setupWatermark(watermarkOptions, enabled, __WM_DELAY__) + }, +}) as ClientConfig diff --git a/plugins/plugin-watermark/src/client/helper/index.ts b/plugins/plugin-watermark/src/client/helper/index.ts new file mode 100644 index 0000000000..69d2f191f9 --- /dev/null +++ b/plugins/plugin-watermark/src/client/helper/index.ts @@ -0,0 +1 @@ +export * from './watermark.js' diff --git a/plugins/plugin-watermark/src/client/helper/watermark.ts b/plugins/plugin-watermark/src/client/helper/watermark.ts new file mode 100644 index 0000000000..ba5dc3a2f5 --- /dev/null +++ b/plugins/plugin-watermark/src/client/helper/watermark.ts @@ -0,0 +1,95 @@ +import { isFunction, isPlainObject } from '@vuepress/helper/client' +import { computed, inject, isRef, ref, toValue, watch } from 'vue' +import type { + App, + ComputedRef, + InjectionKey, + MaybeRef, + MaybeRefOrGetter, + Ref, +} from 'vue' +import { usePageFrontmatter } from 'vuepress/client' +import type { WatermarkOptions as WatermarkRawOptions } from 'watermark-js-plus/dist/types/src/types/index.js' +import type { WatermarkPluginFrontmatter } from '../../shared/index.js' + +export type WatermarkOptions = Partial + +const watermarkSymbol: InjectionKey> = Symbol( + __VUEPRESS_DEV__ ? 'watermark' : '', +) + +const watermarkOptions = ref({}) + +/** + * Define additional watermark configurations in the client-side. + * + * In most cases, the majority of options should be defined in Node, + * but there are some special situations. For example, + * it may be necessary to control different watermark opacities, font colors, + * etc., in dark/light mode, or to pass in callbacks such as `onSuccess`, `extraDrawFunc`, and so on. + * + * 在客户端中定义额外的水印配置。 + * + * 通常来说,大部分选项应该在 Node 中定义,但存在一些特殊情况。 + * 比如需要在 深色/浅色 模式下控制不同的 水印 透明度、字体颜色等, + * 或者需要传入如 `onSuccess`、`extraDrawFunc` 等回调函数。 + * + * @example + * ```ts + * import { computed } from 'vue' + * + * const isDark = useDarkMode() + * + * const watermarkConfig = computed(() => ({ + * fontColor: isDark.value ? '#fff' : '#000', + * onSuccess: () => { + * console.log('success') + * }, + * })) + * + * defineWatermarkConfig(watermarkConfig) + * ``` + * + * @param userConfig Watermark options + * + */ +export const defineWatermarkConfig = ( + userConfig: MaybeRefOrGetter, +): void => { + if (isRef(userConfig)) { + watch( + userConfig, + (value) => { + watermarkOptions.value = value + }, + { immediate: true }, + ) + } else if (isFunction(userConfig)) { + watch(userConfig, (value) => { + watermarkOptions.value = value + }) + } else { + watermarkOptions.value = userConfig + } +} + +export const useWatermarkOptions = ( + options: MaybeRef, +): ComputedRef => { + const globalOptions = inject(watermarkSymbol)! + const frontmatter = usePageFrontmatter() + + return computed(() => { + const { watermark } = frontmatter.value + + return { + ...toValue(options), + ...globalOptions.value, + ...(isPlainObject(watermark) ? watermark : {}), + } + }) +} + +export const injectWatermarkConfig = (app: App): void => { + app.provide(watermarkSymbol, watermarkOptions) +} diff --git a/plugins/plugin-watermark/src/client/index.ts b/plugins/plugin-watermark/src/client/index.ts new file mode 100644 index 0000000000..cd566e1947 --- /dev/null +++ b/plugins/plugin-watermark/src/client/index.ts @@ -0,0 +1,3 @@ +export * from './composables/index.js' +export * from './helper/index.js' +export * from '../shared/index.js' diff --git a/plugins/plugin-watermark/src/node/index.ts b/plugins/plugin-watermark/src/node/index.ts new file mode 100644 index 0000000000..5ace105e6c --- /dev/null +++ b/plugins/plugin-watermark/src/node/index.ts @@ -0,0 +1,3 @@ +export * from './options.js' +export * from './watermarkPlugin.js' +export * from '../shared/index.js' diff --git a/plugins/plugin-watermark/src/node/logger.ts b/plugins/plugin-watermark/src/node/logger.ts new file mode 100644 index 0000000000..3cf328d7f7 --- /dev/null +++ b/plugins/plugin-watermark/src/node/logger.ts @@ -0,0 +1,5 @@ +import { Logger } from '@vuepress/helper' + +export const PLUGIN_NAME = '@vuepress/plugin-watermark' + +export const logger = new Logger(PLUGIN_NAME) diff --git a/plugins/plugin-watermark/src/node/options.ts b/plugins/plugin-watermark/src/node/options.ts new file mode 100644 index 0000000000..5809e2ea4c --- /dev/null +++ b/plugins/plugin-watermark/src/node/options.ts @@ -0,0 +1,41 @@ +import type { Page } from 'vuepress' +import type { WatermarkPureOptions } from '../shared/index.js' + +export interface WatermarkPluginOptions { + /** + * Specify which pages need to have watermarks added. + * + * Pages with `true` value will have watermarks added. + * + * 指定哪些页面需要添加水印。 + * + * 拥有 `true` 值的页面将会被添加水印。 + * + * @default false + */ + enabled?: boolean | ((page: Page) => boolean) + + /** + * Watermark options + * + * 水印配置选项 + * + * @see [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/config/) + */ + watermarkOptions?: WatermarkPureOptions + + /** + * Delay for adding watermarks. In milliseconds. + * + * This delay will only take effect when adding watermarks to a specific element on the page. + * + * A delay may be required when the watermark parent is rerendered when switching pages. + * + * 添加水印的延时。以毫秒为单位。 + * 该延迟仅会在添加水印到页面某个元素时生效。 + * 在切换路由后,需要延迟一段时间后才能添加水印。 + * + * @default 500 + */ + delay?: number +} diff --git a/plugins/plugin-watermark/src/node/watermarkPlugin.ts b/plugins/plugin-watermark/src/node/watermarkPlugin.ts new file mode 100644 index 0000000000..415f45a32b --- /dev/null +++ b/plugins/plugin-watermark/src/node/watermarkPlugin.ts @@ -0,0 +1,39 @@ +import type { Plugin } from 'vuepress/core' +import { isFunction } from 'vuepress/shared' +import { getDirname, path } from 'vuepress/utils' +import { logger, PLUGIN_NAME } from './logger.js' +import type { WatermarkPluginOptions } from './options.js' + +const __dirname = getDirname(import.meta.url) + +export const watermarkPlugin = + ({ + enabled: enable = true, + ...options + }: WatermarkPluginOptions = {}): Plugin => + (app) => { + if (app.env.isDebug) logger.info('Options:', options) + + return { + name: PLUGIN_NAME, + + define: { + __WM_DELAY__: options.delay ?? 500, + __WM_GLOBAL__: enable === true, + __WM_OPTIONS__: options.watermarkOptions ?? {}, + }, + + extendsPage: (page) => { + // When watermark is a filter function, enable watermark for matching pages. + if (isFunction(enable)) { + const { frontmatter } = page + + if (!('watermark' in frontmatter) && enable(page)) { + frontmatter.watermark = true + } + } + }, + + clientConfigFile: path.resolve(__dirname, '../client/config.js'), + } + } diff --git a/plugins/plugin-watermark/src/shared/index.ts b/plugins/plugin-watermark/src/shared/index.ts new file mode 100644 index 0000000000..a66c7e8d47 --- /dev/null +++ b/plugins/plugin-watermark/src/shared/index.ts @@ -0,0 +1 @@ +export * from './options.js' diff --git a/plugins/plugin-watermark/src/shared/options.ts b/plugins/plugin-watermark/src/shared/options.ts new file mode 100644 index 0000000000..1edeaf9ba8 --- /dev/null +++ b/plugins/plugin-watermark/src/shared/options.ts @@ -0,0 +1,24 @@ +import type { WatermarkOptions as _WatermarkRawOptions } from 'watermark-js-plus/dist/types/src/types/index.js' + +export type WatermarkPureOptions = Omit< + Partial<_WatermarkRawOptions>, + | 'onSuccess' + | 'onBeforeDestroy' + | 'onDestroyed' + | 'extraDrawFunc' + | 'onObserveError' + | 'parent' +> & { + /** + * Watermark parent selector + * + * 水印父元素选择器 + * + * @default 'body' + */ + parent?: 'body' | (string & { __z_ignore?: never }) +} + +export interface WatermarkPluginFrontmatter { + watermark?: WatermarkPureOptions | boolean +} diff --git a/plugins/plugin-watermark/tsconfig.build.json b/plugins/plugin-watermark/tsconfig.build.json new file mode 100644 index 0000000000..fd3f9ed86a --- /dev/null +++ b/plugins/plugin-watermark/tsconfig.build.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./lib", + "types": ["vuepress/client-types"] + }, + "include": ["./src"], + "references": [ + { + "path": "../../tools/helper/tsconfig.build.json" + } + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cfadd0c2e..58173c7c3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -188,6 +188,9 @@ importers: '@vuepress/plugin-redirect': specifier: workspace:* version: link:../plugins/plugin-redirect + '@vuepress/plugin-watermark': + specifier: workspace:* + version: link:../plugins/plugin-watermark '@vuepress/theme-default': specifier: workspace:* version: link:../themes/theme-default @@ -653,6 +656,21 @@ importers: specifier: 2.0.0-rc.9 version: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.9(@types/node@20.12.7)(jiti@1.21.0)(sass@1.75.0)(terser@5.30.4)(typescript@5.4.5))(@vuepress/bundler-webpack@2.0.0-rc.9(typescript@5.4.5))(typescript@5.4.5)(vue@3.4.26(typescript@5.4.5)) + plugins/plugin-watermark: + dependencies: + '@vuepress/helper': + specifier: workspace:* + version: link:../../tools/helper + vue: + specifier: ^3.4.26 + version: 3.4.26(typescript@5.4.5) + vuepress: + specifier: 2.0.0-rc.9 + version: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.9(@types/node@20.12.7)(jiti@1.21.0)(sass@1.75.0)(terser@5.30.4)(typescript@5.4.5))(@vuepress/bundler-webpack@2.0.0-rc.9(typescript@5.4.5))(typescript@5.4.5)(vue@3.4.26(typescript@5.4.5)) + watermark-js-plus: + specifier: ^1.4.22 + version: 1.4.22 + themes/theme-default: dependencies: '@vuepress/helper': @@ -6477,6 +6495,10 @@ packages: resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} engines: {node: '>=10.13.0'} + watermark-js-plus@1.4.22: + resolution: {integrity: sha512-/UquC1Wkj3UuraGDmx29Ri3tu4gla05k9u0e+l4T1Ms69bWvLi/K74y9iyzp502gL55gm4BV8jUjvs6LvAzKmA==} + engines: {node: '>=16.0.0'} + wbuf@1.7.3: resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} @@ -8516,7 +8538,7 @@ snapshots: '@types/markdown-it-emoji@2.0.5': dependencies: - '@types/markdown-it': 13.0.7 + '@types/markdown-it': 14.0.1 '@types/markdown-it@13.0.7': dependencies: @@ -13218,6 +13240,8 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 + watermark-js-plus@1.4.22: {} + wbuf@1.7.3: dependencies: minimalistic-assert: 1.0.1 diff --git a/tsconfig.build.json b/tsconfig.build.json index 44e2d38062..322cc6ce0c 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -53,6 +53,7 @@ { "path": "./plugins/plugin-sitemap/tsconfig.build.json" }, { "path": "./plugins/plugin-theme-data/tsconfig.build.json" }, { "path": "./plugins/plugin-toc/tsconfig.build.json" }, + { "path": "./plugins/plugin-watermark/tsconfig.build.json" }, { "path": "./themes/theme-default/tsconfig.build.json" }, { "path": "./tools/create-vuepress/tsconfig.build.json" }, { "path": "./tools/helper/tsconfig.build.json" },