vitepress-linkcard 1.1.1 → 1.1.3
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 +3 -1
- package/dist/.cjs.min.js +1 -1
- package/dist/.esm.min.js +1 -1
- package/dist/api.js +5 -5
- package/dist/assemble/html.js +14 -15
- package/dist/assemble/index.js +4 -4
- package/dist/assemble/local-file-cache.js +10 -10
- package/dist/assemble/metadata.js +2 -2
- package/dist/assemble/parser.js +10 -12
- package/dist/assemble/style.js +42 -42
- package/dist/assemble/url.js +1 -1
- package/dist/assemble/xhr.js +8 -12
- package/dist/index.js +3 -3
- package/dist/link-to-card-plugin.js +12 -12
- package/package.json +2 -2
- package/types/api.d.ts +3 -3
- package/types/assemble/html.d.ts +1 -1
- package/types/assemble/index.d.ts +4 -4
- package/types/assemble/metadata.d.ts +1 -1
- package/types/assemble/parser.d.ts +1 -1
- package/types/index.d.ts +3 -3
- package/types/link-to-card-plugin.d.ts +1 -1
- package/types/types.d.ts +2 -2
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ vitepress-linkcard
|
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
6
6
|
|
|
7
|
+
**Slightly more readable README created with this plugin is [here](https://asumoranda.com/posts/10-vitepress-linkcard.html).**
|
|
8
|
+
|
|
7
9
|
[](https://www.npmjs.com/package/vitepress-linkcard)
|
|
8
10
|
[](https://www.npmjs.com/package/vitepress-linkcard)
|
|
9
11
|
[](/LICENSE)
|
|
@@ -64,7 +66,7 @@ export default defineConfig({
|
|
|
64
66
|
|
|
65
67
|
#### `*.md`
|
|
66
68
|
|
|
67
|
-
Generates a
|
|
69
|
+
Generates a linkcard when `@:` appended.
|
|
68
70
|
|
|
69
71
|
```md
|
|
70
72
|
[example](@:https://example.com)
|
package/dist/.cjs.min.js
CHANGED
package/dist/.esm.min.js
CHANGED
package/dist/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { xhr, generateCardDomFragment, parserMetadata } from
|
|
1
|
+
import { xhr, generateCardDomFragment, parserMetadata } from './assemble';
|
|
2
2
|
const cache = new Map();
|
|
3
3
|
/**
|
|
4
4
|
* @param url
|
|
@@ -13,18 +13,18 @@ export function generateCard(url, options) {
|
|
|
13
13
|
if (urlMetadata) {
|
|
14
14
|
const _options = {
|
|
15
15
|
linkTitle: options.linkTitle,
|
|
16
|
-
target: options.target ||
|
|
17
|
-
classPrefix: options.classPrefix
|
|
16
|
+
target: options.target || '_blank',
|
|
17
|
+
classPrefix: options.classPrefix
|
|
18
18
|
};
|
|
19
19
|
const card = generateCardDomFragment(urlMetadata, {
|
|
20
20
|
..._options,
|
|
21
|
-
href: url
|
|
21
|
+
href: url
|
|
22
22
|
});
|
|
23
23
|
const response = {
|
|
24
24
|
url,
|
|
25
25
|
data: urlMetadata,
|
|
26
26
|
options: _options,
|
|
27
|
-
dom: card
|
|
27
|
+
dom: card
|
|
28
28
|
};
|
|
29
29
|
cache.set(url, response);
|
|
30
30
|
resolve(response);
|
package/dist/assemble/html.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { STYLE } from
|
|
1
|
+
import { STYLE } from './style';
|
|
2
2
|
/**
|
|
3
3
|
* @param data
|
|
4
4
|
* @param options
|
|
@@ -11,33 +11,32 @@ export const generateCardDomFragment = (data, options) => {
|
|
|
11
11
|
href: `href="${options.href}"`,
|
|
12
12
|
title: `title="${options.linkTitle}"`,
|
|
13
13
|
borderColor: `borderColor="${options.borderColor}"`,
|
|
14
|
-
bgColor: `bgColor="${options.bgColor}"
|
|
14
|
+
bgColor: `bgColor="${options.bgColor}"`
|
|
15
15
|
};
|
|
16
16
|
const inject = (s) => {
|
|
17
17
|
return s;
|
|
18
18
|
};
|
|
19
19
|
const escapeHTML = (str) => str
|
|
20
|
-
.replace(/&/g,
|
|
21
|
-
.replace(/</g,
|
|
22
|
-
.replace(/>/g,
|
|
20
|
+
.replace(/&/g, '&')
|
|
21
|
+
.replace(/</g, '<')
|
|
22
|
+
.replace(/>/g, '>')
|
|
23
23
|
.replace(/"/g, '"')
|
|
24
24
|
.replace(/'/g, "'");
|
|
25
|
-
const style = STYLE(options.borderColor ||
|
|
26
|
-
const url = options.href ||
|
|
27
|
-
const domain = new URL(url).origin.replace(/^https?:\/\//,
|
|
28
|
-
"Unknown domain";
|
|
25
|
+
const style = STYLE(options.borderColor || '#7d7d7dff', options.bgColor || '#7d7d7d00');
|
|
26
|
+
const url = options.href || '';
|
|
27
|
+
const domain = new URL(url).origin.replace(/^https?:\/\//, '').replace(/^www\./, '') || 'Unknown domain';
|
|
29
28
|
let title = data.title;
|
|
30
29
|
let description = data.description;
|
|
31
30
|
// Special handling for gitub.com
|
|
32
|
-
if (domain ==
|
|
33
|
-
title = data.title?.split(
|
|
31
|
+
if (domain == 'github.com') {
|
|
32
|
+
title = data.title?.split(':')[0].replace('GitHub - ', '') || 'No title';
|
|
34
33
|
description =
|
|
35
|
-
description?.replace(` - ${title}`,
|
|
36
|
-
|
|
34
|
+
description?.replace(` - ${title}`, '').replace(`Contribute to ${title} development by creating an account on GitHub.`, // 定型句
|
|
35
|
+
'') || '';
|
|
37
36
|
}
|
|
38
37
|
else {
|
|
39
|
-
title = data.title ||
|
|
40
|
-
description = data.description ||
|
|
38
|
+
title = data.title || 'No title';
|
|
39
|
+
description = data.description || '';
|
|
41
40
|
}
|
|
42
41
|
return `<span style="display:block;">
|
|
43
42
|
<a ${aa.rel} ${aa.target} ${aa.href} ${aa.title} ${style.a}>
|
package/dist/assemble/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * as xhr from
|
|
1
|
+
export * from './metadata';
|
|
2
|
+
export * from './html';
|
|
3
|
+
export * from './parser';
|
|
4
|
+
export * as xhr from './xhr';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { isPureObject } from
|
|
2
|
-
import fs from
|
|
1
|
+
import { isPureObject } from '@luckrya/utility';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
3
|
const CONFIG_FILE = () => {
|
|
4
4
|
const filePath = `${process.cwd()}/.linkcard_cache.json`;
|
|
5
5
|
if (!fs.existsSync(filePath)) {
|
|
6
6
|
const initialData = {
|
|
7
|
-
|
|
8
|
-
description:
|
|
9
|
-
logo:
|
|
10
|
-
title:
|
|
11
|
-
}
|
|
7
|
+
'https://example.com/': {
|
|
8
|
+
description: 'Example Website',
|
|
9
|
+
logo: 'https://example.com/example.png',
|
|
10
|
+
title: 'Example Title'
|
|
11
|
+
}
|
|
12
12
|
};
|
|
13
13
|
fs.writeFileSync(filePath, JSON.stringify(initialData, null, 2));
|
|
14
14
|
}
|
|
@@ -16,11 +16,11 @@ const CONFIG_FILE = () => {
|
|
|
16
16
|
};
|
|
17
17
|
const format = () => {
|
|
18
18
|
const filePath = CONFIG_FILE();
|
|
19
|
-
const content = fs.readFileSync(filePath,
|
|
19
|
+
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
|
20
20
|
if (!content)
|
|
21
21
|
return;
|
|
22
22
|
const parsed = JSON.parse(content);
|
|
23
|
-
const formatted = JSON.stringify(parsed, null, 2) +
|
|
23
|
+
const formatted = JSON.stringify(parsed, null, 2) + '\n';
|
|
24
24
|
fs.writeFileSync(filePath, formatted);
|
|
25
25
|
};
|
|
26
26
|
export default class LocalFileCache {
|
|
@@ -41,7 +41,7 @@ export default class LocalFileCache {
|
|
|
41
41
|
* @returns
|
|
42
42
|
*/
|
|
43
43
|
readFile() {
|
|
44
|
-
const content = fs.readFileSync(CONFIG_FILE(),
|
|
44
|
+
const content = fs.readFileSync(CONFIG_FILE(), 'utf-8');
|
|
45
45
|
const data = JSON.parse(content);
|
|
46
46
|
if (isPureObject(data))
|
|
47
47
|
return data;
|
package/dist/assemble/parser.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TODO: Refactor
|
|
3
3
|
*/
|
|
4
|
-
import { isString } from
|
|
5
|
-
import { cleanPath, extractUrl } from
|
|
6
|
-
const DEFAULT_LOGO =
|
|
4
|
+
import { isString } from '@luckrya/utility';
|
|
5
|
+
import { cleanPath, extractUrl } from './url';
|
|
6
|
+
const DEFAULT_LOGO = 'https://resources.whatwg.org/logo-url.svg';
|
|
7
7
|
const HtmlTagContentReg = /(<[A-Za-z]+\s*[^>]*>(.*)<\/[A-Za-z]+>)/;
|
|
8
8
|
const ContentAttrValueHtmlMetaTagReg = /content=["|']([^>]*)["|']/;
|
|
9
9
|
const HrefAttrValueHtmlLinkTagReg = /href=["|']([^>]*)["|']/;
|
|
10
10
|
const HtmlTitleTagReg = /(<title\s*[^>]*>(.*)<\/title>)/g;
|
|
11
11
|
// const HtmlMetaTagReg = /<meta\s[^>]*\/?>/g;
|
|
12
12
|
// const HtmlLinkTagReg = /<link\s[^>]*\/?>/g;
|
|
13
|
-
const containArrSelfLosingHtmlTagReg = (attr, tag =
|
|
13
|
+
const containArrSelfLosingHtmlTagReg = (attr, tag = 'meta') => new RegExp(`<${tag}\\s[^>]*\\w+=['|"]([a-zA-Z]|:|\\s)*${attr}['|"][^>]*\\/?>`);
|
|
14
14
|
/**
|
|
15
15
|
* @param htmlString
|
|
16
16
|
* @returns
|
|
@@ -20,7 +20,7 @@ const containArrSelfLosingHtmlTagReg = (attr, tag = "meta") => new RegExp(`<${ta
|
|
|
20
20
|
*/
|
|
21
21
|
function matchTitleByMetaTag(htmlString) {
|
|
22
22
|
let title;
|
|
23
|
-
const metas = htmlString.match(containArrSelfLosingHtmlTagReg(
|
|
23
|
+
const metas = htmlString.match(containArrSelfLosingHtmlTagReg('title'));
|
|
24
24
|
if (metas?.length) {
|
|
25
25
|
const content = metas[0].match(ContentAttrValueHtmlMetaTagReg);
|
|
26
26
|
if (content && isString(content[1]))
|
|
@@ -43,7 +43,7 @@ function matchTitleByMetaTag(htmlString) {
|
|
|
43
43
|
*/
|
|
44
44
|
function matchDescriptionByMetaTag(htmlString) {
|
|
45
45
|
let description;
|
|
46
|
-
const metas = htmlString.match(containArrSelfLosingHtmlTagReg(
|
|
46
|
+
const metas = htmlString.match(containArrSelfLosingHtmlTagReg('description'));
|
|
47
47
|
if (metas?.length) {
|
|
48
48
|
const content = metas[0].match(ContentAttrValueHtmlMetaTagReg);
|
|
49
49
|
if (content && isString(content[1]))
|
|
@@ -58,14 +58,14 @@ function matchDescriptionByMetaTag(htmlString) {
|
|
|
58
58
|
*/
|
|
59
59
|
function matchLogoByLinkOrMetaTag(htmlString) {
|
|
60
60
|
let logo;
|
|
61
|
-
const metas = htmlString.match(containArrSelfLosingHtmlTagReg(
|
|
61
|
+
const metas = htmlString.match(containArrSelfLosingHtmlTagReg('image'));
|
|
62
62
|
if (metas?.length) {
|
|
63
63
|
const content = metas[0].match(ContentAttrValueHtmlMetaTagReg);
|
|
64
64
|
if (content && isString(content[1]))
|
|
65
65
|
logo = content[1];
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
|
-
const linkHtmlTags = htmlString.match(containArrSelfLosingHtmlTagReg(
|
|
68
|
+
const linkHtmlTags = htmlString.match(containArrSelfLosingHtmlTagReg('icon', 'link'));
|
|
69
69
|
if (linkHtmlTags?.length) {
|
|
70
70
|
const content = linkHtmlTags[0].match(HrefAttrValueHtmlLinkTagReg);
|
|
71
71
|
// logo 判断是否是完整地址
|
|
@@ -84,14 +84,12 @@ export function parserMetadata(htmlString, url) {
|
|
|
84
84
|
function absolute(logo) {
|
|
85
85
|
if (!logo)
|
|
86
86
|
return DEFAULT_LOGO;
|
|
87
|
-
return extractUrl(logo)
|
|
88
|
-
? logo
|
|
89
|
-
: `${extractUrl(url)?.origin}${cleanPath(`/${logo}`)}`; // TODO: no match "content='//img.xx.com/a.png'"
|
|
87
|
+
return extractUrl(logo) ? logo : `${extractUrl(url)?.origin}${cleanPath(`/${logo}`)}`; // TODO: no match "content='//img.xx.com/a.png'"
|
|
90
88
|
}
|
|
91
89
|
const metadata = {
|
|
92
90
|
title: matchTitleByMetaTag(htmlString),
|
|
93
91
|
description: matchDescriptionByMetaTag(htmlString),
|
|
94
|
-
logo: absolute(matchLogoByLinkOrMetaTag(htmlString))
|
|
92
|
+
logo: absolute(matchLogoByLinkOrMetaTag(htmlString))
|
|
95
93
|
};
|
|
96
94
|
if (isEmptyStringObject(metadata))
|
|
97
95
|
return null;
|
package/dist/assemble/style.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @returns
|
|
4
4
|
*/
|
|
5
5
|
function hyphenate(str) {
|
|
6
|
-
return str.replace(/\B([A-Z])/g,
|
|
6
|
+
return str.replace(/\B([A-Z])/g, '-$1').toLowerCase();
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* @param style
|
|
@@ -16,7 +16,7 @@ function join(style) {
|
|
|
16
16
|
return `${hyphenate(k)}: ${v};`;
|
|
17
17
|
})
|
|
18
18
|
.filter(Boolean)
|
|
19
|
-
.join(
|
|
19
|
+
.join(' ');
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* @param style
|
|
@@ -30,15 +30,15 @@ function inlineStyle(style) {
|
|
|
30
30
|
* @returns
|
|
31
31
|
*/
|
|
32
32
|
const ellipsisStyle = (line) => ({
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
display:
|
|
36
|
-
hyphens:
|
|
33
|
+
'-webkit-box-orient': 'vertical',
|
|
34
|
+
'-webkit-line-clamp': line,
|
|
35
|
+
display: '-webkit-box',
|
|
36
|
+
hyphens: 'auto',
|
|
37
37
|
lineClamp: line,
|
|
38
|
-
overflow:
|
|
39
|
-
overflowWrap:
|
|
40
|
-
textOverflow:
|
|
41
|
-
wordBreak:
|
|
38
|
+
overflow: 'hidden',
|
|
39
|
+
overflowWrap: 'anywhere',
|
|
40
|
+
textOverflow: 'ellipsis',
|
|
41
|
+
wordBreak: 'break-word'
|
|
42
42
|
});
|
|
43
43
|
/**
|
|
44
44
|
See: * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/components/VPFeature.vue
|
|
@@ -48,58 +48,58 @@ const ellipsisStyle = (line) => ({
|
|
|
48
48
|
*/
|
|
49
49
|
export const STYLE = (borderColor, bgColor) => ({
|
|
50
50
|
a: inlineStyle({
|
|
51
|
-
color:
|
|
52
|
-
display:
|
|
53
|
-
width:
|
|
54
|
-
textDecoration:
|
|
51
|
+
color: 'unset !important',
|
|
52
|
+
display: 'block',
|
|
53
|
+
width: '100%',
|
|
54
|
+
textDecoration: 'none'
|
|
55
55
|
}),
|
|
56
56
|
container: inlineStyle({
|
|
57
|
-
display:
|
|
58
|
-
alignItems:
|
|
59
|
-
flexWrap:
|
|
60
|
-
gap:
|
|
61
|
-
borderRadius:
|
|
57
|
+
display: 'flex',
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
flexWrap: 'wrap',
|
|
60
|
+
gap: '10px',
|
|
61
|
+
borderRadius: '12px',
|
|
62
62
|
border: `1px solid ${borderColor}`,
|
|
63
63
|
backgroundColor: bgColor,
|
|
64
|
-
boxSizing:
|
|
65
|
-
width:
|
|
66
|
-
height:
|
|
64
|
+
boxSizing: 'border-box',
|
|
65
|
+
width: '100%',
|
|
66
|
+
height: '130px'
|
|
67
67
|
}),
|
|
68
68
|
img: inlineStyle({
|
|
69
|
-
borderRadius:
|
|
70
|
-
maxWidth:
|
|
71
|
-
height:
|
|
69
|
+
borderRadius: '0px 12px 12px 0px',
|
|
70
|
+
maxWidth: '40%',
|
|
71
|
+
height: '128px', // container.height - 2px
|
|
72
72
|
flexShrink: 0,
|
|
73
|
-
objectFit:
|
|
74
|
-
overflow:
|
|
73
|
+
objectFit: 'contain',
|
|
74
|
+
overflow: 'hidden'
|
|
75
75
|
}),
|
|
76
76
|
texts: inlineStyle({
|
|
77
|
-
flex:
|
|
78
|
-
minWidth:
|
|
77
|
+
flex: '1 1 0%',
|
|
78
|
+
minWidth: '0' // ellipsisを有効にするために必要
|
|
79
79
|
}),
|
|
80
80
|
title: inlineStyle({
|
|
81
81
|
...ellipsisStyle(2),
|
|
82
82
|
opacity: 1,
|
|
83
|
-
fontSize:
|
|
84
|
-
lineHeight:
|
|
85
|
-
margin:
|
|
86
|
-
fontWeight:
|
|
83
|
+
fontSize: '16px',
|
|
84
|
+
lineHeight: '22px',
|
|
85
|
+
margin: '0 16px 8px 16px',
|
|
86
|
+
fontWeight: 'bold'
|
|
87
87
|
}),
|
|
88
88
|
domain: inlineStyle({
|
|
89
89
|
...ellipsisStyle(1),
|
|
90
90
|
opacity: 1,
|
|
91
|
-
fontSize:
|
|
92
|
-
lineHeight:
|
|
93
|
-
margin:
|
|
94
|
-
textDecoration:
|
|
91
|
+
fontSize: '12px',
|
|
92
|
+
lineHeight: '16px',
|
|
93
|
+
margin: '8px 16px 8px 16px',
|
|
94
|
+
textDecoration: 'underline'
|
|
95
95
|
}),
|
|
96
96
|
description: inlineStyle({
|
|
97
97
|
...ellipsisStyle(2),
|
|
98
98
|
opacity: 0.8,
|
|
99
|
-
fontSize:
|
|
100
|
-
lineHeight:
|
|
101
|
-
margin:
|
|
102
|
-
})
|
|
99
|
+
fontSize: '12px',
|
|
100
|
+
lineHeight: '16px',
|
|
101
|
+
margin: '8px 16px 0px 16px'
|
|
102
|
+
})
|
|
103
103
|
});
|
|
104
104
|
/**
|
|
105
105
|
* @param prefix
|
|
@@ -111,5 +111,5 @@ export const classNames = (prefix) => ({
|
|
|
111
111
|
texts: `${prefix}__texts`,
|
|
112
112
|
title: `${prefix}__texts--title`,
|
|
113
113
|
domain: `${prefix}__texts--domain`,
|
|
114
|
-
description: `${prefix}__texts--desc
|
|
114
|
+
description: `${prefix}__texts--desc`
|
|
115
115
|
});
|
package/dist/assemble/url.js
CHANGED
package/dist/assemble/xhr.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Refactor: xmlhttprequest will be replaced later
|
|
2
2
|
// @ts-expect-error: xmlhttprequest has no types
|
|
3
|
-
import xhrForNode from
|
|
4
|
-
import { inBrowser, isString } from
|
|
3
|
+
import xhrForNode from 'xmlhttprequest';
|
|
4
|
+
import { inBrowser, isString } from '@luckrya/utility';
|
|
5
5
|
// TODO: Local File Cache
|
|
6
6
|
const cache = new Map();
|
|
7
7
|
const XHR = inBrowser ? window.XMLHttpRequest : xhrForNode.XMLHttpRequest;
|
|
@@ -15,8 +15,8 @@ export function sync(url) {
|
|
|
15
15
|
let result;
|
|
16
16
|
try {
|
|
17
17
|
const xhr = new XHR();
|
|
18
|
-
xhr.open(
|
|
19
|
-
xhr.setRequestHeader(
|
|
18
|
+
xhr.open('GET', url, false);
|
|
19
|
+
xhr.setRequestHeader('Content-Type', 'text/html');
|
|
20
20
|
xhr.send();
|
|
21
21
|
if (xhr.status === 200 && !!xhr.responseText) {
|
|
22
22
|
result = xhr.responseText;
|
|
@@ -24,9 +24,7 @@ export function sync(url) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
catch (err) {
|
|
27
|
-
console.error(`【XHR Error】:${err instanceof Error
|
|
28
|
-
? err.message
|
|
29
|
-
: "get remote URL resource exception!"}`);
|
|
27
|
+
console.error(`【XHR Error】:${err instanceof Error ? err.message : 'get remote URL resource exception!'}`);
|
|
30
28
|
}
|
|
31
29
|
return result;
|
|
32
30
|
}
|
|
@@ -40,12 +38,10 @@ export function async(url) {
|
|
|
40
38
|
if (cache.has(url))
|
|
41
39
|
return resolve(cache.get(url));
|
|
42
40
|
const xhr = new XHR();
|
|
43
|
-
xhr.open(
|
|
44
|
-
xhr.setRequestHeader(
|
|
41
|
+
xhr.open('GET', url, false);
|
|
42
|
+
xhr.setRequestHeader('Content-Type', 'text/html');
|
|
45
43
|
xhr.onreadystatechange = function () {
|
|
46
|
-
if (xhr.readyState === 4 &&
|
|
47
|
-
xhr.status === 200 &&
|
|
48
|
-
isString(xhr.responseText)) {
|
|
44
|
+
if (xhr.readyState === 4 && xhr.status === 200 && isString(xhr.responseText)) {
|
|
49
45
|
cache.set(url, xhr.responseText);
|
|
50
46
|
resolve(xhr.responseText);
|
|
51
47
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from './api';
|
|
2
|
+
export * from './link-to-card-plugin';
|
|
3
|
+
export * from './types';
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { isFunction } from
|
|
2
|
-
import { getUrlMetadata, generateCardDomFragment } from
|
|
1
|
+
import { isFunction } from '@luckrya/utility';
|
|
2
|
+
import { getUrlMetadata, generateCardDomFragment } from './assemble';
|
|
3
3
|
/**
|
|
4
4
|
* @param md
|
|
5
5
|
* @param pluginOptions
|
|
6
6
|
*/
|
|
7
7
|
export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
8
8
|
function parseCardLinkHref(href) {
|
|
9
|
-
const tagRegexp = new RegExp(`^(${
|
|
9
|
+
const tagRegexp = new RegExp(`^(${'@'}:)([a-zA-Z0-9]+.*)`);
|
|
10
10
|
const match = href?.match(tagRegexp);
|
|
11
11
|
return {
|
|
12
12
|
isCardLink: !!match,
|
|
13
|
-
url: match?.[2]
|
|
13
|
+
url: match?.[2]
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
@@ -24,10 +24,10 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
24
24
|
const cardDomOptions = {
|
|
25
25
|
href: options.url,
|
|
26
26
|
linkTitle: joinLinkTitle(options.tokens),
|
|
27
|
-
target: pluginOptions.target ||
|
|
27
|
+
target: pluginOptions.target || '_blank',
|
|
28
28
|
classPrefix: pluginOptions.classPrefix,
|
|
29
29
|
borderColor: pluginOptions.borderColor,
|
|
30
|
-
bgColor: pluginOptions.bgColor
|
|
30
|
+
bgColor: pluginOptions.bgColor
|
|
31
31
|
};
|
|
32
32
|
return isFunction(pluginOptions.render)
|
|
33
33
|
? pluginOptions.render(urlMetadata, cardDomOptions)
|
|
@@ -42,12 +42,12 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
42
42
|
* @returns
|
|
43
43
|
*/
|
|
44
44
|
md.renderer.renderInline = (tokens, rootOptions, env) => {
|
|
45
|
-
let result =
|
|
45
|
+
let result = '';
|
|
46
46
|
for (let i = 0; i < tokens.length; i++) {
|
|
47
47
|
const currentToken = tokens[i];
|
|
48
48
|
const ruleFunction = md.renderer.rules[currentToken.type];
|
|
49
49
|
if (currentToken.hidden) {
|
|
50
|
-
result +=
|
|
50
|
+
result += '';
|
|
51
51
|
}
|
|
52
52
|
else if (isFunction(ruleFunction)) {
|
|
53
53
|
result += ruleFunction(tokens, i, rootOptions, env, md.renderer);
|
|
@@ -69,8 +69,8 @@ export const linkToCardPlugin = (md, pluginOptions = {}) => {
|
|
|
69
69
|
*/
|
|
70
70
|
md.renderer.rules.link_open = (tokens, i, rootOptions, env, self) => {
|
|
71
71
|
const token = tokens[i];
|
|
72
|
-
const isLinkOpenToken = token.tag ===
|
|
73
|
-
const href = token.attrs?.filter((attr) => attr.includes(
|
|
72
|
+
const isLinkOpenToken = token.tag === 'a' && token.type === 'link_open';
|
|
73
|
+
const href = token.attrs?.filter((attr) => attr.includes('href'))[0]?.[1];
|
|
74
74
|
const { url, isCardLink } = parseCardLinkHref(href);
|
|
75
75
|
if (isLinkOpenToken && isCardLink && url) {
|
|
76
76
|
const card = assembleCardTpl({ url, tokens, i });
|
|
@@ -100,8 +100,8 @@ function joinLinkTitle(tokens) {
|
|
|
100
100
|
.map(({ hidden, content }) => {
|
|
101
101
|
if (hidden)
|
|
102
102
|
return content;
|
|
103
|
-
return
|
|
103
|
+
return '';
|
|
104
104
|
})
|
|
105
105
|
.filter(Boolean)
|
|
106
|
-
.join(
|
|
106
|
+
.join('');
|
|
107
107
|
}
|
package/package.json
CHANGED
|
@@ -69,11 +69,11 @@
|
|
|
69
69
|
"clean": "rm -rf dist types",
|
|
70
70
|
"dev": "rollup -c -w",
|
|
71
71
|
"docs": "yarn typedoc",
|
|
72
|
-
"format": "yarn prettier --write src
|
|
72
|
+
"format": "yarn prettier --config .vscode/.prettierrc.json --write .config/*.json .github .vscode src *.json && rm -rf node_modules",
|
|
73
73
|
"lint": "yarn eslint --config .vscode/eslint.config.ts src/**/*",
|
|
74
74
|
"type:dts": "tsc --emitDeclarationOnly"
|
|
75
75
|
},
|
|
76
76
|
"type": "module",
|
|
77
77
|
"types": "./types/index.d.ts",
|
|
78
|
-
"version": "1.1.
|
|
78
|
+
"version": "1.1.3"
|
|
79
79
|
}
|
package/types/api.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { UrlMetadata, CardDomRenderOptions } from
|
|
1
|
+
import type { UrlMetadata, CardDomRenderOptions } from './types';
|
|
2
2
|
interface CardResponse {
|
|
3
3
|
url: string;
|
|
4
4
|
data: UrlMetadata;
|
|
5
|
-
options: Omit<CardDomRenderOptions,
|
|
5
|
+
options: Omit<CardDomRenderOptions, 'href'>;
|
|
6
6
|
dom: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
@@ -10,5 +10,5 @@ interface CardResponse {
|
|
|
10
10
|
* @param options
|
|
11
11
|
* @returns
|
|
12
12
|
*/
|
|
13
|
-
export declare function generateCard(url: string, options: Omit<CardDomRenderOptions,
|
|
13
|
+
export declare function generateCard(url: string, options: Omit<CardDomRenderOptions, 'href'>): Promise<CardResponse>;
|
|
14
14
|
export {};
|
package/types/assemble/html.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * as xhr from
|
|
1
|
+
export * from './metadata';
|
|
2
|
+
export * from './html';
|
|
3
|
+
export * from './parser';
|
|
4
|
+
export * as xhr from './xhr';
|
package/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from './api';
|
|
2
|
+
export * from './link-to-card-plugin';
|
|
3
|
+
export * from './types';
|
package/types/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type MarkdownIt from
|
|
1
|
+
import type MarkdownIt from 'markdown-it';
|
|
2
2
|
export type LinkToCardPlugin = MarkdownIt.PluginWithOptions<LinkToCardPluginOptions>;
|
|
3
3
|
export interface LinkToCardPluginOptions {
|
|
4
4
|
target?: ATarget;
|
|
@@ -13,7 +13,7 @@ export interface UrlMetadata {
|
|
|
13
13
|
logo?: string;
|
|
14
14
|
[key: string]: unknown;
|
|
15
15
|
}
|
|
16
|
-
export type ATarget =
|
|
16
|
+
export type ATarget = '_self' | '_blank' | '_top' | '_parent';
|
|
17
17
|
export interface CardDomRenderOptions {
|
|
18
18
|
href: string;
|
|
19
19
|
linkTitle: string;
|