Skip to content

Commit 0f74899

Browse files
committed
Updated for VuePress v2.0.0-beta.26
1 parent a2833e1 commit 0f74899

3 files changed

Lines changed: 154 additions & 96 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.code-workspace

index.js

Lines changed: 148 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,154 @@
1+
/**
2+
* Frontmatter looks like
3+
ogType: website # default is 'article'
4+
ogTitle: OG/TWITTER TITLE HERE
5+
title: PAGE TITLE HERE
6+
description: A description of your page here.
7+
date: 2021-10-30T04:20:42.00Z
8+
image: /images/og_image_homepage.jpg
9+
*/
10+
111
module.exports = (options = {}, context) => {
2-
options = Object.assign(defaultOptions, options)
3-
4-
return {
5-
extendPageData ($page) {
6-
const $site = context.siteConfig
7-
8-
// In Vuepress core, permalinks are built after enhancers.
9-
const pageClone = Object.assign(Object.create(Object.getPrototypeOf($page)), $page)
10-
pageClone.buildPermalink()
11-
12-
let meta = $page.frontmatter.meta || []
13-
let addMeta = getAddMeta(meta)
14-
let optionArgs = [ $page, $site, pageClone.path ]
15-
let metaContext = {
16-
$page, $site,
17-
siteTitle: options.siteTitle(...optionArgs),
18-
title: options.title(...optionArgs),
19-
description: options.description(...optionArgs),
20-
author: options.author(...optionArgs),
21-
tags: options.tags(...optionArgs),
22-
twitterCard: options.twitterCard(...optionArgs),
23-
type: options.type(...optionArgs),
24-
url: options.url(...optionArgs),
25-
image: options.image(...optionArgs),
26-
publishedAt: options.publishedAt(...optionArgs),
27-
modifiedAt: options.modifiedAt(...optionArgs),
28-
}
29-
30-
options.defaultMeta(addMeta, metaContext)
31-
options.customMeta(addMeta, metaContext)
32-
$page.frontmatter.meta = meta
33-
}
34-
}
35-
}
12+
options = Object.assign(defaultOptions, options);
3613

37-
function getAddMeta(meta) {
38-
return (name, content, attribute = null) => {
39-
if (! content) return
40-
if (! attribute) attribute = ['article:', 'og:'].some(type => name.startsWith(type)) ? 'property' : 'name'
41-
meta.push({ [attribute]: name, content })
42-
}
14+
return {
15+
name: "vuepress-seo-plugin",
16+
17+
extendsPageData: ($page) => {
18+
let $site = { ...context.siteData, ...context.options };
19+
let head = $page.frontmatter.head || [];
20+
let addMeta = getAddMeta(head);
21+
let optionArgs = [$page, $site, $page.path];
22+
23+
// add cannonical
24+
addCanonical(head, $page, $site);
25+
26+
let metaContext = {
27+
$page,
28+
$site,
29+
siteTitle: options.siteTitle(...optionArgs),
30+
title: options.title(...optionArgs),
31+
description: options.description(...optionArgs),
32+
author: options.author(...optionArgs),
33+
tags: options.tags(...optionArgs),
34+
twitterCard: options.twitterCard(...optionArgs),
35+
type: options.type(...optionArgs),
36+
url: options.url(...optionArgs),
37+
image: options.image(...optionArgs),
38+
publishedAt: options.publishedAt(...optionArgs),
39+
modifiedAt: options.modifiedAt(...optionArgs),
40+
};
41+
42+
options.defaultMeta(addMeta, metaContext);
43+
options.customMeta(addMeta, metaContext);
44+
$page.frontmatter.head = head;
45+
},
46+
};
47+
};
48+
49+
function getAddMeta(head) {
50+
return (name, content, attribute = null) => {
51+
// check if meta tag already exists
52+
const isExists =
53+
head.findIndex((item) =>
54+
// if any of hid, name or property fields are same as 'name'
55+
[item[1].hid, item[1].name, item[1].property].includes(name)
56+
) != -1;
57+
// skip if it does
58+
if (isExists) return;
59+
60+
if (!content) return;
61+
if (!attribute)
62+
attribute = ["article:", "og:"].some((type) => name.startsWith(type))
63+
? "property"
64+
: "name";
65+
66+
// push it to 'head' array
67+
head.push([
68+
"head",
69+
{
70+
hid: name,
71+
[attribute]: name,
72+
content: content,
73+
},
74+
]);
75+
};
4376
}
4477

45-
const defaultOptions = {
46-
siteTitle: (_, $site) => $site.title,
47-
title: $page => $page.title,
48-
description: $page => $page.frontmatter.description,
49-
author: (_, $site) => $site.themeConfig.author,
50-
tags: $page => $page.frontmatter.tags,
51-
twitterCard: _ => 'summary_large_image',
52-
type: $page => ['articles', 'posts', 'blog'].some(folder => $page.regularPath.startsWith('/' + folder)) ? 'article' : 'website',
53-
url: (_, $site, path) => ($site.themeConfig.domain || '') + path,
54-
image: ($page, $site) => {
55-
if ($page.frontmatter.image) {
56-
return $site.themeConfig.domain &&
57-
!$page.frontmatter.image.startsWith('http')
58-
? $site.themeConfig.domain + $page.frontmatter.image
59-
: $page.frontmatter.image;
60-
}
61-
return '';
78+
// add cannonical tag
79+
function addCanonical(head, $page, $site) {
80+
// check if canonical tag exists already
81+
let isExists =
82+
head.findIndex((item) => {
83+
return item[1].rel == "canonical";
84+
}) != -1;
85+
86+
// if it does not, auto generate it
87+
if (!isExists)
88+
head.push([
89+
"link",
90+
{
91+
rel: "canonical",
92+
href: ($site.themeConfig.domain || "") + $page.path,
6293
},
63-
publishedAt: $page => $page.frontmatter.date && (new Date($page.frontmatter.date)).toISOString(),
64-
modifiedAt: $page => $page.lastUpdated && (new Date($page.lastUpdated)).toISOString(),
65-
customMeta: () => {},
66-
67-
defaultMeta(add, ctx) {
68-
const { author, tags } = ctx
69-
70-
// Basics.
71-
add('article:published_time', ctx.publishedAt)
72-
add('article:modified_time', ctx.modifiedAt)
73-
add('og:site_name', ctx.siteTitle)
74-
add('og:title', ctx.title)
75-
add('og:description', ctx.description)
76-
add('og:type', ctx.type)
77-
add('og:url', ctx.url)
78-
add('og:image', ctx.image)
79-
add('twitter:title', ctx.title)
80-
add('twitter:description', ctx.description)
81-
add('twitter:url', ctx.url)
82-
add('twitter:card', ctx.twitterCard)
83-
add('twitter:image', ctx.image)
84-
85-
// Author.
86-
if (author) {
87-
add('twitter:label1', 'Written by')
88-
add('twitter:data1', author.name)
89-
add('twitter:creator', author.twitter)
90-
}
91-
92-
// Tags.
93-
if (tags && Array.isArray(tags)) {
94-
add('twitter:label2', 'Filed under')
95-
add('twitter:data2', tags.join(', '))
96-
tags.forEach(tag => add('article:tag', tag))
97-
}
98-
},
94+
]);
9995
}
96+
97+
const defaultOptions = {
98+
siteTitle: (_, $site) => $site.title,
99+
title: ($page) =>
100+
$page.frontmatter.ogTitle || $page.frontmatter.title || $page.title,
101+
description: ($page) => $page.frontmatter.description,
102+
author: ($page) => $page.frontmatter.author,
103+
tags: ($page) => $page.frontmatter.tags,
104+
twitterCard: (_) => "summary_large_image",
105+
type: ($page) => $page.frontmatter.ogType || "article",
106+
url: (_, $site, path) => ($site.themeConfig.domain || "") + path,
107+
image: ($page, $site) => {
108+
if ($page.frontmatter.image) {
109+
return $site.themeConfig.domain &&
110+
!$page.frontmatter.image.startsWith("http")
111+
? $site.themeConfig.domain + $page.frontmatter.image
112+
: $page.frontmatter.image;
113+
}
114+
return "";
115+
},
116+
publishedAt: ($page) =>
117+
$page.frontmatter.date && new Date($page.frontmatter.date).toISOString(),
118+
modifiedAt: ($page) =>
119+
$page.lastUpdated && new Date($page.lastUpdated).toISOString(),
120+
customMeta: () => {},
121+
122+
defaultMeta(add, ctx) {
123+
const { author, tags } = ctx;
124+
125+
// Basics.
126+
add("article:published_time", ctx.publishedAt);
127+
add("article:modified_time", ctx.modifiedAt);
128+
add("og:site_name", ctx.siteTitle);
129+
add("og:title", ctx.title);
130+
add("og:description", ctx.description);
131+
add("og:type", ctx.type);
132+
add("og:url", ctx.url);
133+
add("og:image", ctx.image);
134+
add("twitter:title", ctx.title);
135+
add("twitter:description", ctx.description);
136+
add("twitter:url", ctx.url);
137+
add("twitter:card", ctx.twitterCard);
138+
add("twitter:image", ctx.image);
139+
140+
// Author.
141+
if (author) {
142+
add("twitter:label1", "Written by");
143+
add("twitter:data1", author.name);
144+
add("twitter:creator", author.twitter);
145+
}
146+
147+
// Tags.
148+
if (tags && Array.isArray(tags)) {
149+
add("twitter:label2", "Filed under");
150+
add("twitter:data2", tags.join(", "));
151+
tags.forEach((tag) => add("article:tag", tag));
152+
}
153+
},
154+
};

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
{
22
"name": "vuepress-plugin-seo",
3-
"version": "0.1.4",
4-
"description": "Generate SEO friendly meta header for every page",
3+
"version": "0.2.0",
4+
"description": "Generate SEO friendly meta header for every page, VuePress v2",
55
"main": "index.js",
66
"keywords": [
77
"vuepress",
88
"plugin",
9-
"seo"
9+
"seo",
10+
"meta",
11+
"headers"
1012
],
1113
"repository": {
1214
"type": "git",

0 commit comments

Comments
 (0)