-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathindex.js
154 lines (138 loc) · 4.41 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* Frontmatter looks like
ogType: website # default is 'article'
ogTitle: OG/TWITTER TITLE HERE
title: PAGE TITLE HERE
description: A description of your page here.
date: 2021-10-30T04:20:42.00Z
image: /images/og_image_homepage.jpg
*/
module.exports = (options = {}, context) => {
options = Object.assign(defaultOptions, options);
return {
name: "vuepress-seo-plugin",
extendsPageData: ($page) => {
let $site = { ...context.siteData, ...context.options };
let head = $page.frontmatter.head || [];
let addMeta = getAddMeta(head);
let optionArgs = [$page, $site, $page.path];
// add cannonical
addCanonical(head, $page, $site);
let metaContext = {
$page,
$site,
siteTitle: options.siteTitle(...optionArgs),
title: options.title(...optionArgs),
description: options.description(...optionArgs),
author: options.author(...optionArgs),
tags: options.tags(...optionArgs),
twitterCard: options.twitterCard(...optionArgs),
type: options.type(...optionArgs),
url: options.url(...optionArgs),
image: options.image(...optionArgs),
publishedAt: options.publishedAt(...optionArgs),
modifiedAt: options.modifiedAt(...optionArgs),
};
options.defaultMeta(addMeta, metaContext);
options.customMeta(addMeta, metaContext);
$page.frontmatter.head = head;
},
};
};
function getAddMeta(head) {
return (name, content, attribute = null) => {
// check if meta tag already exists
const isExists =
head.findIndex((item) =>
// if any of hid, name or property fields are same as 'name'
[item[1].hid, item[1].name, item[1].property].includes(name)
) != -1;
// skip if it does
if (isExists) return;
if (!content) return;
if (!attribute)
attribute = ["article:", "og:"].some((type) => name.startsWith(type))
? "property"
: "name";
// push it to 'head' array
head.push([
"meta",
{
hid: name,
[attribute]: name,
content: content,
},
]);
};
}
// add cannonical tag
function addCanonical(head, $page, $site) {
// check if canonical tag exists already
let isExists =
head.findIndex((item) => {
return item[1].rel == "canonical";
}) != -1;
// if it does not, auto generate it
if (!isExists)
head.push([
"link",
{
rel: "canonical",
href: ($site.themeConfig.domain || "") + $page.path,
},
]);
}
const defaultOptions = {
siteTitle: (_, $site) => $site.title,
title: ($page) =>
$page.frontmatter.ogTitle || $page.frontmatter.title || $page.title,
description: ($page) => $page.frontmatter.description,
author: ($page) => $page.frontmatter.author,
tags: ($page) => $page.frontmatter.tags,
twitterCard: (_) => "summary_large_image",
type: ($page) => $page.frontmatter.ogType || "article",
url: (_, $site, path) => ($site.themeConfig.domain || "") + path,
image: ($page, $site) => {
if ($page.frontmatter.image) {
return $site.themeConfig.domain &&
!$page.frontmatter.image.startsWith("http")
? $site.themeConfig.domain + $page.frontmatter.image
: $page.frontmatter.image;
}
return "";
},
publishedAt: ($page) =>
$page.frontmatter.date && new Date($page.frontmatter.date).toISOString(),
modifiedAt: ($page) =>
$page.lastUpdated && new Date($page.lastUpdated).toISOString(),
customMeta: () => {},
defaultMeta(add, ctx) {
const { author, tags } = ctx;
// Basics.
add("article:published_time", ctx.publishedAt);
add("article:modified_time", ctx.modifiedAt);
add("og:site_name", ctx.siteTitle);
add("og:title", ctx.title);
add("og:description", ctx.description);
add("og:type", ctx.type);
add("og:url", ctx.url);
add("og:image", ctx.image);
add("twitter:title", ctx.title);
add("twitter:description", ctx.description);
add("twitter:url", ctx.url);
add("twitter:card", ctx.twitterCard);
add("twitter:image", ctx.image);
// Author.
if (author) {
add("twitter:label1", "Written by");
add("twitter:data1", author.name);
add("twitter:creator", author.twitter);
}
// Tags.
if (tags && Array.isArray(tags)) {
add("twitter:label2", "Filed under");
add("twitter:data2", tags.join(", "));
tags.forEach((tag) => add("article:tag", tag));
}
},
};