mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-12 15:12:26 +03:00
Add meta templates
This commit is contained in:
@@ -458,6 +458,30 @@ Each item in the array maps to a newly-created `<meta>` element, where object pr
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
```
|
||||
|
||||
Since v1.5.0, you can now set up meta templates that work similar to the titleTemplate:
|
||||
|
||||
```js
|
||||
{
|
||||
metaInfo: {
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{
|
||||
'vmid': 'og:title',
|
||||
'property': 'og:title',
|
||||
'content': 'Test title',
|
||||
'template': chunk => `${chunk} - My page` //or as string template: '%s - My page'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<meta charset="utf-8">
|
||||
<meta name="og:title" property="og:title" content="Test title - My page">
|
||||
```
|
||||
|
||||
|
||||
#### `link` ([Object])
|
||||
|
||||
Each item in the array maps to a newly-created `<link>` element, where object properties map to attributes.
|
||||
|
||||
@@ -19,3 +19,6 @@ export const VUE_META_SERVER_RENDERED_ATTRIBUTE = 'data-vue-meta-server-rendered
|
||||
// that both have `vmid` of "description", then vue-meta will overwrite the
|
||||
// shallowest one with the deepest one.
|
||||
export const VUE_META_TAG_LIST_ID_KEY_NAME = 'vmid'
|
||||
|
||||
// This is the key name for possible meta templates
|
||||
export const VUE_META_TEMPLATE_KEY_NAME = 'template'
|
||||
|
||||
@@ -15,7 +15,7 @@ import deepmerge from 'deepmerge'
|
||||
* @return {Object} result - final aggregated result
|
||||
*/
|
||||
export default function getComponentOption (opts, result = {}) {
|
||||
const { component, option, deep, arrayMerge } = opts
|
||||
const { component, option, deep, arrayMerge, metaTemplateKeyName } = opts
|
||||
const { $options } = component
|
||||
|
||||
if (component._inactive) return result
|
||||
@@ -48,6 +48,22 @@ export default function getComponentOption (opts, result = {}) {
|
||||
}, result)
|
||||
})
|
||||
}
|
||||
if (metaTemplateKeyName && result.hasOwnProperty('meta')) {
|
||||
result.meta = Object.keys(result.meta).map(metaKey => {
|
||||
const metaObject = result.meta[metaKey]
|
||||
if (!metaObject.hasOwnProperty(metaTemplateKeyName) || !metaObject.hasOwnProperty('content') || typeof metaObject[metaTemplateKeyName] === 'undefined') {
|
||||
return result.meta[metaKey]
|
||||
}
|
||||
|
||||
const template = metaObject[metaTemplateKeyName]
|
||||
delete metaObject[metaTemplateKeyName]
|
||||
|
||||
if (template) {
|
||||
metaObject.content = typeof template === 'function' ? template(metaObject.content) : template.replace(/%s/g, metaObject.content)
|
||||
}
|
||||
|
||||
return metaObject
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ const escapeHTML = (str) => typeof window === 'undefined'
|
||||
.replace(/'/g, '\u0027')
|
||||
|
||||
export default function _getMetaInfo (options = {}) {
|
||||
const { keyName, tagIDKeyName } = options
|
||||
const { keyName, tagIDKeyName, metaTemplateKeyName } = options
|
||||
/**
|
||||
* Returns the correct meta info for the given component
|
||||
* (child components will overwrite parent meta info)
|
||||
@@ -52,6 +52,7 @@ export default function _getMetaInfo (options = {}) {
|
||||
component,
|
||||
option: keyName,
|
||||
deep: true,
|
||||
metaTemplateKeyName,
|
||||
arrayMerge (target, source) {
|
||||
// we concat the arrays without merging objects contained in,
|
||||
// but we check for a `vmid` property on each object in the array
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
VUE_META_KEY_NAME,
|
||||
VUE_META_ATTRIBUTE,
|
||||
VUE_META_SERVER_RENDERED_ATTRIBUTE,
|
||||
VUE_META_TAG_LIST_ID_KEY_NAME
|
||||
VUE_META_TAG_LIST_ID_KEY_NAME,
|
||||
VUE_META_TEMPLATE_KEY_NAME
|
||||
} from './constants'
|
||||
|
||||
// automatic install
|
||||
@@ -22,6 +23,7 @@ export default function VueMeta (Vue, options = {}) {
|
||||
// set some default options
|
||||
const defaultOptions = {
|
||||
keyName: VUE_META_KEY_NAME,
|
||||
metaTemplateKeyName: VUE_META_TEMPLATE_KEY_NAME,
|
||||
attribute: VUE_META_ATTRIBUTE,
|
||||
ssrAttribute: VUE_META_SERVER_RENDERED_ATTRIBUTE,
|
||||
tagIDKeyName: VUE_META_TAG_LIST_ID_KEY_NAME
|
||||
|
||||
+197
-6
@@ -1,10 +1,11 @@
|
||||
import Vue from 'vue'
|
||||
import _getMetaInfo from '../src/shared/getMetaInfo'
|
||||
import {
|
||||
VUE_META_KEY_NAME,
|
||||
VUE_META_ATTRIBUTE,
|
||||
VUE_META_KEY_NAME,
|
||||
VUE_META_SERVER_RENDERED_ATTRIBUTE,
|
||||
VUE_META_TAG_LIST_ID_KEY_NAME
|
||||
VUE_META_TAG_LIST_ID_KEY_NAME,
|
||||
VUE_META_TEMPLATE_KEY_NAME
|
||||
} from '../src/shared/constants'
|
||||
|
||||
// set some default options
|
||||
@@ -12,6 +13,7 @@ const defaultOptions = {
|
||||
keyName: VUE_META_KEY_NAME,
|
||||
attribute: VUE_META_ATTRIBUTE,
|
||||
ssrAttribute: VUE_META_SERVER_RENDERED_ATTRIBUTE,
|
||||
metaTemplateKeyName: VUE_META_TEMPLATE_KEY_NAME,
|
||||
tagIDKeyName: VUE_META_TAG_LIST_ID_KEY_NAME
|
||||
}
|
||||
|
||||
@@ -108,7 +110,7 @@ describe('getMetaInfo', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
titleTemplate: titleTemplate,
|
||||
titleTemplate,
|
||||
meta: [
|
||||
{ charset: 'utf-8' }
|
||||
]
|
||||
@@ -117,7 +119,7 @@ describe('getMetaInfo', () => {
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello Function World',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: titleTemplate,
|
||||
titleTemplate,
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
@@ -142,7 +144,7 @@ describe('getMetaInfo', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
titleTemplate: titleTemplate,
|
||||
titleTemplate,
|
||||
meta: [
|
||||
{ charset: 'utf-8' }
|
||||
]
|
||||
@@ -156,7 +158,7 @@ describe('getMetaInfo', () => {
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello Function World',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: titleTemplate,
|
||||
titleTemplate,
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
@@ -172,4 +174,193 @@ describe('getMetaInfo', () => {
|
||||
__dangerouslyDisableSanitizersByTagID: {}
|
||||
})
|
||||
})
|
||||
|
||||
it('properly uses string meta templates', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title',
|
||||
template: '%s - My page'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: '%s',
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title - My page'
|
||||
}
|
||||
],
|
||||
base: [],
|
||||
link: [],
|
||||
style: [],
|
||||
script: [],
|
||||
noscript: [],
|
||||
__dangerouslyDisableSanitizers: [],
|
||||
__dangerouslyDisableSanitizersByTagID: {}
|
||||
})
|
||||
})
|
||||
|
||||
it('properly uses function meta templates', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title',
|
||||
template: chunk => `${chunk} - My page`
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: '%s',
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title - My page'
|
||||
}
|
||||
],
|
||||
base: [],
|
||||
link: [],
|
||||
style: [],
|
||||
script: [],
|
||||
noscript: [],
|
||||
__dangerouslyDisableSanitizers: [],
|
||||
__dangerouslyDisableSanitizersByTagID: {}
|
||||
})
|
||||
})
|
||||
|
||||
it('properly uses content only if template is not defined', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: '%s',
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title'
|
||||
}
|
||||
],
|
||||
base: [],
|
||||
link: [],
|
||||
style: [],
|
||||
script: [],
|
||||
noscript: [],
|
||||
__dangerouslyDisableSanitizers: [],
|
||||
__dangerouslyDisableSanitizersByTagID: {}
|
||||
})
|
||||
})
|
||||
|
||||
it('properly uses content only if template is null', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title',
|
||||
template: null
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: '%s',
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title'
|
||||
}
|
||||
],
|
||||
base: [],
|
||||
link: [],
|
||||
style: [],
|
||||
script: [],
|
||||
noscript: [],
|
||||
__dangerouslyDisableSanitizers: [],
|
||||
__dangerouslyDisableSanitizersByTagID: {}
|
||||
})
|
||||
})
|
||||
|
||||
it('properly uses content only if template is false', () => {
|
||||
component = new Vue({
|
||||
metaInfo: {
|
||||
title: 'Hello',
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title',
|
||||
template: false
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
expect(getMetaInfo(component)).to.eql({
|
||||
title: 'Hello',
|
||||
titleChunk: 'Hello',
|
||||
titleTemplate: '%s',
|
||||
htmlAttrs: {},
|
||||
headAttrs: {},
|
||||
bodyAttrs: {},
|
||||
meta: [
|
||||
{
|
||||
vmid: 'og:title',
|
||||
property: 'og:title',
|
||||
content: 'Test title'
|
||||
}
|
||||
],
|
||||
base: [],
|
||||
link: [],
|
||||
style: [],
|
||||
script: [],
|
||||
noscript: [],
|
||||
__dangerouslyDisableSanitizers: [],
|
||||
__dangerouslyDisableSanitizersByTagID: {}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user