mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-22 21:20:34 +03:00
feat: add components proposal
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "vue-app",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.4.5",
|
||||||
|
"@babel/preset-env": "^7.4.5",
|
||||||
|
"@vue/server-test-utils": "^1.0.0-beta.29",
|
||||||
|
"babel-jest": "^24.8.0",
|
||||||
|
"jest": "^24.8.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { createComponent, variantProps } from '../utils'
|
||||||
|
|
||||||
|
export const charset = {
|
||||||
|
functional: true,
|
||||||
|
props: {
|
||||||
|
value: String
|
||||||
|
},
|
||||||
|
render(h, { data, props }) {
|
||||||
|
data.attrs = {
|
||||||
|
...data.attrs,
|
||||||
|
charset: props.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('meta', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { createComponent, variantProps } from '../utils'
|
||||||
|
|
||||||
|
export function createDescriptionComponent({ namePrefix = '', nameAttribute = 'name' } = {}) {
|
||||||
|
return createComponent({
|
||||||
|
valueAttribute: 'content',
|
||||||
|
attrs: {
|
||||||
|
[nameAttribute]: `${namePrefix}${namePrefix ? ':' : ''}description`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const htmlDescription = createDescriptionComponent()
|
||||||
|
|
||||||
|
export const ogDescription = createDescriptionComponent({ namePrefix: 'og' })
|
||||||
|
|
||||||
|
export const twitterDescription = createDescriptionComponent({ namePrefix: 'twitter' })
|
||||||
|
|
||||||
|
export const websiteDescription = createDescriptionComponent({ nameAttribute: 'itemprop' })
|
||||||
|
|
||||||
|
export const variants = {
|
||||||
|
html: htmlDescription,
|
||||||
|
og: ogDescription,
|
||||||
|
twitter: twitterDescription,
|
||||||
|
website: websiteDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
export const description = {
|
||||||
|
...createComponent(),
|
||||||
|
render(h, { data, props }) {
|
||||||
|
return Object.keys(variantProps)
|
||||||
|
.filter(variant => props[variant] && !!variants[variant])
|
||||||
|
.map(variant => h(variants[variant], {
|
||||||
|
...data,
|
||||||
|
props: { ...props }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { createComponent, variantProps } from '../utils'
|
||||||
|
|
||||||
|
function createTitleComponent({ tag = 'meta', namePrefix = '', nameAttribute = 'name' } = {}) {
|
||||||
|
const isHtmlTitle = tag === 'title'
|
||||||
|
|
||||||
|
return createComponent({
|
||||||
|
tag,
|
||||||
|
valueAttribute: isHtmlTitle ? undefined : 'content',
|
||||||
|
attrs: isHtmlTitle ? undefined : {
|
||||||
|
[nameAttribute]: `${namePrefix}${namePrefix ? ':' : ''}title`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const htmlTitle = createTitleComponent({ tag: 'title' })
|
||||||
|
|
||||||
|
export const ogTitle = createTitleComponent({ namePrefix: 'og' })
|
||||||
|
|
||||||
|
export const twitterTitle = createTitleComponent({ namePrefix: 'twitter' })
|
||||||
|
|
||||||
|
export const websiteTitle = createTitleComponent({ nameAttribute: 'itemprop' })
|
||||||
|
|
||||||
|
export const variants = {
|
||||||
|
html: htmlTitle,
|
||||||
|
og: ogTitle,
|
||||||
|
twitter: twitterTitle,
|
||||||
|
website: websiteTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
export const title = {
|
||||||
|
...createComponent(),
|
||||||
|
render(h, { data, props }) {
|
||||||
|
return Object.keys(variantProps)
|
||||||
|
.filter(variant => props[variant] && !!variants[variant])
|
||||||
|
.map(variant => h(variants[variant], {
|
||||||
|
...data,
|
||||||
|
props: { ...props }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
export const variantProps = {
|
||||||
|
html: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
og: Boolean,
|
||||||
|
twitter: Boolean,
|
||||||
|
website: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createComponent({
|
||||||
|
tag = 'meta',
|
||||||
|
attrs = {},
|
||||||
|
valueAttribute
|
||||||
|
} = {}) {
|
||||||
|
return {
|
||||||
|
functional: true,
|
||||||
|
props: {
|
||||||
|
value: String,
|
||||||
|
...variantProps
|
||||||
|
},
|
||||||
|
render(h, { data, props }) {
|
||||||
|
let vAttr = null
|
||||||
|
if (valueAttribute) {
|
||||||
|
vAttr = { [valueAttribute]: props.value }
|
||||||
|
}
|
||||||
|
|
||||||
|
data.attrs = {
|
||||||
|
...data.attrs,
|
||||||
|
...attrs,
|
||||||
|
...vAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
return h(tag, data, valueAttribute ? undefined : props.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMetaComponent(options) {
|
||||||
|
if (!options.hasOwnProperty('valueAttribute')) {
|
||||||
|
options.valueAttribute = 'content'
|
||||||
|
}
|
||||||
|
|
||||||
|
return createComponent({
|
||||||
|
...options,
|
||||||
|
tag: 'meta'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`charset 1`] = `"<meta charset=\\"utf-8\\" data-server-rendered=\\"true\\">"`;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`description 1`] = `"<meta name=\\"description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`description:html 1`] = `"<meta name=\\"description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`description:og 1`] = `"<meta name=\\"og:description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`description:twitter 1`] = `"<meta name=\\"twitter:description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`description:website 1`] = `"<meta itemprop=\\"description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`og-description 1`] = `"<meta name=\\"og:description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`twitter-description 1`] = `"<meta name=\\"twitter:description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`website-description 1`] = `"<meta itemprop=\\"description\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`og-title 1`] = `"<meta name=\\"og:title\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`title 1`] = `"<title data-server-rendered=\\"true\\">test</title>"`;
|
||||||
|
|
||||||
|
exports[`title:html 1`] = `"<title data-server-rendered=\\"true\\">test</title>"`;
|
||||||
|
|
||||||
|
exports[`title:og 1`] = `"<meta name=\\"og:title\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`title:twitter 1`] = `"<meta name=\\"twitter:title\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`title:website 1`] = `"<meta itemprop=\\"title\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`twitter-title 1`] = `"<meta name=\\"twitter:title\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
|
|
||||||
|
exports[`website-title 1`] = `"<meta itemprop=\\"title\\" content=\\"test\\" data-server-rendered=\\"true\\">"`;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { renderToString } from '@vue/server-test-utils'
|
||||||
|
import { charset } from '../src/elements/charset'
|
||||||
|
|
||||||
|
const renderOptions = {
|
||||||
|
propsData: {
|
||||||
|
value: 'utf-8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('charset', async () => {
|
||||||
|
const str = await renderToString(charset, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { renderToString } from '@vue/server-test-utils'
|
||||||
|
import * as descriptions from '../src/elements/description'
|
||||||
|
|
||||||
|
const renderOptions = {
|
||||||
|
propsData: {
|
||||||
|
value: 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('description', async () => {
|
||||||
|
const str = await renderToString(descriptions.htmlDescription, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('og-description', async () => {
|
||||||
|
const str = await renderToString(descriptions.ogDescription, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('twitter-description', async () => {
|
||||||
|
const str = await renderToString(descriptions.twitterDescription, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('website-description', async () => {
|
||||||
|
const str = await renderToString(descriptions.websiteDescription, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('description:html', async () => {
|
||||||
|
const str = await renderToString(descriptions.description, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('description:og', async () => {
|
||||||
|
const str = await renderToString(descriptions.description, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: false,
|
||||||
|
og: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('description:twitter', async () => {
|
||||||
|
const str = await renderToString(descriptions.description, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: false,
|
||||||
|
twitter: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('description:website', async () => {
|
||||||
|
const str = await renderToString(descriptions.description, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: false,
|
||||||
|
website: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { renderToString } from '@vue/server-test-utils'
|
||||||
|
import * as titles from '../src/elements/title'
|
||||||
|
|
||||||
|
const renderOptions = {
|
||||||
|
propsData: {
|
||||||
|
value: 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('title', async () => {
|
||||||
|
const str = await renderToString(titles.htmlTitle, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('og-title', async () => {
|
||||||
|
const str = await renderToString(titles.ogTitle, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('twitter-title', async () => {
|
||||||
|
const str = await renderToString(titles.twitterTitle, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('website-title', async () => {
|
||||||
|
const str = await renderToString(titles.websiteTitle, renderOptions)
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('title:html', async () => {
|
||||||
|
const str = await renderToString(titles.title, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('title:og', async () => {
|
||||||
|
const str = await renderToString(titles.title, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: false,
|
||||||
|
og: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('title:twitter', async () => {
|
||||||
|
const str = await renderToString(titles.title, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: false,
|
||||||
|
twitter: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('title:website', async () => {
|
||||||
|
const str = await renderToString(titles.title, {
|
||||||
|
...renderOptions,
|
||||||
|
propsData: {
|
||||||
|
...renderOptions.propsData,
|
||||||
|
html: false,
|
||||||
|
website: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect(str).toMatchSnapshot()
|
||||||
|
})
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user