vitepress-linkcard 1.2.8 → 2.0.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 +36 -22
- package/dist/.cjs.min.js +5 -5
- package/dist/.esm.min.js +5 -5
- package/dist/api.js +31 -3
- package/dist/assemble/html.js +61 -8
- package/dist/assemble/local-file-cache.js +119 -8
- package/dist/assemble/metadata.js +30 -2
- package/dist/assemble/parser.js +133 -19
- package/dist/assemble/style.js +117 -18
- package/dist/assemble/url.js +35 -4
- package/dist/assemble/xhr.js +71 -5
- package/dist/link-to-card-plugin.js +104 -24
- package/package.json +3 -3
- package/types/api.d.ts +42 -3
- package/types/assemble/html.d.ts +51 -3
- package/types/assemble/local-file-cache.d.ts +98 -8
- package/types/assemble/metadata.d.ts +25 -2
- package/types/assemble/parser.d.ts +31 -4
- package/types/assemble/style.d.ts +56 -7
- package/types/assemble/url.d.ts +35 -4
- package/types/assemble/xhr.d.ts +62 -4
- package/types/link-to-card-plugin.d.ts +27 -2
- package/types/types.d.ts +103 -4
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
import { isFunction } from '@luckrya/utility';
|
|
2
2
|
import { getUrlMetadata, generateCardDomFragment } from './assemble';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Markdown-it plugin that converts specially-formatted links into rich link preview cards.
|
|
5
|
+
*
|
|
6
|
+
* This plugin intercepts markdown links that start with the `@:` prefix and transforms them
|
|
7
|
+
* into interactive cards displaying metadata (title, description, logo) fetched from the target URL.
|
|
8
|
+
*
|
|
9
|
+
* ## Usage
|
|
10
|
+
*
|
|
11
|
+
* In your markdown file:
|
|
12
|
+
* ```md
|
|
13
|
+
* [@:https://example.com](Link Title)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Plugin configuration:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import MarkdownIt from 'markdown-it'
|
|
19
|
+
* import { linkToCardPlugin } from 'vitepress-linkcard'
|
|
20
|
+
*
|
|
21
|
+
* const md = new MarkdownIt()
|
|
22
|
+
* md.use(linkToCardPlugin, {
|
|
23
|
+
* target: '_blank'
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @param md - The markdown-it instance
|
|
28
|
+
* @param pluginOptions - Configuration options for the plugin
|
|
29
|
+
*
|
|
30
|
+
* @see {@link LinkToCardPluginOptions} for available options
|
|
6
31
|
*/
|
|
7
32
|
export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
33
|
+
/**
|
|
34
|
+
* Parses a link href to determine if it's a card link and extracts the URL.
|
|
35
|
+
*
|
|
36
|
+
* Card links are identified by the `@:` prefix (e.g., `@:https://example.com`).
|
|
37
|
+
*
|
|
38
|
+
* @param href - The href attribute from a markdown link token
|
|
39
|
+
* @returns An object containing:
|
|
40
|
+
* - `isCardLink`: true if the href matches the card link pattern
|
|
41
|
+
* - `url`: the extracted URL (without the `@:` prefix)
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
8
45
|
function parseCardLinkHref(href) {
|
|
9
46
|
const tagRegexp = new RegExp(`^(${'@'}:)([a-zA-Z0-9]+.*)`);
|
|
10
47
|
const match = href?.match(tagRegexp);
|
|
@@ -14,8 +51,21 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
14
51
|
};
|
|
15
52
|
}
|
|
16
53
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
54
|
+
* Assembles the HTML template for a link card by fetching metadata and rendering.
|
|
55
|
+
*
|
|
56
|
+
* This function:
|
|
57
|
+
* 1. Fetches URL metadata (title, description, logo)
|
|
58
|
+
* 2. Hides remaining tokens in the link to prevent duplicate content
|
|
59
|
+
* 3. Extracts the link title from tokens
|
|
60
|
+
* 4. Renders the card using either a custom renderer or the default one
|
|
61
|
+
*
|
|
62
|
+
* @param options - Contains the URL and token information
|
|
63
|
+
* @param options.url - The URL to create a card for
|
|
64
|
+
* @param options.tokens - Array of markdown-it tokens
|
|
65
|
+
* @param options.i - Current token index
|
|
66
|
+
* @returns HTML string of the rendered card, or undefined if metadata cannot be fetched
|
|
67
|
+
*
|
|
68
|
+
* @internal
|
|
19
69
|
*/
|
|
20
70
|
function assembleCardTpl(options) {
|
|
21
71
|
const urlMetadata = getUrlMetadata(options.url);
|
|
@@ -25,9 +75,7 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
25
75
|
href: options.url,
|
|
26
76
|
linkTitle: joinLinkTitle(options.tokens),
|
|
27
77
|
target: pluginOptions.target || '_blank',
|
|
28
|
-
classPrefix: pluginOptions.classPrefix
|
|
29
|
-
borderColor: pluginOptions.borderColor,
|
|
30
|
-
bgColor: pluginOptions.bgColor
|
|
78
|
+
classPrefix: pluginOptions.classPrefix
|
|
31
79
|
};
|
|
32
80
|
return isFunction(pluginOptions.render)
|
|
33
81
|
? pluginOptions.render(urlMetadata, cardDomOptions)
|
|
@@ -35,11 +83,17 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
35
83
|
}
|
|
36
84
|
}
|
|
37
85
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
86
|
+
* Custom inline renderer that preserves hidden token handling.
|
|
87
|
+
*
|
|
88
|
+
* This overrides the default markdown-it inline renderer to properly handle
|
|
89
|
+
* tokens marked as hidden, which is necessary for the card link processing.
|
|
90
|
+
*
|
|
91
|
+
* @param tokens - Array of tokens to render
|
|
92
|
+
* @param rootOptions - Markdown-it rendering options
|
|
93
|
+
* @param env - Markdown-it environment variables
|
|
94
|
+
* @returns The rendered HTML string
|
|
95
|
+
*
|
|
96
|
+
* @see {@link https://markdown-it.github.io/markdown-it/#MarkdownIt.renderInline | MarkdownIt.renderInline}
|
|
43
97
|
*/
|
|
44
98
|
md.renderer.renderInline = (tokens, rootOptions, env) => {
|
|
45
99
|
let result = '';
|
|
@@ -59,13 +113,22 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
59
113
|
return result;
|
|
60
114
|
};
|
|
61
115
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* @
|
|
116
|
+
* Custom renderer for link_open tokens that intercepts card links.
|
|
117
|
+
*
|
|
118
|
+
* This function checks if a link is a card link (prefixed with `@:`) and if so,
|
|
119
|
+
* generates and returns the card HTML. Regular links are passed through to the
|
|
120
|
+
* default renderer.
|
|
121
|
+
*
|
|
122
|
+
* @param tokens - Array of tokens being rendered
|
|
123
|
+
* @param i - Current token index
|
|
124
|
+
* @param rootOptions - Markdown-it rendering options
|
|
125
|
+
* @param env - Markdown-it environment (must be present even if unused to maintain signature)
|
|
126
|
+
* @param self - The renderer instance
|
|
127
|
+
* @returns HTML string for the link (either a card or a regular link)
|
|
128
|
+
*
|
|
129
|
+
* @remarks
|
|
130
|
+
* The `env` parameter must not be removed even if unused, as it's part of the
|
|
131
|
+
* markdown-it renderer signature.
|
|
69
132
|
*/
|
|
70
133
|
md.renderer.rules.link_open = (tokens, i, rootOptions, env, self) => {
|
|
71
134
|
const token = tokens[i];
|
|
@@ -81,9 +144,18 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
81
144
|
};
|
|
82
145
|
};
|
|
83
146
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
147
|
+
* Marks all tokens except the one at index `i` as hidden.
|
|
148
|
+
*
|
|
149
|
+
* This is used to prevent the link text and closing tag from being rendered
|
|
150
|
+
* when a card link is detected, as the card HTML replaces the entire link element.
|
|
151
|
+
*
|
|
152
|
+
* @param tokens - Array of tokens to modify
|
|
153
|
+
* @param i - Index of the token to keep visible
|
|
154
|
+
*
|
|
155
|
+
* @todo Handle softbreak tokens properly
|
|
156
|
+
* @see {@link https://markdown-it.github.io/ | markdown-it documentation}
|
|
157
|
+
*
|
|
158
|
+
* @internal
|
|
87
159
|
*/
|
|
88
160
|
function ignoreRestToken(tokens, i) {
|
|
89
161
|
tokens.forEach((token, index) => {
|
|
@@ -92,8 +164,16 @@ function ignoreRestToken(tokens, i) {
|
|
|
92
164
|
});
|
|
93
165
|
}
|
|
94
166
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
167
|
+
* Extracts and joins the content from hidden tokens to form the link title.
|
|
168
|
+
*
|
|
169
|
+
* When processing a card link, the link text tokens are marked as hidden.
|
|
170
|
+
* This function collects the content from those hidden tokens to use as the
|
|
171
|
+
* card's title attribute.
|
|
172
|
+
*
|
|
173
|
+
* @param tokens - Array of tokens to extract content from
|
|
174
|
+
* @returns The concatenated content from all hidden tokens
|
|
175
|
+
*
|
|
176
|
+
* @internal
|
|
97
177
|
*/
|
|
98
178
|
function joinLinkTitle(tokens) {
|
|
99
179
|
return tokens
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
22
22
|
"@types/babel__core": "^7",
|
|
23
23
|
"@types/markdown-it": "^13.0.2",
|
|
24
|
-
"@types/node": "^25.0.
|
|
24
|
+
"@types/node": "^25.0.3",
|
|
25
25
|
"eslint": "^9.39.2",
|
|
26
26
|
"eslint-plugin-vue": "^10.6.2",
|
|
27
27
|
"globals": "^16.5.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"typedoc": "^0.28.15",
|
|
35
35
|
"typedoc-theme-hierarchy": "^6.0.0",
|
|
36
36
|
"typescript": "^5.9.3",
|
|
37
|
-
"typescript-eslint": "^8.50.
|
|
37
|
+
"typescript-eslint": "^8.50.1",
|
|
38
38
|
"vue-eslint-parser": "^10.2.0",
|
|
39
39
|
"xmlhttprequest": "^1.8.0"
|
|
40
40
|
},
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
},
|
|
76
76
|
"type": "module",
|
|
77
77
|
"types": "./types/index.d.ts",
|
|
78
|
-
"version": "
|
|
78
|
+
"version": "2.0.0"
|
|
79
79
|
}
|
package/types/api.d.ts
CHANGED
|
@@ -1,14 +1,53 @@
|
|
|
1
1
|
import type { UrlMetadata, CardDomRenderOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Represents a complete card response with all necessary data for rendering.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
2
6
|
interface CardResponse {
|
|
7
|
+
/**
|
|
8
|
+
* The URL that was fetched.
|
|
9
|
+
*/
|
|
3
10
|
url: string;
|
|
11
|
+
/**
|
|
12
|
+
* Parsed metadata from the URL.
|
|
13
|
+
*/
|
|
4
14
|
data: UrlMetadata;
|
|
15
|
+
/**
|
|
16
|
+
* Rendering options (excluding href which is derived from url).
|
|
17
|
+
*/
|
|
5
18
|
options: Omit<CardDomRenderOptions, 'href'>;
|
|
19
|
+
/**
|
|
20
|
+
* The generated HTML string for the card.
|
|
21
|
+
*/
|
|
6
22
|
dom: string;
|
|
7
23
|
}
|
|
8
24
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
25
|
+
* Generates a link card by fetching and parsing metadata from a URL.
|
|
26
|
+
*
|
|
27
|
+
* This function performs the following operations:
|
|
28
|
+
* 1. Fetches the HTML content from the provided URL synchronously
|
|
29
|
+
* 2. Parses metadata (title, description, logo) from the HTML
|
|
30
|
+
* 3. Generates an HTML card fragment with the metadata
|
|
31
|
+
* 4. Caches the result for subsequent calls
|
|
32
|
+
*
|
|
33
|
+
* The function is primarily used by the link-to-card plugin during markdown processing
|
|
34
|
+
* but can also be used standalone for programmatic card generation.
|
|
35
|
+
*
|
|
36
|
+
* @param url - The URL to fetch metadata from
|
|
37
|
+
* @param options - Rendering options for the card (excluding href, which is set to the url parameter)
|
|
38
|
+
* @returns A promise that resolves to a CardResponse containing the card data and HTML
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const card = await generateCard('https://example.com', {
|
|
43
|
+
* linkTitle: 'Example Site',
|
|
44
|
+
* target: '_blank'
|
|
45
|
+
* })
|
|
46
|
+
* console.log(card.dom) // HTML string of the card
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @see {@link parserMetadata} for details on metadata extraction
|
|
50
|
+
* @see {@link generateCardDomFragment} for details on card HTML generation
|
|
12
51
|
*/
|
|
13
52
|
export declare function generateCard(url: string, options: Omit<CardDomRenderOptions, 'href'>): Promise<CardResponse>;
|
|
14
53
|
export {};
|
package/types/assemble/html.d.ts
CHANGED
|
@@ -1,7 +1,55 @@
|
|
|
1
1
|
import type { CardDomRender } from '../types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Generates the HTML DOM fragment for a link card display.
|
|
4
|
+
*
|
|
5
|
+
* This is the default card renderer that creates a rich preview card with:
|
|
6
|
+
* - Card title (with 2-line ellipsis)
|
|
7
|
+
* - Domain name (with underline)
|
|
8
|
+
* - Description (with 2-line ellipsis)
|
|
9
|
+
* - Logo/icon image
|
|
10
|
+
* - Smooth border transition for hover effects
|
|
11
|
+
*
|
|
12
|
+
* The function includes special handling for GitHub URLs to improve the display
|
|
13
|
+
* of repository cards by cleaning up redundant text patterns.
|
|
14
|
+
*
|
|
15
|
+
* @param data - The metadata extracted from the URL (title, description, logo)
|
|
16
|
+
* @param options - Rendering options including href, target, colors, etc.
|
|
17
|
+
* @returns An HTML string containing the complete card markup with inline styles
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const html = generateCardDomFragment(
|
|
22
|
+
* { title: 'Example', description: 'A site', logo: 'https://...' },
|
|
23
|
+
* { href: 'https://example.com', linkTitle: 'Link', target: '_blank' }
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* - HTML entities in title/description are automatically escaped
|
|
29
|
+
* - For GitHub URLs, the title is cleaned to remove "GitHub - " prefix and redundant text
|
|
30
|
+
* - The card uses flexbox layout for responsive design
|
|
31
|
+
* - All styles are inlined for maximum compatibility
|
|
32
|
+
* - Container has class `vitepress-linkcard-container` for custom styling
|
|
33
|
+
* - Uses CSS custom properties for theming:
|
|
34
|
+
* - `--vitepress-linkcard-border-color`: Customize border color
|
|
35
|
+
* - `--vitepress-linkcard-bg-color`: Customize background color
|
|
36
|
+
* - Styling options in your VitePress theme's custom CSS:
|
|
37
|
+
* ```css
|
|
38
|
+
* .vitepress-linkcard-container {
|
|
39
|
+
* --vitepress-linkcard-border-color: #e0e0e0;
|
|
40
|
+
* --vitepress-linkcard-bg-color: #f9f9f9;
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* .vitepress-linkcard-container {
|
|
44
|
+
* border-color: var(--vp-c-brand-2) !important;
|
|
45
|
+
* background-color: var(--vp-c-brand-soft) !important;
|
|
46
|
+
* }
|
|
47
|
+
*
|
|
48
|
+
* .vitepress-linkcard-container:hover {
|
|
49
|
+
* border-color: var(--vp-c-brand-1) !important;
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @see {@link STYLE} for the styling implementation
|
|
6
54
|
*/
|
|
7
55
|
export declare const generateCardDomFragment: CardDomRender;
|
|
@@ -1,26 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local file-based cache implementation for persisting URL metadata.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a simple key-value cache that persists data to a JSON file
|
|
5
|
+
* on disk. It's used to cache fetched URL metadata to avoid redundant network requests
|
|
6
|
+
* across different build sessions.
|
|
7
|
+
*
|
|
8
|
+
* @module local-file-cache
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* A simple file-based cache for storing and retrieving structured data.
|
|
12
|
+
*
|
|
13
|
+
* This class provides a Map-like interface for caching data that persists to disk
|
|
14
|
+
* in JSON format. Each cache entry is keyed by URL and stores structured metadata.
|
|
15
|
+
*
|
|
16
|
+
* The cache file is automatically created if it doesn't exist, and all writes are
|
|
17
|
+
* synchronized and formatted for readability.
|
|
18
|
+
*
|
|
19
|
+
* @template V - The value type, must extend Record<string, unknown>
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const cache = new LocalFileCache<UrlMetadata>()
|
|
24
|
+
*
|
|
25
|
+
* // Store metadata
|
|
26
|
+
* cache.set('https://example.com', {
|
|
27
|
+
* title: 'Example',
|
|
28
|
+
* description: 'A site',
|
|
29
|
+
* logo: 'https://example.com/logo.png'
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* // Retrieve metadata
|
|
33
|
+
* const metadata = cache.get('https://example.com')
|
|
34
|
+
*
|
|
35
|
+
* // Check if URL is cached
|
|
36
|
+
* if (cache.has('https://example.com')) {
|
|
37
|
+
* console.log('URL is cached')
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* - Cache is stored in `.linkcard_cache.json` at project root
|
|
43
|
+
* - All operations are synchronous
|
|
44
|
+
* - Cache persists across process restarts
|
|
45
|
+
* - Merges new data with existing cache entries
|
|
46
|
+
*/
|
|
1
47
|
export default class LocalFileCache<V extends Record<string, unknown>> {
|
|
2
48
|
constructor();
|
|
3
49
|
/**
|
|
4
|
-
*
|
|
50
|
+
* Writes data to the cache file.
|
|
51
|
+
*
|
|
52
|
+
* Merges the provided data with existing cache content and writes the result
|
|
53
|
+
* to disk. The file is automatically formatted after writing.
|
|
54
|
+
*
|
|
55
|
+
* @param data - Object mapping URLs to cached data
|
|
56
|
+
*
|
|
57
|
+
* @private
|
|
5
58
|
*/
|
|
6
59
|
private setFile;
|
|
7
60
|
/**
|
|
8
|
-
*
|
|
61
|
+
* Reads and parses the cache file.
|
|
62
|
+
*
|
|
63
|
+
* @returns The parsed cache data, or undefined if the file is empty or invalid
|
|
64
|
+
*
|
|
65
|
+
* @private
|
|
9
66
|
*/
|
|
10
67
|
private readFile;
|
|
11
68
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
69
|
+
* Checks if a URL exists in the cache.
|
|
70
|
+
*
|
|
71
|
+
* @param url - The URL to check
|
|
72
|
+
* @returns true if the URL has cached data, false otherwise
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* if (cache.has('https://example.com')) {
|
|
77
|
+
* console.log('Cache hit!')
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
14
80
|
*/
|
|
15
81
|
has(url: string): boolean;
|
|
16
82
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
83
|
+
* Retrieves cached data for a URL.
|
|
84
|
+
*
|
|
85
|
+
* @param url - The URL to retrieve data for
|
|
86
|
+
* @returns The cached data for the URL, or undefined if not found
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const metadata = cache.get('https://example.com')
|
|
91
|
+
* if (metadata) {
|
|
92
|
+
* console.log(metadata.title)
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
19
95
|
*/
|
|
20
96
|
get(url: string): V | undefined;
|
|
21
97
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
98
|
+
* Stores data in the cache for a URL.
|
|
99
|
+
*
|
|
100
|
+
* Adds or updates the cache entry for the specified URL. The data is merged
|
|
101
|
+
* with existing cache content and persisted to disk.
|
|
102
|
+
*
|
|
103
|
+
* @param url - The URL to cache data for
|
|
104
|
+
* @param data - The data to cache
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* cache.set('https://example.com', {
|
|
109
|
+
* title: 'Example Domain',
|
|
110
|
+
* description: 'Example description',
|
|
111
|
+
* logo: 'https://example.com/logo.png'
|
|
112
|
+
* })
|
|
113
|
+
* ```
|
|
24
114
|
*/
|
|
25
115
|
set(url: string, data: V): void;
|
|
26
116
|
}
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import type { UrlMetadata } from '../types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Retrieves metadata for a given URL, using cache when available.
|
|
4
|
+
*
|
|
5
|
+
* This function first checks if the metadata is already cached. If not, it fetches
|
|
6
|
+
* the HTML content from the URL, parses the metadata, and caches the result for
|
|
7
|
+
* future use.
|
|
8
|
+
*
|
|
9
|
+
* The metadata includes:
|
|
10
|
+
* - Title (from `<title>` or OGP tags)
|
|
11
|
+
* - Description (from meta description or OGP tags)
|
|
12
|
+
* - Logo/icon (from OGP image or favicon)
|
|
13
|
+
*
|
|
14
|
+
* @param url - The URL to fetch metadata from
|
|
15
|
+
* @returns The parsed URL metadata, or null if the URL cannot be fetched or parsed
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const metadata = getUrlMetadata('https://example.com')
|
|
20
|
+
* if (metadata) {
|
|
21
|
+
* console.log(metadata.title) // "Example Domain"
|
|
22
|
+
* console.log(metadata.description) // "Example website description"
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @see {@link parserMetadata} for details on metadata extraction
|
|
27
|
+
* @see {@link LocalFileCache} for caching implementation
|
|
5
28
|
*/
|
|
6
29
|
export declare function getUrlMetadata(url: string): UrlMetadata | null | undefined;
|
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* HTML parser module for extracting metadata from web pages.
|
|
3
|
+
*
|
|
4
|
+
* This module provides functions to parse HTML strings and extract metadata such as
|
|
5
|
+
* title, description, and logo/icon URLs. It supports both standard HTML meta tags
|
|
6
|
+
* and Open Graph Protocol (OGP) tags.
|
|
7
|
+
*
|
|
8
|
+
* @module parser
|
|
9
|
+
* @todo Refactor to improve maintainability and add support for more meta tag formats
|
|
3
10
|
*/
|
|
4
11
|
import type { UrlMetadata } from '../types';
|
|
5
12
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
13
|
+
* Parses HTML string to extract structured metadata for link card generation.
|
|
14
|
+
*
|
|
15
|
+
* This is the main parsing function that extracts title, description, and logo
|
|
16
|
+
* from an HTML page. It handles both absolute and relative URLs, converting
|
|
17
|
+
* relative logo paths to absolute URLs when necessary.
|
|
18
|
+
*
|
|
19
|
+
* @param htmlString - The HTML content to parse
|
|
20
|
+
* @param url - The URL of the page (used to resolve relative logo URLs)
|
|
21
|
+
* @returns Parsed metadata object, or null if no valid metadata could be extracted
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const html = '<title>Example</title><meta name="description" content="Test">'
|
|
26
|
+
* const metadata = parserMetadata(html, 'https://example.com')
|
|
27
|
+
* // Returns: { title: 'Example', description: 'Test', logo: '...' }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* - Returns null if all metadata fields (title, description, logo) are empty
|
|
32
|
+
* - Relative logo URLs are converted to absolute URLs using the page's origin
|
|
33
|
+
* - Falls back to a default logo if no logo can be found
|
|
34
|
+
*
|
|
35
|
+
* @todo Handle protocol-relative URLs like `//img.example.com/logo.png`
|
|
9
36
|
*/
|
|
10
37
|
export declare function parserMetadata(htmlString: string, url: string): UrlMetadata | null;
|
|
@@ -1,10 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Style generation utilities for link card rendering.
|
|
3
|
+
*
|
|
4
|
+
* This module provides functions to generate inline CSS styles and class names
|
|
5
|
+
* for the link card components. The styles support customizable colors and
|
|
6
|
+
* responsive design with text ellipsis for long content.
|
|
7
|
+
*
|
|
8
|
+
* @module style
|
|
6
9
|
*/
|
|
7
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Generates complete inline styles for all link card components.
|
|
12
|
+
*
|
|
13
|
+
* Creates a set of inline style strings for each part of the link card:
|
|
14
|
+
* - Container: main card box with border and background
|
|
15
|
+
* - Image: logo/icon display
|
|
16
|
+
* - Texts: wrapper for text content
|
|
17
|
+
* - Title: card title (2-line ellipsis)
|
|
18
|
+
* - Domain: domain name with underline
|
|
19
|
+
* - Description: description text (2-line ellipsis)
|
|
20
|
+
*
|
|
21
|
+
* The styles are inspired by VitePress's VPFeature component design.
|
|
22
|
+
*
|
|
23
|
+
* The container uses CSS custom properties for theming:
|
|
24
|
+
* - `--vitepress-linkcard-border-color`: Border color (default: #7d7d7dff)
|
|
25
|
+
* - `--vitepress-linkcard-bg-color`: Background color (default: transparent)
|
|
26
|
+
*
|
|
27
|
+
* @returns Object containing style attribute strings for each card component
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const styles = STYLE()
|
|
32
|
+
* // Use in HTML: <div ${styles.container}>...</div>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @see {@link https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/components/VPFeature.vue | VPFeature component}
|
|
36
|
+
*/
|
|
37
|
+
export declare const STYLE: () => {
|
|
8
38
|
a: string;
|
|
9
39
|
container: string;
|
|
10
40
|
img: string;
|
|
@@ -14,8 +44,27 @@ export declare const STYLE: (borderColor: string, bgColor: string) => {
|
|
|
14
44
|
description: string;
|
|
15
45
|
};
|
|
16
46
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
47
|
+
* Generates CSS class names with a custom prefix.
|
|
48
|
+
*
|
|
49
|
+
* When using the `classPrefix` option, this function creates consistent
|
|
50
|
+
* class names for all card components following a BEM-like naming convention.
|
|
51
|
+
*
|
|
52
|
+
* @param prefix - The prefix to prepend to all class names
|
|
53
|
+
* @returns Object mapping component names to their class names
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const classes = classNames('my-card')
|
|
58
|
+
* // Returns: {
|
|
59
|
+
* // container: 'my-card__container',
|
|
60
|
+
* // title: 'my-card__texts--title',
|
|
61
|
+
* // ...
|
|
62
|
+
* // }
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* When class names are used instead of inline styles, you must provide
|
|
67
|
+
* your own CSS definitions for these classes.
|
|
19
68
|
*/
|
|
20
69
|
export declare const classNames: (prefix?: string) => {
|
|
21
70
|
container: string;
|
package/types/assemble/url.d.ts
CHANGED
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* URL utility functions for parsing and manipulating URLs.
|
|
3
|
+
*
|
|
4
|
+
* @module url
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Parses a URL string and returns a URL object.
|
|
8
|
+
*
|
|
9
|
+
* This is a wrapper around the native URL constructor that provides
|
|
10
|
+
* a consistent interface for URL parsing throughout the codebase.
|
|
11
|
+
*
|
|
12
|
+
* @param url - The URL string to parse
|
|
13
|
+
* @returns A URL object containing the parsed components
|
|
14
|
+
* @throws {TypeError} If the URL string is invalid
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const urlObj = extractUrl('https://example.com/path')
|
|
19
|
+
* console.log(urlObj.origin) // "https://example.com"
|
|
20
|
+
* console.log(urlObj.pathname) // "/path"
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/URL | MDN - URL}
|
|
4
24
|
*/
|
|
5
25
|
export declare function extractUrl(url: string): URL;
|
|
6
26
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
27
|
+
* Removes duplicate consecutive slashes from a path string.
|
|
28
|
+
*
|
|
29
|
+
* This function normalizes paths by replacing multiple consecutive slashes
|
|
30
|
+
* with a single slash. Useful for constructing clean URLs from path segments.
|
|
31
|
+
*
|
|
32
|
+
* @param path - The path string to clean
|
|
33
|
+
* @returns The cleaned path with no consecutive slashes
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* cleanPath('/path//to///file') // Returns: '/path/to/file'
|
|
38
|
+
* cleanPath('//images//logo.png') // Returns: '/images/logo.png'
|
|
39
|
+
* ```
|
|
9
40
|
*/
|
|
10
41
|
export declare function cleanPath(path: string): string;
|