mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-06 00:32:23 +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