GithubHelp home page GithubHelp logo

nuxt / vue-meta Goto Github PK

View Code? Open in Web Editor NEW
4.1K 43.0 247.0 5.52 MB

Manage HTML metadata in Vue.js components with SSR support

Home Page: https://vue-meta.nuxtjs.org

License: Other

JavaScript 97.75% Vue 0.89% TypeScript 1.36%
vue metadata meta seo

vue-meta's Introduction

This project is not actively maintained anymore.

More information can be found in #808


โœŒ๏ธ๐Ÿฅ‰ Check the next branch for Vue3 support


vue-meta

Manage HTML metadata in Vue.js components with SSR support

npm downloads npm version Coverage Status Build Status dependencies Status Discord

<template>
  ...
</template>

<script>
  export default {
    metaInfo: {
      title: 'My Example App',
      titleTemplate: '%s - Yay!',
      htmlAttrs: {
        lang: 'en',
        amp: true
      }
    }
  }
</script>
<html lang="en" amp>
<head>
  <title>My Example App - Yay!</title>
  ...
</head>

Introduction

Vue Meta is a Vue.js plugin that allows you to manage your app's metadata. It is inspired by and works similar as react-helmet for react. However, instead of setting your data as props passed to a proprietary component, you simply export it as part of your component's data using the metaInfo property.

These properties, when set on a deeply nested component, will cleverly overwrite their parent components' metaInfo, thereby enabling custom info for each top-level view as well as coupling metadata directly to deeply nested subcomponents for more maintainable code.

Documentation

Please find the documention on https://vue-meta.nuxtjs.org

๐ŸŒ Please help us translate the documentation into your language, see here for more information

Examples

Looking for more examples what vue-meta can do for you? Have a look at the examples

Installation

Yarn
$ yarn add vue-meta
npm
$ npm install vue-meta --save
Download / CDN

Use the download links below - if you want a previous version, check the instructions at https://unpkg.com.

Latest version: https://unpkg.com/vue-meta/dist/vue-meta.min.js

Latest v1.x version: https://unpkg.com/vue-meta@1/dist/vue-meta.min.js

Uncompressed:

<script src="https://unpkg.com/vue-meta/dist/vue-meta.js"></script>

Minified:

<script src="https://unpkg.com/vue-meta/dist/vue-meta.min.js"></script>

Quick Usage

See the documentation for more information

import Vue from 'vue'
import VueMeta from 'vue-meta'

Vue.use(VueMeta, {
  // optional pluginOptions
  refreshOnceOnNavigation: true
})

Frameworks using vue-meta

If you wish to create your app even more quickly, take a look at the following frameworks which use vue-meta

  • Nuxt.js - The Vue.js Progressive Framework
  • Gridsome - The Vue.js JAMstack Framework
  • Ream - Framework for building universal web app and static website in Vue.js
  • Vue-Storefront - PWA for eCommerce
  • Factor JS - Extension-first VueJS platform for front-end developers.

How to translate documentation

Thanks for your interest in translating the documentation. As our docs are based on VuePress, we recommend to have a look at their docs about internationalization as well

Here are the steps you will need to take:

  • Clone this repository
  • Create a new branch
  • Browse to /docs/
  • Create a folder with the language code you will add a translation for (eg /zh/)
  • Copy all *.md files and the folders api, faq, and guide to that folder
  • Translate the copied files in your language folder
  • Edit .vuepress/config.yml and add a config section for your locale in both locales as themeConfig.locales
  • Test your translation by running the docs dev server with yarn docs
  • Create a pull request with your changes
  • Receive eternal gratefulness from your fellow language speakers โค๏ธ

Old versions

Click here if you are looking for the old v1 readme

License

MIT

vue-meta's People

Contributors

adrienbaron avatar albinodrought avatar atinux avatar btkostner avatar clarkdo avatar eddiesigner avatar greenkeeper[bot] avatar jhaynie avatar lxvc avatar mannil avatar marshallswain avatar mojodna avatar neonvoice avatar nicolasigot avatar paulgv avatar pi0 avatar pimlie avatar raiondesu avatar rchl avatar renovate-bot avatar renovate[bot] avatar rhwilr avatar ricardogobbosouza avatar salvadornico avatar shyiko avatar silentdepth avatar simplesmiler avatar vintprox avatar wilk avatar zspecza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-meta's Issues

JSON+LD Structured data

Hi

As you know, Google is using JSON+LD markup to display structured data on results. Maybe it would be good having the possibility to include a JSON+LD script tag per page with vue-meta?

Cheers
Jerome

When I create another new vue instance

for example:

import Vue from 'vue';
import VueMeta from 'vue-meta';

Vue.use(VueMeta);

new Vue({
    el: '#app',
    metaInfo: { ... }
});

new Vue({
    el: '#anoter',
});

When another instance changed, like: beforeCreateใ€created ใ€beforeMount ใ€destroyed ๏ผŒdocument's meta will be clean.

VueMeta should be used for only one vue instance.

Another new vue instance maybe from other people's vue plugin.

Watch for changes

Posting this here because #12 is about custom options

@Atinux posted a really cool idea: #12 (comment)

To watch for changes via the use of a computed property and react to those changes by calling $meta().refresh() automatically. This would remove the need to manually manage asynchronous updates.

Add examples

  • basic usage
  • basic render function usage
  • using component data as data source
  • using component props as data source
  • usage with vue-router
  • usage with vuex
  • async usage with vuex
  • overriding parent metaInfo
  • sibling metaInfo (not sure how this behaves atm)
  • SSR with renderToString
  • SSR with renderToStream
  • disabling sanitization
  • documentation on running examples

imports not working on Meteor

Reproduction:

meteor create test-app
cd test-app
meteor add akryum:vue-component
npm i vue vue-meta --save
npm i
meteor

Then import vue-meta on the client-side, results in:

image

akryum:vue-component should not be related to this problem though.

renderToStream: first chunk too big cause vue-meta can't get correct meta info of child components

In stream.once('data', ...), if the first chunk is too big, the following child components haven't been created at the moment, so their metaInfo won't have effects.

Github: https://github.com/fenivana/vue-meta-streaming-issue

Run in node.js:

const Vue = require('vue')
const renderer = require('vue-server-renderer').createRenderer()
const VueMeta = require('vue-meta')

Vue.use(VueMeta)

const vm = new Vue({
  metaInfo: {
    title: 'root'
  },

  template: `
    <div>
      ${'a'.repeat(100000)}
      <foo/>
    </div>
  `,

  components: {
    foo: {
      metaInfo: {
        title: 'foo'
      },
      template: '<div>foo</div>'
    }
  }
})

const stream = renderer.renderToStream(vm)

stream.once('data', () => {
  // BUG: title is 'root'. SHOULD be 'foo'
  console.log(vm.$meta().inject().title.text())
})

Merge default Metadata

Hi, i have a idea for Defaults

As example

In my app.vue i have

metaInfo: {
    title: 'Renka',
    meta: [
      {
        name: 'description', content: 'bar'
      },
      {
        property: 'og:title',
        content: 'Default'
      },
      {
        property: 'og_sitename',
        content: 'Default'
      },
      {
        property: 'og:image',
        content: 'Default'
      }
    ]
  }

and when i open my Home.vue
which comes from <router-view></router-view> in my App.vue

  metaInfo: {
    title: 'Home',
    meta: [
      {
        name: 'description', content: 'bar'
      },
      {
        property: 'og:title',
        content: 'Test'
      },
      {
        property: 'og:image',
        content: 'Test'
      }
    ]
  },

Will overwrite my whole meta tags and og_sitename is gone

i could just make my own function which will merge both objects but then i need todo this over and over
i think a i simple solution would be pass the defaults via Options or something i would do a Pr but yea.. my js is not the best :P
awesome plugin! ๐Ÿ’ƒ

Function-style metaInfo broken with keep-alive

When I use vue-meta with vue-router and <keep-alive>, I can't reliably use the function-style metaInfo.

I have two pages in my application, with the following in their component definitions:

// Page one
...
metaInfo: {
	title: 'Hello world!'
},
...

// Page 2
...
metaInfo: function () {
	return {
		title: 'Route name: ' + this.$route.name
	};
},
...

When I load my application and enter page one, I will see "Hello world!" as the page title. When I switch to page 2, I will see something like "Route name: pageTwoRouteName" as expected. However when I then switch back to page one, the page title is something like "Route name: pageOneRouteName". (The route names are what I have defined in my route configuration.)

It seems that when using a function to return the values for metaInfo, vue-meta starts $watching for the changes but never stores or calls the unwatch callback that would stop listening to the changes and writing, in my case, a new title for the component that has been transitioned out and deactivated but is still alive in the background.

If this is the case then I suspect similar unexpected results happen in any situation where components that use function-style metaInfo are used for a component that is not destroyed when navigating away from them, so it's not vue-router-specific issue even if it's probably the most common use case.

I can work on a PR later on but maybe someone can confirm if this is what's actually happening. If so, maybe just adding the unwatch callbacks to deactivated and beforeDestroy will do the trick.

Children components of render functions

I'm using vue-meta on a children component of a render function that use createElement to render a component List with different props given by routes.

The method beforeMount is called everytime I change the route (tried to log on it), but metaInfo updates only at first render (logged on title() method as suggested by docs), how is it possible? If i use metaInfo on component with render function everything is working.

Thank you in advice.

Incorrect handling of metadata with navigation

Say the app.vue parent component at route / has this property:

metaInfo () {
    return {
      title: 'parent title'
    }
}

and a child component at route /child has this property:

 metaInfo() {
    return {
      title: `${this.name}`
    }
 },

When navigating to the child, the title changes correctly. Then when going back, the title stays as the child's title (it should go back to parent title). Then when navigating to the same child component (a different instance), the title flicks to 'undefined' before changing to the new this.name.

What I would expect is that going back from /child to / would change the title back to what it was before the child overrode it. Then I would expect that if this.name is not ready yet when metaInfo is initially called it will leave the current title, rather than changing it to undefined, thus causing the flicker.

when add option like '__dangerouslyDisableSanitizers' in Nuxt.js , something is wrong like 'Uncaught DOMException: Failed to execute 'setAttribute' on 'Element': '0' is not a valid attribute name.'

vue-meta in nuxt

script: [ {innerHTML: "(function(h){h.className=h.className.replace('no-js','js')})(document.documentElement)"} ], __dangerouslyDisableSanitizers: ["script"], // because of the inner quotes

From one route to another route, something is wrong like 'Uncaught DOMException: Failed to execute 'setAttribute' on 'Element': '0' is not a valid attribute name.'

line 786:

newElement.setAttribute(attr, value);

so we fix it like this:

image

Cannot convert undefined or null to object(โ€ฆ)

I have it setup with vue-router.

whenever I do the Vue.use(VueMeta); I get the current console error and it doesn't load my component.

vue-meta.js?ffcf:1151Uncaught TypeError: Cannot convert undefined or null to object(โ€ฆ)

Error: head script dangerouslyDisableSanitizers

Hello

I need insert google tag manager

head: {
  script: [
    //googletagmanager
    { innerHTML: "some script" },
  ],
  __dangerouslyDisableSanitizers: ['script']
}

when i change page (this.$router.push())

I have error Exeption

Do you can to help me?

Implement metaInfo options

Props

  • title
    • client
    • server
  • titleTemplate
    • client
    • server
  • base
    • client
    • server
  • htmlAttrs
    • client
    • server
  • bodyAttrs
    • client
    • server
  • meta
    • client
    • server
  • link
    • client
    • server
  • script
    • client
    • server
  • noscript
    • client
    • server
  • style
    • client
    • server

Other

  • documentation

vue-meta for AMP

Hi,

only a suggestion,

I use vue-meta to manage meta, but also to respect AMP requierement (Google Accelerated Mobile Page).

They have some required mark-up, always the same
https://www.ampproject.org/docs/tutorials/create/basic_markup

Maybe it's possible to add an AMP option to respect some of the requierement.

Like :
"Contain a <script async src="https://cdn.ampproject.org/v0.js"></script> tag as the second child of their tag (this includes and loads the AMP JS library)."

An AMP option could force AMP cdn.ampproject.org to be the second child after the head
(scripts can be declare in more then one component, it could be difficult to put the script at the second child if we have many scripts in many components).

Or if no AMP option, maybe give us a way to order the scripts ?

Thanks for the good work

beforeMount is calling server side

I'm not sure if this is an issue with your library, my setup or Vue itself.

But

beforeMount: function beforeMount () {
      var this$1 = this;

      // batch potential DOM updates to prevent extraneous re-rendering
      batchID = batchUpdate(batchID, function () { return this$1.$meta().refresh(); });
    }

this is being called server side. Even this.$isServer comes back true and it's throwing a document no found error. Technically I don't think beforeMount is supposed to run server side so this may be an issue with Vue.

Empty string is undefined

Hi,

in my application I set an initial data variable as empty string in my component. My next step is to get the final value from an async call.

Within this time from initialization of the data variable and the overwrite from the ajax call the value is undefined. I have tested it without the ajax call and it is independent of it. If I have defined my variable in the data function of my component as an empty string, it got undefined.

My current dirty solution is to use an string with an empty line in it, because I donยดt want an 'undefined' text in my page title.

This very simple example produce an undefined page title:

module.exports = {
    data: function () {
        return {
            title: ''
        }
    }

    metaInfo: function () {
        return {
            title: this.title,
            titleTemplate: '%s | MySite'
        }
    }
}

Asynchronous Actions Prevent Meta Info Updates

Due to non-reactivity. If a property is null before reference, (as is the case when using a Vuex action to asynchronously fetch data) Vue throws an error and the title does not update, it instead refers to old data. See #10 (comment) for more info.

data-vue-meta-server-rendered not working

Even if I set data-vue-meta-server-rendered attribute and the meta tag is still generated on the initial page render. Maybe because of some ajax stuff before create Vue App instance. Anyone experience the same issue ?

version 0.5.3

Vuex / Computed Prop

Hi,

What is the best way to get the title from a Vuex getter?

Current problem is my Title is not the same as in the Post on the page first after a F5 Refresh the title is correct

<template>
    <article class="single-post" v-if="post">
        <header class="post-header">
            <h1> {{post.title}} </h1>
        </header>
        <section v-html="post.content_html" class="post-content">
        </section>
    </article>
</template>

Also the title in post.title != my title in metaInfo but its should i dont know its a problem because async

  name: 'SinglePost',
        computed: {
            post() {
                var post = this.$store.getters.getPost
                return post;
            }
        },
        metaInfo: {
            // if no subcomponents specify a metaInfo.title, this title will be used
            title () {
                    return this.post.title 
//The title is not the same as on the page the title is from the last visited page 
            }
        },
        data() {
            return {
                post: {}
            }
        },
        preFetch: function (store) {
            return store.dispatch('singlePost', store.state.route.params.slug)
        },
        mounted() {

            this.$store.dispatch('singlePost', this.$store.state.route.params.slug)

        },

    }

When i use in Simple Components works fine

//E maybe the problem is from my side how i handle Switching the post

Problem is it updates not all the time when i console.log out in the metaInfo i see its just hits on the first load and not when switchting between my posts

{
          path: ':slug',
          component: SinglePost,
          meta: {
            bodyClass: 'light',
          }

Or its something like #9

sry my english is not so good

document on ssr = true is not defined

Hello

I'm using nuxt and would like to know if its possible that there is currently a bug in vue-meta regarding of a document call on SSR: vue-meta line 825:

function _updateClientMetaInfo (options) {
  if ( options === void 0 ) options = {};

  var ssrAttribute = options.ssrAttribute;

  /**
   * Performs client-side updates when new meta info is received
   *
   * @param  {Object} newInfo - the meta info to update to
   */
  return function updateClientMetaInfo (newInfo) {
    var htmlTag = document.getElementsByTagName('html')[0];
  var htmlTag = document.getElementsByTagName('html')[0];
                  ^

ReferenceError: document is not defined

If ssrAttribute is set, and the server tries to render, vue-meta throws error. Any idea if this intend to work like this? I posted this on nuxt as well: nuxt/nuxt#449
Thanks

Why the tab title show full url in browser ??

Hi, I am using your basic configuration in every component, but why does it show the full url in the tab title such as i refresh the page or route to another page. See the attached image below.

path

In the component, i just these setting in export default

metaInfo () {
     return {
          title: this.title || 'Loading',
	  titleTemplate: '%s - VueJs'
     }
},
computed: {
     title () {
           return 'Login'
     }
}

How should i fixed it ? Thanks to help !

Getting "document is not defined" after upgrading to 0.5.6

We've been using vue-meta with SSR on 0.5.5, but after upgrading to 0.5.6 we started getting the following errors on the server:

ReferenceError: document is not defined
    at updateClientMetaInfo (/path/to/node_modules/vue-meta/lib/vue-meta.js:824:19)
    at Vue$2.refresh (/path/to/node_modules/vue-meta/lib/vue-meta.js:885:35)
    at /path/to/node_modules/vue-meta/lib/vue-meta.js:1013:74
    at Timeout._onTimeout (/path/to/node_modules/vue-meta/lib/vue-meta.js:924:5)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)

Allow to specify a limit for <title> text length, truncate if above

Hi,

It would be nice to have a way to specify a limit for the text length in the title tag. If the title length is greater than the limit, it would truncate the part before the titleTemplate string.

Example
Let's say you have:

title: 'Your page example is brought to you by the example company',
titleTemplate: '%s | Example Website'

If you specify the limit to 50, which this text exceeds, the computed title would be:

Your page example is brought ... | Example Website

which is 50 characters long.

It would definitely be a nice-to-have feature for handling title lengths with Google limitations.

Cheers,
Jerome

Better code format in source for meta data-vue-meta

Hi,

it's really a detail, not really important, it's working.

When you look the source code directly, not with the inspector, all the meta are on one line. They should be one per line for better readability.
Exemple :

` <meta data-vue-meta="true" name="description" content=""/><meta data-vue-meta="true" name="twitter:card" content="summary_large_image"/><meta data-vue-meta="true" name="twitter:site" content="@string"/><meta data-vue-meta="true" name="twitter:creator" content="@string"/><meta data-vue-meta="true" name="twitter:title" content=""/><meta data-vue-meta="true" name="twitter:description" content=""/><meta data-vue-meta="true" name="twitter:image" content=""/><meta data-vue-meta="true" property="og:site_name" content="string"/><meta data-vue-meta="true" property="og:type" content="website"/><meta data-vue-meta="true" property="og:url" content="http://localhost:7070/amp/recipes/et-soluta-accusamus-accusamus-rerum-nisi-nam-quo"/><meta data-vue-meta="true" property="og:description" content=""/><meta data-vue-meta="true" property="og:title" content=""/><meta data-vue-meta="true" property="og:image" content=""/><meta data-vue-meta="true" name="description" content="null"/><meta data-vue-meta="true" name="twitter:card" content="summary_large_image"/><meta data-vue-meta="true" name="twitter:site" content="@string"/><meta data-vue-meta="true" name="twitter:creator" content="@string"/><meta data-vue-meta="true" name="twitter:title" content="null"/><meta data-vue-meta="true" name="twitter:description" content="null"/><meta data-vue-meta="true" name="twitter:image" content=""/><meta data-vue-meta="true" property="og:site_name" content="string"/><meta data-vue-meta="true" property="og:type" content="website"/><meta data-vue-meta="true" property="og:url" content="http://localhost:7070/amp/recipes/et-soluta-accusamus-accusamus-rerum-nisi-nam-quo"/><meta data-vue-meta="true" property="og:description" content="null"/><meta data-vue-meta="true" property="og:title" content="null"/><meta data-vue-meta="true" property="og:image" content=""/>`

Uncaught TypeError: plugin.apply is not a function When Running Karma unit test

Hello,

I've installed the plugin with npm and imported it in my router

Code:

import Vue from 'vue'
import Router from 'vue-router'
import Meta from 'vue-meta'
Vue.use(Router)
Vue.use(Meta)

after this, Karma unit test throw error

Error:

17 11 2016 16:17:25.621:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
17 11 2016 16:17:25.625:INFO [launcher]: Launching browser Chrome with unlimited concurrency
17 11 2016 16:17:25.632:INFO [launcher]: Starting browser Chrome
17 11 2016 16:17:26.819:INFO [Chrome 54.0.2840 (Mac OS X 10.12.1)]: Connected on socket /#Dan5pkY-wXijHOQSAAAA with id 65822028
Chrome 54.0.2840 (Mac OS X 10.12.1) ERROR
  Uncaught TypeError: plugin.apply is not a function
  at index.js:3310

Chrome 54.0.2840 (Mac OS X 10.12.1): Executed 0 of 0 ERROR (0.539 secs / 0 secs)

Any idea?

Thank's :)

Replace existing meta

If you have an already existing meta like description in the DOM (PHP server rendering) you may want to replace it instead of adding a new one. Is is possible ?

version 0.5.3

MetaInfo in Vue's root

metaInfo: {
    meta: [
      { vmid: 'description', name: 'description', content: 'dolor' }
    ]
  }

Expected result

Original tag

<meta name="description" content="lorem ipsum">

Output

<meta name="description" content="dolor">

Current result

Original tag

<meta name="description" content="lorem ipsum">

Output

<meta name="description" content="lorem ipsum">
<meta vmid="description" name="description" content="dolor" data-vue-meta="true">

Internal JS doesn't process properly with multiple keys

Hello, I'm using nuxt and trying to add internal JS in JSON-LD format.
For the purpose to be short, I added just a couple of properties in the example. Without __dangerouslyDisableSanitizers: ['script'], it doesn't process " leaving it as &quot;

export default {
  head () {
    return {
      script: [
        { innerHTML: '{ "@context": "http://www.schema.org", "@type": "Organization" }', type: 'application/ld+json' }
      ],
      __dangerouslyDisableSanitizers: ['script']
    }
  }
}

Twitter cards meta bug?

Website: https://nuxt-head-elements.now.sh/about

You can take a look at the source code, there is:

<meta n-head="true" charset="utf-8"/>
<meta n-head="true" name="viewport" content="width=device-width, initial-scale=1"/>
<meta n-head="true" hid="description" name="description" content="About page description"/>
<meta n-head="true" name="twitter:card" content="summary"/>
<meta n-head="true" name="twitter:site" content="@nuxt_js"/>
<meta n-head="true" name="twitter:title" content="Nuxt.js Twitter Card"/>
<meta n-head="true" name="twitter:description" content="Nuxt.js lets you handle custom headers for your app with vue-meta"/>
<meta n-head="true" name="twitter:image" content="https://avatars0.githubusercontent.com/u/23360933?v=3"/>
<meta n-head="true" name="twitter:image:alt" content="Nuxt.js logo"/>
<title n-head="true">About Page - Nuxt.js</title>

But if you try to check the meta tags here: https://cards-dev.twitter.com/validator

It says that no meta tags has been found.

Same for some other meta checker like http://www.seocentro.com/tools/search-engines/metatag-analyzer.html

Do you think it's because of the n-head attribute or hid?

Doesn't work with vue-router + ssr

It seems before the vue root instance mounted, its $children will be an empty array, so getComponentOption won't work properly cause we don't 'mount' instance in server side.

Anyone has the same issue ?

__dangerouslyDisableSanitizers causing errors

Hello, I'm new to vuejs and vue-meta

the issue is I am running into some errors on the client side and I have a working hack, but would like some insights on how to properly handle these errors

the problem

I think that the vue-meta thinks __dangerouslyDisableSanitizers and its value ['script'] are properties and tries to continually traverse into the ['script'] array which then causes the string 'script' into an array.

__dangerouslyDisableSanitizers ["script"]
0 s
1 c
2 r
3 i
4 p
5 t

some background, I am using SSR and ran into this issue, however it is reproducible on the examples as well

Here are the Errors (chrome inspector)

updateTags.js?8526**:37 Uncaught DOMException: Failed to execute 'setAttribute' on 'Element': '0' is not a valid attribute name.
    at http://localhost:8080/__build__/basic.js:9274:26
    at Array.forEach (native)
    at updateTags (http://localhost:8080/__build__/basic.js:9259:12)
    at http://localhost:8080/__build__/basic.js:9151:67
    at Array.forEach (native)
    at http://localhost:8080/__build__/basic.js:9133:30
    at updateClientMetaInfo (http://localhost:8080/__build__/basic.js:9166:9)
    at Vue$3.refresh (http://localhost:8080/__build__/basic.js:9083:49)
    at http://localhost:8080/__build__/basic.js:9811:31
    at http://localhost:8080/__build__/basic.js:9042:5

heres the code from examples/basic/app.js

import Vue from 'vue'
import VueMeta from 'vue-meta'

Vue.use(VueMeta)

new Vue({
  template: `
    <div id="app">
      <h1>Basic</h1>
      <p>Inspect Element to see the meta info</p>
    </div>
  `,
  metaInfo: () => ({
    title: 'Basic',
    titleTemplate: '%s | Vue Meta Examples',
    htmlAttrs: {
      lang: 'en',
      amp: undefined
    },
    script: [
      { innerHTML: '{ "@context": "http://schema.org" }', type: 'text/javascript' }
    ],
    __dangerouslyDisableSanitizers: ['script']

  })
}).$mount('#app')

and heres my hack

updateClientMetaInfo.js

~ line 36 i added case '__dangerouslyDisableSanitizers':

case 'titleChunk':
case 'titleTemplate':
case 'changed':
case '__dangerouslyDisableSanitizers':
  break
// catch-all update tags
default:
...

getMetaInfo.js

~ line 101 i added
escaped[key] = val;
if (key === '__dangerouslyDisableSanitizers') return escaped;

const isDisabled = ref && ref.indexOf(key) > -1
const val = info[key]

escaped[key] = val;
if (key === '__dangerouslyDisableSanitizers') return escaped;

if (!isDisabled) {
  if (typeof val === 'string') {
    escaped[key] = escapeHTML(val)
...

open to any comments
thanks!

Adding options `keyName`

Hi!

I think it could be great to set the keyName as an option when installing vue-meta:

import Meta from 'vue-meta'

var options = {
  keyName: 'head'
}
Vue.use(Meta, options)

So then, in my components, I can do:

<script>
  export default {
    head: {
      title: 'My Example App',
      htmlAttrs: { lang: 'en' }
    }
  }
</script>

I want to implement it in nuxt.js as similar as in next.js, the component name is , so a key head seems the best name to making it similar (even if vue-meta can update more than inside the , which rocks ๐Ÿš€ )

I you like the idea, I can try to make a pull request?

Not working with vue-cli webpack

Hi,

tried to get it working, but somehow it doesn't add the title, not even other meta data, which I set.

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Meta from 'vue-meta'
import axios from 'axios'
import Homepage from '@/components/Homepage'

Vue.use(Router, Meta, axios)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Homepage',
      component: Homepage
    }
  ]
})

App.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'app',
  metaInfo () {
    return {
      title: 'Hello World'
    }
  }
}
</script>

components/Homepage.vue (excerpt)

...
<script>
import axios from 'axios'
import storage from '../storage.js'

export default {
  name: 'homepage',
  metaInfo () {
    return {
      title: 'Homepage'
    }
  },
...

title.text() is empty

Hi Guys,

I recently installed vue-meta to manage my titles, metas etc. This plugin is excellent so thanks a lot !
However I'm facing a few issues while trying to make it work with SSR.

I started my project from the well known official hackernews2 template. I precisely followed vue-meta plugin instructions regarding SSR but when I log context.meta.inject().title.text() when rendering on server, I always get:
<title data-vue-meta="true"></title>

Since the code from hackernews was a bit different, here's what I did :

  1. Added Vue.use(Meta) inside app.js
  2. Added const meta = app.$meta() and context.meta = meta inside server-entry.js
  3. Added some metaInfo inside app.vue component
  4. Updated the code inside server.js to this (I don't know if its the best way):
  let context = { url: req.url }
  let stream = renderer.renderToStream(context)
  stream.on('error', errorHandler)
  stream.on('end', () => console.log(`whole request: ${Date.now() - s}ms`))
  stream.on('pipe', (chunk) => {
    const {
      title, htmlAttrs, bodyAttrs, link, style, script, noscript, meta
    } = context.meta.inject()
    console.log(title.text()) // Here's where I always got <title data-vue-meta="true"></title>
    chunk.head = chunk.head.replace(/<title>(.*?)<\/title>/, title.text()) //Obviously, regarding the previous line, the replaced title contains <title data-vue-meta="true"></title>...
    chunk.head = chunk.head += meta.text() // A test to append meta from vue-meta at the end of the header. Didn't try it yet
  })
  stream.pipe(res)

Are you facing the same issue ? What am I doing wrong ?

Thanks a lot in advance,

Allow special characters

Hi, how do you allow special characters?
For example, if you have This is my title's, it will render as This is my title&#39;s which doesn't rendere correctly in the title tag

Style and Script not converted right

In version 0.5.2 the style and script are not converted how they should.

metaInfo: {
        titleTemplate: 'Shop Admin | %s',
        title: 'Dashboard',
        style: [
            { cssText: '.foo { color: red }', type: 'text/css' }
        ],
        script: [
            { innerHTML: 'console.log("Foo");', type: 'text/javascript' }
        ]
 }
<style csstext=".foo { color: red }" type="text/css" data-vue-meta="true"></style>
<script innerhtml="console.log(&amp;quot;Foo&amp;quot;);" type="text/javascript" data-vue-meta="true"></script>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.