2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-06-22 18:20:33 +03:00

test: add render tests

fix: webpack dev server

chore: use eslint not prettier

unfeat: remove support for comments (its brokenn in Vue, maybe later)
This commit is contained in:
pimlie
2020-07-26 00:11:28 +02:00
parent 28d3fc1923
commit 27aaf4744a
80 changed files with 2785 additions and 12109 deletions
+4 -4
View File
@@ -10,14 +10,14 @@ window.users.push({
zipcode: '92998-3874',
geo: {
lat: '-37.3159',
lng: '81.1496',
},
lng: '81.1496'
}
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets',
},
bs: 'harness real-time e-markets'
}
})
+4 -4
View File
@@ -10,14 +10,14 @@ window.users.push({
zipcode: '90566-7771',
geo: {
lat: '-43.9509',
lng: '-34.4618',
},
lng: '-34.4618'
}
},
phone: '010-692-6593 x09125',
website: 'anastasia.net',
company: {
name: 'Deckow-Crist',
catchPhrase: 'Proactive didactic contingency',
bs: 'synergize scalable supply-chains',
},
bs: 'synergize scalable supply-chains'
}
})
+4 -4
View File
@@ -10,14 +10,14 @@ window.users.push({
zipcode: '59590-4157',
geo: {
lat: '-68.6102',
lng: '-47.0653',
},
lng: '-47.0653'
}
},
phone: '1-463-123-4447',
website: 'ramiro.info',
company: {
name: 'Romaguera-Jacobson',
catchPhrase: 'Face to face bifurcated interface',
bs: 'e-enable strategic applications',
},
bs: 'e-enable strategic applications'
}
})
+4 -4
View File
@@ -10,14 +10,14 @@ window.users.push({
zipcode: '53919-4257',
geo: {
lat: '29.4572',
lng: '-164.2990',
},
lng: '-164.2990'
}
},
phone: '493-170-9623 x156',
website: 'kale.biz',
company: {
name: 'Robel-Corkery',
catchPhrase: 'Multi-tiered zero tolerance productivity',
bs: 'transition cutting-edge web services',
},
bs: 'transition cutting-edge web services'
}
})
+16 -16
View File
@@ -6,7 +6,7 @@ Vue.use(VueMeta)
window.users = []
new Vue({
metaInfo() {
metaInfo () {
return {
title: 'Async Callback',
titleTemplate: '%s | Vue Meta Examples',
@@ -16,56 +16,56 @@ new Vue({
vmid: 'potatoes',
src: '/user-3.js',
async: true,
callback: this.updateCounter,
callback: this.updateCounter
},
{
skip: this.count < 1,
vmid: 'vegetables',
src: '/user-2.js',
async: true,
callback: this.updateCounter,
callback: this.updateCounter
},
{
vmid: 'meat',
src: '/user-1.js',
async: true,
callback: el => this.loadCallback(el.getAttribute('data-vmid')),
callback: el => this.loadCallback(el.getAttribute('data-vmid'))
},
...this.scripts,
],
...this.scripts
]
}
},
data() {
data () {
return {
count: 0,
scripts: [],
users: window.users,
users: window.users
}
},
watch: {
count(val) {
count (val) {
if (val === 3) {
this.addScript()
}
},
}
},
methods: {
updateCounter() {
updateCounter () {
this.count++
},
addScript() {
addScript () {
this.scripts.push({
src: '/user-4.js',
callback: () => {
this.updateCounter()
},
}
})
},
loadCallback(vmid) {
loadCallback (vmid) {
if (vmid === 'meat') {
this.updateCounter()
}
},
}
},
template: `
<div id="app">
@@ -84,5 +84,5 @@ new Vue({
</ul>
</div>
</div>
`,
`
}).$mount('#app')
+10 -10
View File
@@ -8,17 +8,17 @@ Vue.component('child', {
props: {
page: {
type: String,
default: '',
},
},
render(h) {
return h('h3', null, this.page)
},
metaInfo() {
return {
title: this.page,
default: ''
}
},
render (h) {
return h('h3', null, this.page)
},
metaInfo () {
return {
title: this.page
}
}
})
new Vue({
@@ -28,5 +28,5 @@ new Vue({
<p>Inspect Element to see the meta info</p>
<child page="This is a prop"></child>
</div>
`,
`
}).$mount('#app')
+7 -7
View File
@@ -15,24 +15,24 @@ new Vue({
titleTemplate: '%s | Vue Meta Examples',
htmlAttrs: {
lang: 'en',
amp: undefined,
amp: undefined
},
headAttrs: {
test: true,
test: true
},
meta: [{ name: 'description', content: 'Hello', vmid: 'test' }],
script: [
{
innerHTML:
'{ "@context": "http://www.schema.org", "@type": "Organization" }',
type: 'application/ld+json',
type: 'application/ld+json'
},
{
innerHTML: '{ "body": "yes" }',
body: true,
type: 'application/ld+json',
},
type: 'application/ld+json'
}
],
__dangerouslyDisableSanitizers: ['script'],
}),
__dangerouslyDisableSanitizers: ['script']
})
}).$mount('#app')
+7 -7
View File
@@ -6,18 +6,18 @@ Vue.use(VueMeta)
Vue.component('foo', {
template: '<p>Foo component</p>',
metaInfo: {
title: 'Keep me Foo',
},
title: 'Keep me Foo'
}
})
new Vue({
data() {
data () {
return { showFoo: false }
},
methods: {
show() {
show () {
this.showFoo = !this.showFoo
},
}
},
template: `
<div id="app">
@@ -29,6 +29,6 @@ new Vue({
</div>
`,
metaInfo: () => ({
title: 'Keep-alive',
}),
title: 'Keep-alive'
})
}).$mount('#app')
+4 -4
View File
@@ -5,12 +5,12 @@ const {
processIf,
getBaseTransformPreset,
createObjectExpression,
createObjectProperty,
createObjectProperty
} = require('@vue/compiler-core')
const { parse } = require('@vue/compiler-dom')
function headTransform(node, context) {
function headTransform (node, context) {
console.log('NODE', node)
if (node.type === 1 /* NodeTypes.ELEMENT */) {
return () => {
@@ -35,13 +35,13 @@ module.exports = function (source, map) {
// console.log('AST', ast)
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset({
prefixIdentifiers: true,
prefixIdentifiers: true
})
transform(ast, {
prefixIdentifiers: true,
nodeTransforms: [...nodeTransforms, headTransform],
directiveTransforms,
directiveTransforms
})
const result = generate(ast, { mode: 'module' })
+14 -14
View File
@@ -6,50 +6,50 @@ Vue.use(VueMeta)
// index.html contains a manual SSR render
const app1 = new Vue({
metaInfo() {
metaInfo () {
return {
title: 'App 1 title',
bodyAttrs: {
class: 'app-1',
class: 'app-1'
},
meta: [
{ name: 'description', content: 'Hello from app 1', vmid: 'test' },
{ name: 'og:description', content: this.ogContent },
{ name: 'og:description', content: this.ogContent }
],
script: [
{ innerHTML: 'var appId=1.1', body: true },
{ innerHTML: 'var appId=1.2', vmid: 'app-id-body' },
],
{ innerHTML: 'var appId=1.2', vmid: 'app-id-body' }
]
}
},
data() {
data () {
return {
ogContent: 'Hello from ssr app',
ogContent: 'Hello from ssr app'
}
},
template: `
<div id="app1"><h1>App 1</h1></div>
`,
`
})
const app2 = new Vue({
metaInfo: () => ({
title: 'App 2 title',
bodyAttrs: {
class: 'app-2',
class: 'app-2'
},
meta: [
{ name: 'description', content: 'Hello from app 2', vmid: 'test' },
{ name: 'og:description', content: 'Hello from app 2' },
{ name: 'og:description', content: 'Hello from app 2' }
],
script: [
{ innerHTML: 'var appId=2.1', body: true },
{ innerHTML: 'var appId=2.2', vmid: 'app-id-body', body: true },
],
{ innerHTML: 'var appId=2.2', vmid: 'app-id-body', body: true }
]
}),
template: `
<div id="app2"><h1>App 2</h1></div>
`,
`
}).$mount('#app2')
app1.$mount('#app1')
@@ -57,7 +57,7 @@ app1.$mount('#app1')
const app3 = new Vue({
template: `
<div id="app3"><h1>App 3 (empty metaInfo)</h1></div>
`,
`
}).$mount('#app3')
setTimeout(() => {
+3 -3
View File
@@ -16,14 +16,14 @@ app.use(
writeToDisk: true,
stats: {
colors: true,
chunks: false,
},
chunks: false
}
})
)
fs.readdirSync(__dirname)
.filter(file => file !== 'ssr')
.forEach(file => {
.forEach((file) => {
if (fs.statSync(path.join(__dirname, file)).isDirectory()) {
app.use(rewrite(`/${file}/*`, `/${file}/index.html`))
}
+31 -31
View File
@@ -6,7 +6,7 @@ Vue.use(VueMeta, {
tagIDKeyName: 'hid'
}) */
export default function createMyApp() {
export default function createMyApp () {
const Home = {
template: `<div>
<router-link to="/about">About</router-link>
@@ -19,15 +19,15 @@ export default function createMyApp() {
{
hid: 'og:title',
name: 'og:title',
content: 'Hello World',
content: 'Hello World'
},
{
hid: 'description',
name: 'description',
content: 'Hello World',
},
],
},
content: 'Hello World'
}
]
}
}
const About = {
@@ -42,28 +42,28 @@ export default function createMyApp() {
{
hid: 'og:title',
name: 'og:title',
content: 'About World',
content: 'About World'
},
{
hid: 'description',
name: 'description',
content: 'About World',
},
],
},
content: 'About World'
}
]
}
}
const router = createRouter({
history: createMemoryHistory('/ssr'),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
],
{ path: '/about', component: About }
]
})
const app = createSSRApp({
router,
metaInfo() {
metaInfo () {
return {
title: 'Boring Title',
htmlAttrs: { amp: true },
@@ -74,63 +74,63 @@ export default function createMyApp() {
hid: 'og:title',
name: 'og:title',
template: chunk => `${chunk} - My Site`,
content: 'Default Title',
content: 'Default Title'
},
{
hid: 'description',
name: 'description',
content: 'Say something',
},
content: 'Say something'
}
],
script: [
{
hid: 'ldjson-schema',
type: 'application/ld+json',
innerHTML:
'{ "@context": "http://www.schema.org", "@type": "Organization" }',
'{ "@context": "http://www.schema.org", "@type": "Organization" }'
},
{
type: 'application/ld+json',
innerHTML: '{ "body": "yes" }',
body: true,
body: true
},
{
hid: 'my-async-script-with-load-callback',
src: '/user-1.js',
body: true,
defer: true,
callback: this.loadCallback,
callback: this.loadCallback
},
{
skip: this.count < 1,
src: '/user-2.js',
body: true,
callback: this.loadCallback,
},
callback: this.loadCallback
}
],
__dangerouslyDisableSanitizersByTagID: {
'ldjson-schema': ['innerHTML'],
},
'ldjson-schema': ['innerHTML']
}
}
},
data() {
data () {
return {
count: 0,
users: process.server ? [] : window.users,
users: process.server ? [] : window.users
}
},
mounted() {
mounted () {
const { set, remove } = this.$meta().addApp('client-only')
set({
bodyAttrs: { class: 'client-only' },
bodyAttrs: { class: 'client-only' }
})
setTimeout(() => remove(), 3000)
},
methods: {
loadCallback() {
loadCallback () {
this.count++
},
}
},
template: `
<div id="app">
@@ -146,7 +146,7 @@ export default function createMyApp() {
</ul>
<router-view />
</div>`,
</div>`
})
app.use(router)
+5 -5
View File
@@ -12,7 +12,7 @@ const compiled = template(templateContent, { interpolate: /{{([\s\S]+?)}}/g })
process.server = true
export async function renderPage({ url }) {
export async function renderPage ({ url }) {
const { app, router } = await createApp()
await router.push(url.substr(4))
@@ -30,17 +30,17 @@ export async function renderPage({ url }) {
const pageHtml = compiled({
app: appHtml,
htmlAttrs: {
text: () => {},
text: () => {}
},
headAttrs: {
text: () => {},
text: () => {}
},
bodyAttrs: {
text: () => {},
text: () => {}
},
head: () => {},
bodyPrepend: () => {},
bodyAppend: () => {},
bodyAppend: () => {}
// ...app.$meta().inject()
})
-2
View File
@@ -27,5 +27,3 @@ export default {
}
}
</script>
useMeta()
+51 -51
View File
@@ -6,10 +6,10 @@ import {
inject,
toRefs,
h,
watch,
watch
} from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { createManager, useMeta, useMetainfo } from '../../src'
import { createManager, useMeta, useMetainfo } from 'vue-meta'
// import About from './about.vue'
const metaUpdated = 'no'
@@ -17,47 +17,47 @@ const metaUpdated = 'no'
const ChildComponent = defineComponent({
name: 'child-component',
props: {
page: String,
page: String
},
template: `
<div>
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
</div>`,
setup(props) {
setup (props) {
const state = reactive({
date: null,
metaUpdated,
metaUpdated
})
const title = props.page[0].toUpperCase() + props.page.slice(1)
console.log('ChildComponent Setup')
useMeta({
/* useMeta({
charset: 'utf16',
title,
description: 'Description ' + props.page,
og: {
title: 'Og Title ' + props.page,
},
})
}) */
return {
...toRefs(state),
...toRefs(state)
}
},
}
})
function view(page) {
function view (page) {
return {
name: `section-${page}`,
render() {
render () {
return h(ChildComponent, { page })
},
}
}
}
const App = {
setup() {
setup () {
// console.log('App', getCurrentInstance())
const { meta } = useMeta({
base: { href: '/vue-router', target: '_blank' },
@@ -69,69 +69,69 @@ const App = {
description: 'Bla bla',
image: [
'https://picsum.photos/600/400/?image=80',
'https://picsum.photos/600/400/?image=82',
],
'https://picsum.photos/600/400/?image=82'
]
},
twitter: {
title: 'Twitter Title',
title: 'Twitter Title'
},
noscript: [
'<!-- // A code comment -->',
{ tag: 'link', rel: 'stylesheet', href: 'style.css' },
//'<!-- // A code comment -->',
{ tag: 'link', rel: 'stylesheet', href: 'style.css' }
],
otherNoscript: {
tag: 'noscript',
'data-test': 'hello',
content: [
'<!-- // Another code comment -->',
{ tag: 'link', rel: 'stylesheet', href: 'style2.css' },
],
children: [
//'<!-- // Another code comment -->',
{ tag: 'link', rel: 'stylesheet', href: 'style2.css' }
]
},
body: 'body-script1.js',
script: [
'<!--[if IE]>',
//'<!--[if IE]>',
{ src: 'head-script1.js' },
'<![endif]-->',
{ src: 'body-script2.js', target: 'body' },
{ src: 'body-script3.js', target: '#put-it-here' },
//'<![endif]-->',
{ src: 'body-script2.js', to: 'body' },
{ src: 'body-script3.js', to: '#put-it-here' }
],
esi: {
content: [
children: [
{
tag: 'choose',
content: [
children: [
{
tag: 'when',
test: '$(HTTP_COOKIE{group})=="Advanced"',
content: [
children: [
{
tag: 'include',
src: 'http://www.example.com/advanced.html',
},
],
},
],
},
],
},
src: 'http://www.example.com/advanced.html'
}
]
}
]
}
]
}
})
setTimeout(() => (meta.title = 'My Updated Title'), 2000)
const metainfo = useMetainfo()
const metadata = useMetainfo()
window.$metainfo = metainfo
window.$metainfo = metadata
watch(metainfo, (newValue, oldValue) => {
watch(metadata, (newValue, oldValue) => {
console.log('UPDATE', newValue)
})
return {
metainfo,
metadata
}
},
template: `
<metainfo :metainfo="metainfo">
<metainfo :metainfo="metadata">
<template v-slot:base="{ content, metainfo }">http://nuxt.dev:3000{{ content }}</template>
<template v-slot:title="{ content, metainfo }">{{ content }} - {{ metainfo.description }} - Hello</template>
<template v-slot:og(title)="{ content, metainfo, og }">
@@ -148,10 +148,10 @@ const App = {
</transition>
<p>Inspect Element to see the meta info</p>
</div>
`,
`
}
function decisionMaker5000000(key, pathSegments, getOptions, getCurrentValue) {
function decisionMaker5000000 (key, pathSegments, getOptions, getCurrentValue) {
let theChosenOne
const options = getOptions()
@@ -177,26 +177,26 @@ const metaManager = createManager({
esi: {
group: true,
namespaced: true,
contentAttributes: ['src', 'test', 'text'],
},
},
attributes: ['src', 'test', 'text']
}
}
})
useMeta(
/* useMeta(
{
og: {
something: 'test',
},
},
metaManager
)
) */
const router = createRouter({
history: createWebHistory('/vue-router'),
routes: [
{ name: 'home', path: '/', component: view('home') },
{ name: 'about', path: '/about', component: view('about') },
],
{ name: 'about', path: '/about', component: view('about') }
]
})
const app = createApp(App)
+2 -2
View File
@@ -12,6 +12,6 @@ export default new Router({
base: '/vuex-async',
routes: [
{ path: '/', component: Home },
{ path: '/posts/:slug', component: Post },
],
{ path: '/posts/:slug', component: Post }
]
})
+17 -17
View File
@@ -14,64 +14,64 @@ export default new Vuex.Store({
title: '',
content: '',
slug: '',
published: false,
published: false
},
posts: [
{
slug: 'a-sample-blog-post',
title: 'A Sample Blog Post',
content: 'This is the blog post content',
published: true,
published: true
},
{
slug: 'an-unpublished-blog-post',
title: 'An Unpublished Blog Post',
content: 'This is the blog post content',
published: false,
published: false
},
{
slug: 'another-blog-post',
title: 'Another Blog Post',
content: 'This is the blog post content',
published: true,
},
],
published: true
}
]
},
// GETTERS
getters: {
isLoading(state) {
isLoading (state) {
return state.isLoading
},
post(state) {
post (state) {
return state.post
},
publishedPosts(state) {
publishedPosts (state) {
return state.posts.filter(post => post.published)
},
publishedPostsCount(state, getters) {
publishedPostsCount (state, getters) {
return getters.publishedPosts.length
},
}
},
// MUTATIONS
mutations: {
loadingState(state, { isLoading }) {
loadingState (state, { isLoading }) {
state.isLoading = isLoading
},
getPost(state, { slug }) {
getPost (state, { slug }) {
state.post = state.posts.find(post => post.slug === slug)
},
}
},
// ACTIONS
actions: {
getPost({ commit }, payload) {
getPost ({ commit }, payload) {
commit('loadingState', { isLoading: true })
setTimeout(() => {
commit('getPost', payload)
commit('loadingState', { isLoading: false })
}, 2000)
},
},
}
}
})
+2 -2
View File
@@ -13,6 +13,6 @@ export default new Router({
base: '/vuex',
routes: [
{ path: '/', component: Home },
{ path: '/posts/:slug', component: Post },
],
{ path: '/posts/:slug', component: Post }
]
})
+15 -15
View File
@@ -14,54 +14,54 @@ export default new Vuex.Store({
title: '',
content: '',
slug: '',
published: false,
published: false
},
posts: [
{
slug: 'a-sample-blog-post',
title: 'A Sample Blog Post',
content: 'This is the blog post content',
published: true,
published: true
},
{
slug: 'an-unpublished-blog-post',
title: 'An Unpublished Blog Post',
content: 'This is the blog post content',
published: false,
published: false
},
{
slug: 'another-blog-post',
title: 'Another Blog Post',
content: 'This is the blog post content',
published: true,
},
],
published: true
}
]
},
// GETTERS
getters: {
post(state) {
post (state) {
return state.post
},
publishedPosts(state) {
publishedPosts (state) {
return state.posts.filter(post => post.published)
},
publishedPostsCount(state, getters) {
publishedPostsCount (state, getters) {
return getters.publishedPosts.length
},
}
},
// MUTATIONS
mutations: {
getPost(state, { slug }) {
getPost (state, { slug }) {
state.post = state.posts.find(post => post.slug === slug)
},
}
},
// ACTIONS
actions: {
getPost({ commit }, payload) {
getPost ({ commit }, payload) {
commit('getPost', payload)
},
},
}
}
})
+96
View File
@@ -0,0 +1,96 @@
import fs from 'fs'
import path from 'path'
import webpack from 'webpack'
import WebpackBar from 'webpackbar'
import { VueLoaderPlugin } from 'vue-loader'
// const srcDir = path.join(__dirname, '..', 'src')
export default {
devtool: 'inline-source-map',
mode: 'development',
entry: fs.readdirSync(__dirname)
.reduce((entries, dir) => {
const fullDir = path.join(__dirname, dir)
if (dir === 'ssr') {
entries[dir] = path.join(fullDir, 'browser.js')
} else if (dir === 'vue-router') {
const entry = path.join(fullDir, 'app.js')
if (fs.statSync(fullDir).isDirectory() && fs.existsSync(entry)) {
entries[dir] = entry
}
}
return entries
}, {}),
output: {
path: path.join(__dirname, '__build__'),
filename: '[name].js',
chunkFilename: '[id].chunk.js',
publicPath: '/__build__/'
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: '3',
targets: { ie: 9, safari: '5.1' }
}]
]
}
}
},
{
resourceQuery: /blockType=head/,
loader: require.resolve('./meta-loader.js')
},
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
alias: {
// this isn't technically needed, since the default `vue` entry for bundlers
// is a simple `export * from '@vue/runtime-dom`. However having this
// extra re-export somehow causes webpack to always invalidate the module
// on the first HMR update and causes the page to reload.
vue: 'vue/dist/vue.esm-bundler.js',
'vue-meta': path.resolve(__dirname, '../src/')
}
},
// Expose __dirname to allow automatically setting basename.
context: __dirname,
node: {
__dirname: true
},
plugins: [
new WebpackBar(),
new VueLoaderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
__DEV__: process.env.NODE_ENV !== 'production'
})
],
devServer: {
inline: true,
hot: true,
stats: 'minimal',
contentBase: __dirname,
overlay: true
}
}