From 18234598687f7e348c769d66f1ac88c091cafcdd Mon Sep 17 00:00:00 2001 From: taichunmin Date: Fri, 18 Sep 2020 12:42:39 +0800 Subject: [PATCH] fix: change meta tags merge function #2614 --- .../__tests__/root-mixins/updateMeta.spec.js | 100 ++++++++++++++++++ .../core/lib/client/root-mixins/updateMeta.js | 19 ++-- 2 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 packages/@vuepress/core/lib/client/__tests__/root-mixins/updateMeta.spec.js diff --git a/packages/@vuepress/core/lib/client/__tests__/root-mixins/updateMeta.spec.js b/packages/@vuepress/core/lib/client/__tests__/root-mixins/updateMeta.spec.js new file mode 100644 index 0000000000..d0ce17a69a --- /dev/null +++ b/packages/@vuepress/core/lib/client/__tests__/root-mixins/updateMeta.spec.js @@ -0,0 +1,100 @@ +import updateMeta from '../../root-mixins/updateMeta' + +describe('getMergedMetaTags', () => { + function metaFaker (pageMeta = null, siteMeta = []) { + return { + $page: { + frontmatter: { meta: pageMeta } + }, + $description: '$description', + siteMeta: siteMeta + } + } + + test('empty', () => { + const me = metaFaker() + const actual = updateMeta.methods.getMergedMetaTags.call(me) + expect(actual).toEqual([ + { name: 'description', content: '$description' } + ]) + }) + + test('description in pageMeta, $description and siteMeta should use pageMeta', () => { + const me = metaFaker([ + { name: 'description', content: 'pageMeta' } + ], [ + { name: 'description', content: 'siteMeta' } + ]) + const actual = updateMeta.methods.getMergedMetaTags.call(me) + expect(actual).toEqual([ + { name: 'description', content: 'pageMeta' } + ]) + }) + + test('description in $description and siteMeta should use $description', () => { + const me = metaFaker(null, [ + { name: 'description', content: 'siteMeta' } + ]) + const actual = updateMeta.methods.getMergedMetaTags.call(me) + expect(actual).toEqual([ + { name: 'description', content: '$description' } + ]) + }) + + test('allow multiple article:tag', () => { + const me = metaFaker([ + { property: 'article:tag', content: 'tag1' }, + { property: 'article:tag', content: 'tag2' }, + { property: 'article:tag', content: 'tag3' } + ], []) + const actual = updateMeta.methods.getMergedMetaTags.call(me) + expect(actual).toEqual([ + { property: 'article:tag', content: 'tag1' }, + { property: 'article:tag', content: 'tag2' }, + { property: 'article:tag', content: 'tag3' }, + { name: 'description', content: '$description' } + ]) + }) + + test('pageMeta order should not be changed', () => { + const me = metaFaker([ + { property: 'og:image', content: 'https://example.com/rock.jpg' }, + { property: 'og:image:width', content: '300' }, + { property: 'og:image:height', content: '300' }, + { property: 'og:image', content: 'https://example.com/rock2.jpg' }, + { property: 'og:image', content: 'https://example.com/rock3.jpg' }, + { property: 'og:image:height', content: '1000' } + ], []) + const actual = updateMeta.methods.getMergedMetaTags.call(me) + expect(actual).toEqual([ + { property: 'og:image', content: 'https://example.com/rock.jpg' }, + { property: 'og:image:width', content: '300' }, + { property: 'og:image:height', content: '300' }, + { property: 'og:image', content: 'https://example.com/rock2.jpg' }, + { property: 'og:image', content: 'https://example.com/rock3.jpg' }, + { property: 'og:image:height', content: '1000' }, + { name: 'description', content: '$description' } + ]) + }) + + test('siteMeta with same meta identifier of pageMeta should be ignore', () => { + const me = metaFaker([ + { property: 'og:image', content: 'https://example.com/rock2.jpg' }, + { property: 'og:image:width', content: '300' }, + { property: 'og:image:height', content: '300' } + ], [ + { property: 'og:image', content: 'https://example.com/rock1.jpg' }, + { property: 'og:image:width', content: '100' }, + { property: 'og:image:height', content: '100' }, + { property: 'og:site_name', content: 'siteMeta' } + ]) + const actual = updateMeta.methods.getMergedMetaTags.call(me) + expect(actual).toEqual([ + { property: 'og:image', content: 'https://example.com/rock2.jpg' }, + { property: 'og:image:width', content: '300' }, + { property: 'og:image:height', content: '300' }, + { name: 'description', content: '$description' }, + { property: 'og:site_name', content: 'siteMeta' } + ]) + }) +}) diff --git a/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js b/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js index 485f544d38..7f00dec5d3 100644 --- a/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js +++ b/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js @@ -1,4 +1,4 @@ -import unionBy from 'lodash/unionBy' +import transform from 'lodash/transform' export default { // created will be called on both client and ssr @@ -34,11 +34,18 @@ export default { }, getMergedMetaTags () { - const pageMeta = this.$page.frontmatter.meta || [] - // pageMetaTags have higher priority than siteMetaTags - // description needs special attention as it has too many entries - return unionBy([{ name: 'description', content: this.$description }], - pageMeta, this.siteMeta, metaIdentifier) + const exists = {} + return transform([ + this.$page.frontmatter.meta || [], // page meta + [{ name: 'description', content: this.$description }], // meta description + this.siteMeta // site meta + ], (merged, meta) => { + const filtered = meta.filter(tag => !exists[metaIdentifier(tag)]) + merged.push(...filtered) + filtered.forEach(tag => { + exists[metaIdentifier(tag)] = 1 + }) + }, []) } },