UNPKG

7.14 kBJavaScriptView Raw
1const getTag = require("get-tag");
2
3module.exports = (eleventyConfig, pluginNamespace) => {
4 eleventyConfig.namespace(pluginNamespace, () => {
5 eleventyConfig.addShortcode("metagen", (data) => {
6
7 function comments(data, key, commentGroup) {
8 return data.comments ? `${(data[key] ? `<!-- ${data[key]} -->` : `<!-- ${commentGroup} -->`)}` : "";
9 }
10
11 function getDnsTags(data, rel) {
12 if (typeof data == "string") {
13 return getTag("link", null, {rel: rel, href: data});
14 } else if (typeof data == "object" && typeof data.crawlers === "object" && data.constructor === Object) {
15 let tags = "";
16 data.forEach(link => tags += getTag("link", null, {rel: rel, href: link}));
17 return tags;
18 }
19 }
20
21 function handleDnsResolution(data) {
22 let tags = "";
23 if (data.preconnect) tags += getDnsTags(data.preconnect, "preconnect");
24 if (data.dns_prefetch) tags += getDnsTags(data.dns_prefetch, "dns-prefetch");
25 return tags;
26 }
27
28 function handleCustomCrawlers(data) {
29 if (data.crawlers && typeof data.crawlers === "object" && data.constructor === Object) {
30 let tags = "";
31 for (const key in data.crawlers) tags += getTag("meta", null, {name: key, content: data.crawlers[key] });
32 return tags;
33 }
34 }
35
36 function getStaticAssets(tagInfoList, asset) {
37 return tagInfoList
38 .filter(tagInfo => tagInfo[1])
39 .map(tagInfo => {
40 if (tagInfo[0] === `inline-${asset}`) {
41 return asset == "css" ? `\t${getTag("style", tagInfo[1])}` : `\t${getTag("script", tagInfo[1])}`;
42 } else {
43 return tagInfo[1].map(tagData => {
44 if (typeof tagData === "object") {
45 return `<script src="${tagData[0]}" ${tagData[1]}></script>`;
46 }
47 return asset == "css" ? getTag("link", null, {rel: "stylesheet", href: tagData }) : `<script src="${tagData}"></script>`;
48 }).join("\n\t");
49 }
50 });
51 }
52
53 if (data) {
54 let canonical, css, js, customTags = "";
55 const metadata = [
56 ["charset", getTag("meta", null, {charset: data.charset || "utf-8"})],
57 ["http-equiv", getTag("meta", null, { "http-equiv": "X-UA-Compatible", content: "IE=edge" })],
58 ["viewport", "width=device-width, initial-scale=1"],
59 ["dns", handleDnsResolution(data)],
60 ["mainTitle", getTag("title", data.title)],
61 ["author", data.name],
62 ["title", data.title],
63 ["description", data.desc],
64 ["robots", data.robots],
65 ["crawlers", handleCustomCrawlers(data)],
66 ["generator", data.generator]
67 ].filter(tagInfo => tagInfo && tagInfo[1]).map(tagInfo => {
68 if (["charset", "dns", "crawlers", "http-equiv", "mainTitle"].includes(tagInfo[0])) return tagInfo[1];
69 return getTag("meta", null, { name: tagInfo[0], content: tagInfo[1] });
70 });
71
72 const openGraph = [
73 ["comments", comments(data, "og-comment", "Open Graph")],
74 ["og:type", data.type || "website"],
75 ["og:url", data.url],
76 ["og:site_name", data.site_name],
77 ["og:video", data.og_video],
78 ["og:audio", data.og_audio],
79 ["og:determiner", data.og_determiner],
80 ["og:locale:alternate", data.og_alternate_locales],
81 ["og:locale", data.locale || "en_US"],
82 ["og:title", data.og_title || data.title],
83 ["og:description", data.og_desc || data.desc],
84 ["og:image", data.img],
85 ["og:image:alt", data.img_alt],
86 ["og:image:width", data.img_width],
87 ["og:image:height", data.img_height],
88 ["og:image:type", data.og_img_type],
89 ["og:image:secure_url", data.og_img_url]
90 ].filter(tagInfo => tagInfo[1]).map(tagInfo => {
91 if (tagInfo[0] == "og:locale:alternate") {
92 return tagInfo[1].map(locale => {
93 return getTag("meta", null, {property: tagInfo[0], content: locale });
94 }).join("\n\t");
95 }
96 return tagInfo[0] === "comments" ? tagInfo[1] : getTag("meta", null, { property: tagInfo[0], content: tagInfo[1] });
97 });
98
99 const twitterCard = [
100 ["comments", comments(data, "twitter-comment", "Twitter")],
101 ["twitter:card", data.twitter_card_type || 'summary'],
102 ["twitter:site", `@${data.twitter_handle}`],
103 data.twitter_card_type === "summary_large_image" ? ["twitter:creator", `@${data.creator_handle || data.twitter_handle}`] : "",
104 ["twitter:url", data.url],
105 ["twitter:title", data.twitter_title || data.title],
106 ["twitter:description", data.twitter_desc || data.desc],
107 ["twitter:image", data.img],
108 ["twitter:image:alt", data.img_alt]
109 ].filter(tagInfo => tagInfo[1]).map(tagInfo => {
110 return tagInfo[0] === "comments" ? tagInfo[1] : getTag("meta", null, { [data.attr_name || "name"]: tagInfo[0], content: tagInfo[1] });
111 });
112
113 if (data.url) canonical = getTag("link", null, {rel: "canonical", href: data.url });
114 if (data.css || data.inline_css) css = getStaticAssets([["css", data.css], ["inline-css", data.inline_css]], "css").join("\n");
115 if (data.js || data.inline_js) js = getStaticAssets([["js", data.js], ["inline-js", data.inline_js]], "js").join("\n");
116
117 if (data.custom) {
118 customTags = data.custom.map(item => {
119 if (item.length < 3) return;
120 if (item.length === 3) return getTag(item[0], item[1], item[2]);
121 return getTag(item[0], item[1], item[2], item[3]);
122 }).join("\n\t");
123 }
124
125 return [...metadata, ...openGraph, ...twitterCard, canonical, customTags, css, js].filter(Boolean).join("\n\t");
126 } else {
127 console.error("No data was added into the meta generator")
128 return "";
129 }
130 });
131 });
132};