|
| 1 | +const { path } = require('@vuepress/shared-utils'); |
| 2 | + |
| 3 | +module.exports = (options = {}, context) => ({ |
| 4 | + extendPageData($page) { |
| 5 | + const { |
| 6 | + frontmatter, |
| 7 | + path |
| 8 | + } = $page; |
| 9 | + |
| 10 | + let root_url = options.root_url || ""; |
| 11 | + if(frontmatter.root_url){ |
| 12 | + root_url = frontmatter.root_url |
| 13 | + } |
| 14 | + const full_url = root_url + path; |
| 15 | + |
| 16 | + const is_duplicate_og = property => has_property(frontmatter, property); |
| 17 | + const is_duplicate_tw = name => has_name(frontmatter, name); |
| 18 | + const is_duplicate_ite = ite => has_itemprop(frontmatter, ite); |
| 19 | + |
| 20 | + const push_og = (property, content) => frontmatter.meta.push(og_template(property, content)); |
| 21 | + const push_twit = (name, content) =>frontmatter.meta.push(twitter_template(name, content)); |
| 22 | + |
| 23 | + const image_seo = (options = {}, frontmatter) => { |
| 24 | + const { |
| 25 | + default_image, |
| 26 | + default_image_type, |
| 27 | + default_image_width, |
| 28 | + default_image_height, |
| 29 | + default_image_alt |
| 30 | + } = options; |
| 31 | + |
| 32 | + const { |
| 33 | + image, |
| 34 | + image_type, |
| 35 | + image_width, |
| 36 | + image_height, |
| 37 | + image_alt |
| 38 | + } = frontmatter; |
| 39 | + |
| 40 | + let default_image_full_path; |
| 41 | + if (default_image) |
| 42 | + default_image_full_path = root_url + default_image; |
| 43 | + |
| 44 | + // Default |
| 45 | + if (!is_duplicate_og('og:image') && !image) { |
| 46 | + const push_og_image_default = { |
| 47 | + 'og:image': default_image_full_path, |
| 48 | + 'og:image:type': default_image_type, |
| 49 | + 'og:image:width': default_image_width, |
| 50 | + 'og:image:height': default_image_height, |
| 51 | + 'og:image:alt': default_image_alt |
| 52 | + }; |
| 53 | + |
| 54 | + Object.keys(push_og_image_default).forEach((property)=>{ |
| 55 | + if (!is_duplicate_og(property) && push_og_image_default[property]) |
| 56 | + push_og(property, push_og_image_default[property]) |
| 57 | + }) |
| 58 | + |
| 59 | + if (!is_duplicate_tw('twitter:image') && !image) // case. image empty |
| 60 | + push_twit('twitter:image', default_image_full_path); |
| 61 | + } |
| 62 | + |
| 63 | + // frontmatter |
| 64 | + if (image) { |
| 65 | + const push_og_image_front = { |
| 66 | + 'og:image': image, |
| 67 | + 'og:image:type': image_type, |
| 68 | + 'og:image:width': image_width, |
| 69 | + 'og:image:height': image_height, |
| 70 | + 'og:image:alt': image_alt |
| 71 | + } |
| 72 | + Object.keys(push_og_image_front).forEach((property)=>{ |
| 73 | + if (!is_duplicate_og(property)) push_og(property, push_og_image_front[property]); |
| 74 | + }) |
| 75 | + |
| 76 | + if (!is_duplicate_tw('twitter:image')) push_twit('twitter:image', image) |
| 77 | + if (!is_duplicate_ite( 'image')) |
| 78 | + frontmatter.meta.push(itemprop_template('image', image)) |
| 79 | + } |
| 80 | + }; |
| 81 | + |
| 82 | + |
| 83 | + const description_seo = () => { |
| 84 | + const { |
| 85 | + description |
| 86 | + } = frontmatter |
| 87 | + let meta_description = find_meta_description(frontmatter); |
| 88 | + |
| 89 | + if (description) { |
| 90 | + console.log('fr') |
| 91 | + if (!is_duplicate_og('og:description')) |
| 92 | + push_og('og:description', description); |
| 93 | + if (!is_duplicate_tw( 'twitter:description')) |
| 94 | + push_twit('twitter:description', description); |
| 95 | + if (!meta_description) |
| 96 | + frontmatter.meta.push({'name': 'description', 'content': description}); |
| 97 | + if (!is_duplicate_ite( 'description')) |
| 98 | + frontmatter.meta.push(itemprop_template('description', description)) |
| 99 | + } |
| 100 | + meta_description = find_meta_description(frontmatter); |
| 101 | + |
| 102 | + if (meta_description) { |
| 103 | + console.log('meta') |
| 104 | + if (!is_duplicate_og('og:description')) { |
| 105 | + console.log("og") |
| 106 | + push_og('og:description', meta_description); |
| 107 | + } |
| 108 | + if (!is_duplicate_tw('twitter:description')) |
| 109 | + push_twit('twitter:description', meta_description); |
| 110 | + if (!is_duplicate_ite( 'description')) |
| 111 | + frontmatter.meta.push(itemprop_template('description', meta_description)) |
| 112 | + } |
| 113 | + }; |
| 114 | + |
| 115 | + const url_seo = () => { |
| 116 | + if (!is_duplicate_og('og:url')) |
| 117 | + push_og('og:url', full_url); |
| 118 | + if (!has_name(frontmatter, 'twitter:url')) |
| 119 | + push_twit('twitter:url', full_url) |
| 120 | + }; |
| 121 | + |
| 122 | + const title_seo = () => { |
| 123 | + const {title} = $page |
| 124 | + if(frontmatter.title){ |
| 125 | + if (!is_duplicate_og('og:title')) |
| 126 | + push_og('og:title', frontmatter.title); |
| 127 | + if (!is_duplicate_tw('twitter:title')) |
| 128 | + push_twit('twitter:title', frontmatter.title); |
| 129 | + if (!is_duplicate_ite('name')) |
| 130 | + frontmatter.meta.push(itemprop_template('name', frontmatter.title)) |
| 131 | + return |
| 132 | + } |
| 133 | + |
| 134 | + if (!is_duplicate_og('og:title')) |
| 135 | + push_og('og:title', title); |
| 136 | + if (!is_duplicate_tw('twitter:title')) |
| 137 | + push_twit('twitter:title', title); |
| 138 | + if (!is_duplicate_ite('name')) |
| 139 | + frontmatter.meta.push(itemprop_template('name', title)) |
| 140 | + }; |
| 141 | + |
| 142 | + const twitter_creator_seo = () => { |
| 143 | + const {default_twitter_creator}=options |
| 144 | + const {twitter_creator} = frontmatter |
| 145 | + let creator; |
| 146 | + if (is_duplicate_tw('twitter:creator')) return |
| 147 | + |
| 148 | + if (twitter_creator) { |
| 149 | + if(!twitter_creator.includes("@")){ |
| 150 | + creator = "@"+twitter_creator |
| 151 | + }else{ |
| 152 | + creator = twitter_creator |
| 153 | + } |
| 154 | + push_twit('twitter:creator', creator); |
| 155 | + } |
| 156 | + else if (default_twitter_creator) { |
| 157 | + if(!twitter_creator.includes("@")) { |
| 158 | + creator = "@"+default_twitter_creator |
| 159 | + }else{ |
| 160 | + creator = default_twitter_creator |
| 161 | + } |
| 162 | + push_twit('twitter:creator', creator) |
| 163 | + } |
| 164 | + }; |
| 165 | + |
| 166 | + const og_type_seo = () => { |
| 167 | + const {og_type} = frontmatter |
| 168 | + let default_og_type = options.default_og_type || "article"; |
| 169 | + |
| 170 | + if (is_duplicate_og('og:type')) return |
| 171 | + |
| 172 | + if (og_type) |
| 173 | + push_og('og:type', og_type); |
| 174 | + else |
| 175 | + push_og('og:type', default_og_type) |
| 176 | + }; |
| 177 | + |
| 178 | + const twitter_card_seo = () => { |
| 179 | + let default_twitter_card = options.default_twitter_card || "summary"; |
| 180 | + const {twitter_card} = frontmatter |
| 181 | + |
| 182 | + if (!is_duplicate_tw('twitter:card') && twitter_card) |
| 183 | + push_twit('twitter:card', twitter_card); |
| 184 | + if (!is_duplicate_tw('twitter:card')) |
| 185 | + push_twit('twitter:card', default_twitter_card) |
| 186 | + }; |
| 187 | + |
| 188 | + const site_name_seo = () => { |
| 189 | + const {default_site_name} = options |
| 190 | + const {site_name} = frontmatter |
| 191 | + |
| 192 | + if (!is_duplicate_og('og:site_name') && site_name) |
| 193 | + push_og('og:site_name', site_name); |
| 194 | + if (!is_duplicate_og('og:site_name') && default_site_name) |
| 195 | + push_og('og:site_name', default_site_name) |
| 196 | + }; |
| 197 | + |
| 198 | + const twitter_site_seo = () => { |
| 199 | + const {default_twitter_site} = options |
| 200 | + const {twitter_site} = frontmatter |
| 201 | + let sit; |
| 202 | + |
| 203 | + if (!is_duplicate_tw('twitter:site') && twitter_site) |
| 204 | + if(!twitter_site.includes("@")){ |
| 205 | + sit = "@"+twitter_site |
| 206 | + }else{ |
| 207 | + sit = twitter_site |
| 208 | + } |
| 209 | + push_twit('twitter:site', sit); |
| 210 | + if (!is_duplicate_tw('twitter:site') && default_twitter_site) |
| 211 | + if(!twitter_site.includes("@")){ |
| 212 | + sit = "@"+default_twitter_site |
| 213 | + }else{ |
| 214 | + sit = default_twitter_site |
| 215 | + } |
| 216 | + push_twit('twitter:site', sit) |
| 217 | + }; |
| 218 | + |
| 219 | + if (!exists_meta(frontmatter)) frontmatter.meta = []; |
| 220 | + /* IMAGE SEO */ |
| 221 | + image_seo(options, frontmatter); |
| 222 | + /* DESCRIPTION SEO */ |
| 223 | + description_seo(); |
| 224 | + /* URL SEO */ |
| 225 | + url_seo(); |
| 226 | + /* TITLE SEO */ |
| 227 | + title_seo(); |
| 228 | + /* OG TYPE SEO */ |
| 229 | + og_type_seo(); |
| 230 | + /* TWITTER CARD SEO */ |
| 231 | + twitter_card_seo(); |
| 232 | + /* SITE NAME SEO */ |
| 233 | + site_name_seo(); |
| 234 | + /* TWITTER SITE SEO */ |
| 235 | + twitter_site_seo(); |
| 236 | + /* TWITTER CREATOR SEO */ |
| 237 | + twitter_creator_seo(); |
| 238 | + } |
| 239 | +}); |
| 240 | + |
| 241 | +const find_meta_description = frontmatter => { |
| 242 | + let flag = false; |
| 243 | + let description = ""; |
| 244 | + |
| 245 | + for (const elem of frontmatter.meta) if (elem.hasOwnProperty('name') && elem.name === 'description') { |
| 246 | + flag = true; |
| 247 | + description = elem.content |
| 248 | + } |
| 249 | + |
| 250 | + if(flag) return description |
| 251 | + return flag |
| 252 | +}; |
| 253 | + |
| 254 | +const exists_meta = frontmatter => frontmatter.meta !== undefined; |
| 255 | + |
| 256 | +const has_property = (frontmatter, property_name) => { |
| 257 | + let flag = false; |
| 258 | + frontmatter.meta.forEach(elem => { |
| 259 | + if (elem.hasOwnProperty('property') && elem.property === property_name) flag = true; |
| 260 | + }) |
| 261 | + return flag |
| 262 | +}; |
| 263 | + |
| 264 | +const has_name = (frontmatter, name) => { |
| 265 | + let flag = false; |
| 266 | + frontmatter.meta.forEach(elem => { |
| 267 | + if (elem.hasOwnProperty('name') && elem.name === name) flag = true; |
| 268 | + }) |
| 269 | + return flag |
| 270 | +}; |
| 271 | +const has_itemprop = (frontmatter, itemprop) => { |
| 272 | + let flag = false; |
| 273 | + frontmatter.meta.forEach(elem => { |
| 274 | + if (elem.hasOwnProperty('itemprop') && elem.itemprop === itemprop) flag = true; |
| 275 | + }); |
| 276 | + return flag |
| 277 | +}; |
| 278 | + |
| 279 | +const og_template = (property, content) => ({ |
| 280 | + 'property': property, |
| 281 | + 'content': content |
| 282 | +}); |
| 283 | + |
| 284 | +const twitter_template = (name, content) => ({ |
| 285 | + 'name': name, |
| 286 | + 'content': content |
| 287 | +}); |
| 288 | + |
| 289 | +const itemprop_template = (itemprop, content) => ({ |
| 290 | + 'itemprop': itemprop, |
| 291 | + 'content': content |
| 292 | +}); |
0 commit comments