vitepress-plugin-toolkit 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,391 @@
1
+ # vitepress-plugin-toolkit
2
+
3
+ > [中文文档](./README.zh-CN.md)
4
+
5
+ Development toolkit for VitePress plugin authors, providing shared utilities, components, and composables for both Node and Client side.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add vitepress-plugin-toolkit
11
+ ```
12
+
13
+ ## Entry Points
14
+
15
+ | Entry | Description |
16
+ | ----------------------------------- | ------------------------------------------------------------------------------- |
17
+ | `vitepress-plugin-toolkit` | Node-side tools (markdown-it plugins, Vite plugins, VitePress config utilities) |
18
+ | `vitepress-plugin-toolkit/client` | Client-side tools (Vue components, composables, environment detection) |
19
+ | `vitepress-plugin-toolkit/styles/*` | CSS transition animations and component styles |
20
+
21
+ ## Node API
22
+
23
+ ### Markdown Tools
24
+
25
+ #### `createEmbedRuleBlock(md, options)`
26
+
27
+ Creates an embed rule block for parsing `@[type info](source)` syntax in markdown.
28
+
29
+ ```ts
30
+ import { createEmbedRuleBlock } from 'vitepress-plugin-toolkit'
31
+
32
+ createEmbedRuleBlock(md, {
33
+ type: 'video',
34
+ meta: (info, source) => ({ src: source, title: info }),
35
+ content: meta => `<video src="${meta.src}" title="${meta.title}"></video>`,
36
+ })
37
+ ```
38
+
39
+ Usage in markdown:
40
+
41
+ ```md
42
+ @[video My Video](https://example.com/video.mp4)
43
+ ```
44
+
45
+ **Options:**
46
+
47
+ | Parameter | Type | Description |
48
+ | --------- | ------------------------------------------ | -------------------------------------------------------- |
49
+ | `type` | `string` | Embed type identifier, e.g. `'video'`, `'embed'` |
50
+ | `name` | `string` | Optional, custom token name, defaults to `embed_${type}` |
51
+ | `meta` | `(info: string, source: string) => Meta` | Parses info and source into a metadata object |
52
+ | `content` | `(meta: Meta, env: MarkdownEnv) => string` | Optional, generates HTML content from metadata |
53
+
54
+ #### `createContainerPlugin(md, type, options?)`
55
+
56
+ Creates a custom container plugin based on `markdown-it-container`. Content is processed normally by markdown-it.
57
+
58
+ ```ts
59
+ import { createContainerPlugin } from 'vitepress-plugin-toolkit'
60
+
61
+ md.use(createContainerPlugin, 'tip', {
62
+ before: info => `<div class="tip">${info}`,
63
+ after: () => '</div>',
64
+ })
65
+ ```
66
+
67
+ Usage in markdown:
68
+
69
+ ```md
70
+ ::: tip Note
71
+ This is a tip message
72
+ :::
73
+ ```
74
+
75
+ **Options:**
76
+
77
+ | Parameter | Type | Description |
78
+ | --------- | ----------------------------------------------------- | -------------------------------------------- |
79
+ | `before` | `(info: string, ...args: RenderRuleParams) => string` | Optional, callback for container opening tag |
80
+ | `after` | `(info: string, ...args: RenderRuleParams) => string` | Optional, callback for container closing tag |
81
+
82
+ #### `createContainerSyntaxPlugin(md, type, render?)`
83
+
84
+ Creates a custom container syntax plugin. Content inside the container is **NOT** processed by markdown-it,
85
+ but passed entirely to a custom render function.
86
+
87
+ ```ts
88
+ import { createContainerSyntaxPlugin } from 'vitepress-plugin-toolkit'
89
+
90
+ createContainerSyntaxPlugin(md, 'chart', (tokens, idx) => {
91
+ const { content, meta } = tokens[idx]
92
+ return `<div class="chart">${content}</div>`
93
+ })
94
+ ```
95
+
96
+ ### VitePress Config Utilities
97
+
98
+ #### `getVitepressConfig()`
99
+
100
+ Retrieves the current VitePress site configuration from `globalThis.VITEPRESS_CONFIG`.
101
+
102
+ ```ts
103
+ import { getVitepressConfig } from 'vitepress-plugin-toolkit'
104
+
105
+ const config = getVitepressConfig()
106
+ console.log(config.userConfig.title)
107
+ ```
108
+
109
+ #### `createLocales(builtinLocales, userLocales?)`
110
+
111
+ Creates a locales configuration by merging built-in locale data with user-provided locale data.
112
+
113
+ ```ts
114
+ import { createLocales } from 'vitepress-plugin-toolkit'
115
+
116
+ const locales = createLocales(
117
+ [
118
+ [['en', 'en-US'], { title: 'English' }],
119
+ [['zh', 'zh-CN'], { title: '中文' }],
120
+ ],
121
+ { zh: { title: 'My Site' } },
122
+ )
123
+ ```
124
+
125
+ #### `resolveRouteLink(url, env)`
126
+
127
+ Resolves markdown links according to VitePress routing rules:
128
+
129
+ - External links returned as-is
130
+ - Absolute paths prefixed with site base
131
+ - Relative `.md` links converted to `.html` based on `cleanUrls`
132
+ - `index.md` collapsed to directory path
133
+ - Hash fragments auto-slugified
134
+
135
+ ```ts
136
+ import { resolveRouteLink } from 'vitepress-plugin-toolkit'
137
+
138
+ resolveRouteLink('./guide.md', env) // -> './guide.html' (depends on cleanUrls)
139
+ ```
140
+
141
+ #### `getLocaleWithPath(path)`
142
+
143
+ Returns the language code and locale prefix for a given path.
144
+
145
+ ```ts
146
+ import { getLocaleWithPath } from 'vitepress-plugin-toolkit'
147
+
148
+ getLocaleWithPath('/zh/guide/') // { lang: 'zh-CN', locale: '/zh/' }
149
+ getLocaleWithPath('/guide/') // { lang: 'en', locale: '' } (root)
150
+ ```
151
+
152
+ ### Vite Plugin
153
+
154
+ #### `iconPlugin(icons)`
155
+
156
+ Creates a Vite plugin that registers SVG icons as CSS custom properties (`--icon`), generating CSS selectors like `.vpi-<name>`.
157
+
158
+ ```ts
159
+ import { iconPlugin } from 'vitepress-plugin-toolkit'
160
+
161
+ defineConfig({
162
+ vite: {
163
+ plugins: [
164
+ iconPlugin([
165
+ { name: 'github', svg: '<svg>...</svg>' },
166
+ { name: 'twitter', svg: '<svg>...</svg>' },
167
+ ]),
168
+ ],
169
+ },
170
+ })
171
+ ```
172
+
173
+ Display icons by adding class names:
174
+
175
+ ```html
176
+ <span class="vpi-github"></span>
177
+ ```
178
+
179
+ ### Node Utility Functions
180
+
181
+ #### `resolveAttrs(info)` / `resolveAttr(info, key)`
182
+
183
+ Parses an attribute string into an object, or extracts a single attribute value.
184
+ Supports `key="value"` format and boolean attributes (`disabled`, etc.).
185
+
186
+ ```ts
187
+ import { resolveAttrs, resolveAttr } from 'vitepress-plugin-toolkit'
188
+
189
+ resolveAttrs('width="100" height="50"') // { width: '100', height: '50' }
190
+ resolveAttr('width="100" height="50"', 'width') // '100'
191
+ ```
192
+
193
+ #### `stringifyAttrs(attrs, withUndefinedOrNull?, forceStringify?)`
194
+
195
+ Stringifies an attributes object into an HTML attribute string. Automatically handles Boolean, Number, and String types.
196
+
197
+ ```ts
198
+ import { stringifyAttrs } from 'vitepress-plugin-toolkit'
199
+
200
+ stringifyAttrs({ width: 100, disabled: true })
201
+ // ' :width="100" disabled'
202
+ ```
203
+
204
+ #### `parseRect(str, unit?)`
205
+
206
+ Parses a size string, appending a unit (default `px`) to bare numbers.
207
+
208
+ ```ts
209
+ import { parseRect } from 'vitepress-plugin-toolkit'
210
+
211
+ parseRect('100') // '100px'
212
+ parseRect('50%') // '50%'
213
+ parseRect('200', 'rpx') // '200rpx'
214
+ ```
215
+
216
+ #### `slugify(str)`
217
+
218
+ Generates a URL-friendly slug, removing accents, control characters, and special characters, and merging consecutive separators.
219
+
220
+ ```ts
221
+ import { slugify } from 'vitepress-plugin-toolkit'
222
+
223
+ slugify('Hello World!') // 'hello-world'
224
+ ```
225
+
226
+ #### `genHash(data, length?)`
227
+
228
+ Generates a SHA-256 hash for any data, with optional truncation length.
229
+
230
+ ```ts
231
+ import { genHash } from 'vitepress-plugin-toolkit'
232
+
233
+ genHash('hello') // full SHA-256 hash
234
+ genHash({ a: 1 }, 8) // 8-character hash
235
+ ```
236
+
237
+ #### `treatAsHtml(filename)`
238
+
239
+ Determines whether a file should be treated as an HTML route (not a static asset).
240
+
241
+ ```ts
242
+ import { treatAsHtml } from 'vitepress-plugin-toolkit'
243
+
244
+ treatAsHtml('about') // true
245
+ treatAsHtml('logo.png') // false
246
+ ```
247
+
248
+ #### `createLogger(prefix, defaultLevel?)`
249
+
250
+ Creates a formatted logger instance with colored labels and timestamps.
251
+
252
+ ```ts
253
+ import { createLogger } from 'vitepress-plugin-toolkit'
254
+
255
+ const logger = createLogger('my-plugin', 'info')
256
+ logger.info('Build started')
257
+ logger.warn('Deprecated feature used')
258
+ logger.debug('Verbose details', 'debug')
259
+ ```
260
+
261
+ #### Constants
262
+
263
+ ```ts
264
+ import {
265
+ isBuild, // Whether building for production
266
+ isDev, // Whether in development mode
267
+ EXTENSION_VIDEOS, // Browser-supported video file extensions
268
+ EXTENSION_IMAGES, // Browser-supported image file extensions
269
+ EXTENSION_AUDIOS, // Browser-supported audio file extensions
270
+ } from 'vitepress-plugin-toolkit'
271
+ ```
272
+
273
+ ## Client API
274
+
275
+ ### Vue Components
276
+
277
+ - `VPCopyButton` — Copy-to-clipboard button component
278
+ - `VPLoading` — Loading animation component
279
+ - `VPTabSwitch` — Tab switch component
280
+
281
+ ```vue
282
+ <script setup>
283
+ import { VPCopyButton, VPLoading, VPTabSwitch } from 'vitepress-plugin-toolkit/client'
284
+ </script>
285
+
286
+ <template>
287
+ <VPCopyButton text="Click to copy this text" />
288
+ <VPLoading :size="40" />
289
+ <VPTabSwitch :tabs="['Code', 'Preview']" />
290
+ </template>
291
+ ```
292
+
293
+ ### Composables
294
+
295
+ #### `useSize(el, options, extraHeight?)`
296
+
297
+ Reactive size calculation based on width, height, and aspect ratio options. Automatically listens for window resize and orientationchange events.
298
+
299
+ ```ts
300
+ import { useSize } from 'vitepress-plugin-toolkit/client'
301
+
302
+ const el = ref<HTMLElement>()
303
+ const { width, height, resize } = useSize(
304
+ el,
305
+ toRefs({ width: '100%', ratio: '16:9' }),
306
+ )
307
+ ```
308
+
309
+ #### `useZoomAndDrag(parentEl)`
310
+
311
+ Provides zoom and drag interaction for a content stage, supporting mouse drag, touch drag, and pinch-to-zoom.
312
+
313
+ ```ts
314
+ import { useZoomAndDrag } from 'vitepress-plugin-toolkit/client'
315
+
316
+ const stageEl = ref<HTMLDivElement>()
317
+ const { actorStyle, zoom, zoomIn, zoomOut, resetZoom, reset } = useZoomAndDrag(stageEl)
318
+ ```
319
+
320
+ ### Environment Detection
321
+
322
+ ```ts
323
+ import {
324
+ isiPhone, // Is iPhone
325
+ isiPad, // Is iPad
326
+ isIOS, // Is iOS
327
+ isWindows, // Is Windows
328
+ isMacOS, // Is macOS
329
+ isSafari, // Is Safari browser
330
+ isMobile, // Is mobile device
331
+ } from 'vitepress-plugin-toolkit/client'
332
+ ```
333
+
334
+ ### CSS Transitions
335
+
336
+ Import preset CSS transition classes via `vitepress-plugin-toolkit/styles/*`:
337
+
338
+ ```
339
+ vitepress-plugin-toolkit/styles/transition/fade-in.css
340
+ vitepress-plugin-toolkit/styles/transition/fade-in-up.css
341
+ vitepress-plugin-toolkit/styles/transition/fade-in-down.css
342
+ vitepress-plugin-toolkit/styles/transition/fade-in-left.css
343
+ vitepress-plugin-toolkit/styles/transition/fade-in-right.css
344
+ vitepress-plugin-toolkit/styles/transition/fade-in-scale-up.css
345
+ vitepress-plugin-toolkit/styles/transition/fade-in-width-expand.css
346
+ vitepress-plugin-toolkit/styles/transition/fade-in-height-expand.css
347
+ vitepress-plugin-toolkit/styles/transition/slide-in-up.css
348
+ vitepress-plugin-toolkit/styles/transition/slide-in-down.css
349
+ vitepress-plugin-toolkit/styles/transition/slide-in-left.css
350
+ vitepress-plugin-toolkit/styles/transition/slide-in-right.css
351
+ ```
352
+
353
+ ```ts
354
+ import 'vitepress-plugin-toolkit/styles/transition/fade-in-up.css'
355
+ ```
356
+
357
+ ## Shared
358
+
359
+ The following utilities are available on both Node and Client side.
360
+
361
+ ### `isExternal(path)` / `isLinkWithProtocol(link)`
362
+
363
+ Checks whether a path is an external URL.
364
+
365
+ ```ts
366
+ import { isExternal, isLinkWithProtocol } from 'vitepress-plugin-toolkit'
367
+
368
+ isExternal('https://example.com') // true
369
+ isExternal('/about') // false
370
+ isLinkWithProtocol('//cdn.example.com/lib.js') // true
371
+ ```
372
+
373
+ ### `EXTERNAL_URL_RE` / `URL_PROTOCOL_RE`
374
+
375
+ Regular expressions for matching external URLs and protocol schemes.
376
+
377
+ ### `SizeOptions`
378
+
379
+ TypeScript interface for size configuration:
380
+
381
+ ```ts
382
+ interface SizeOptions {
383
+ width?: string // Width CSS value, e.g. '100%', '640px'
384
+ height?: string // Height CSS value, e.g. 'auto', '360px'
385
+ ratio?: number | string // Aspect ratio, e.g. 16/9 or '16:9'
386
+ }
387
+ ```
388
+
389
+ ## License
390
+
391
+ MIT