diff --git a/LICENSE.md b/LICENSE.md
index d4415fd..eddb309 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,9 @@
MIT License
-Copyright (c) 2016-2018 Declan de Wet & Sébastien Chopin
+Copyright (c) 2016-2019
+- Declan de Wet
+- Sébastien Chopin
+- All the amazing contributors (https://github.com/nuxt/vue-meta/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 8f3823c..203fcad 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,18 @@
-
+
- Manage page meta info in Vue 2.0 components. SSR + Streaming supported. Inspired by react-helmet.
+ Manage page metadata in Vue.js components with SSR support
-
-
-
+
+
+
+
+
+
```html
@@ -20,852 +23,87 @@
```
+```html
+
+
+ My Example App - Yay!
+ ...
+
+```
+# Introduction
+Vue Meta is a [Vue.js](https://vuejs.org) plugin that allows you to manage your app's metadata. It is inspired by and works similar as [`react-helmet`](https://github.com/nfl/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.
-
-
-# Table of Contents
+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.
-- [Description](#description)
-- [Installation](#installation)
- - [Yarn](#yarn)
- - [NPM](#npm)
- - [CDN](#cdn)
-- [Usage](#usage)
- - [Step 1: Preparing the plugin](#step-1-preparing-the-plugin)
- - [Options](#options)
- - [Step 2: Server Rendering (Optional)](#step-2-server-rendering-optional)
- - [Step 2.1: Exposing `$meta` to `bundleRenderer`](#step-21-exposing-meta-to-bundlerenderer)
- - [Step 2.2: Populating the document meta info with `inject()`](#step-22-populating-the-document-meta-info-with-inject)
- - [Simple Rendering with `renderToString()`](#simple-rendering-with-rendertostring)
- - [Streaming Rendering with `renderToStream()`](#streaming-rendering-with-rendertostream)
- - [Step 3: Start defining `metaInfo`](#step-3-start-defining-metainfo)
- - [Recognized `metaInfo` Properties](#recognized-metainfo-properties)
- - [`title` (String)](#title-string)
- - [`titleTemplate` (String | Function)](#titletemplate-string--function)
- - [`htmlAttrs` (Object)](#htmlattrs-object)
- - [`headAttrs` (Object)](#headattrs-object)
- - [`bodyAttrs` (Object)](#bodyattrs-object)
- - [`base` (Object)](#base-object)
- - [`meta` ([Object])](#meta-object)
- - [`link` ([Object])](#link-object)
- - [`style` ([Object])](#style-object)
- - [`script` ([Object])](#script-object)
- - [`noscript` ([Object])](#noscript-object)
- - [`__dangerouslyDisableSanitizers` ([String])](#__dangerouslydisablesanitizers-string)
- - [`__dangerouslyDisableSanitizersByTagID` ({[String]})](#__dangerouslydisablesanitizersbytagid-string)
- - [`changed` (Function)](#changed-function)
- - [`refreshOnceOnNavigation` (Boolean)](#refreshonceonnavigation-boolean)
- - [`afterNavigation` (Function)](#afternavigation-function)
- - [How `metaInfo` is Resolved](#how-metainfo-is-resolved)
- - [Lists of Tags](#lists-of-tags)
-- [Performance](#performance)
- - [How to prevent the update on the initial page render](#how-to-prevent-the-update-on-the-initial-page-render)
-- [FAQ](#faq)
- - [How do I use component props and/or component data in `metaInfo`?](#how-do-i-use-component-props-andor-component-data-in-metainfo)
- - [How do I populate `metaInfo` from the result of an asynchronous action?](#how-do-i-populate-metainfo-from-the-result-of-an-asynchronous-action)
- - [Why doesn't `vue-meta` support `jsnext:main`?](#why-doesnt-vue-meta-support-jsnextmain)
-- [Examples](#examples)
+## Documentation
-
+Please find the documention on https://vue-meta.nuxtjs.org
+> :globe_with_meridians: Please help us translate the documentation into your language
-# Description
-`vue-meta` is a [Vue 2.0](https://vuejs.org) plugin that allows you to manage your app's meta information, much like [`react-helmet`](https://github.com/nfl/react-helmet) does 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.
+## Examples
-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 meta info directly to deeply nested subcomponents for more maintainable code.
+Looking for more examples what vue-meta can do for you? Have a look at the [examples](https://github.com/nuxt/vue-meta/tree/master/examples)
-# Installation
+## Installation
-### Yarn
+##### Yarn
```sh
$ yarn add vue-meta
```
-### NPM
+##### npm
```sh
$ npm install vue-meta --save
```
-### CDN
+##### Download / CDN
-Use the links below - if you want a previous version, check the instructions at https://unpkg.com.
+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/lib/vue-meta.min.js
+
+Latest v1.x version: https://unpkg.com/vue-meta@1/lib/vue-meta.min.js
-
**Uncompressed:**
```html
-
+
```
**Minified:**
```html
-
+
```
-
-# Usage
+## Quick Usage
-## Step 1: Preparing the plugin
-> This step is optional if you don't need SSR and `Vue` is available as a global variable. `vue-meta` will install itself in this case.
-
-In order to use this plugin, you first need to pass it to `Vue.use` - if you're not rendering on the server-side, your JS entry file will suffice. If you are rendering on the server, then place it in a file that runs both on the server and on the client before your root instance is mounted. If you're using [`vue-router`](https://github.com/vuejs/vue-router), then your main `router.js` file is a good place:
-
-**router.js:**
+See the [documentation](https://vue-meta.nuxtjs.org) for more information
```js
import Vue from 'vue'
-import Router from 'vue-router'
-import Meta from 'vue-meta'
+import VueMeta from 'vue-meta'
-Vue.use(Router)
-Vue.use(Meta)
-
-export default new Router({
- ...
+Vue.use(VueMeta, {
+ // optional pluginOptions
+ refreshOnceOnNavigation: true
})
```
-#### Options
+## Higher level 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
-`vue-meta` allows a few custom options:
+- [Nuxt.js](https://github.com/nuxt/nuxt.js) - The Vue.js Meta framework
+- [Gridsome](https://github.com/gridsome/gridsome) - The Vue.js JAMstack framework
-```js
-Vue.use(Meta, {
- keyName: 'metaInfo', // the component option name that vue-meta looks for meta info on.
- attribute: 'data-vue-meta', // the attribute name vue-meta adds to the tags it observes
- ssrAttribute: 'data-vue-meta-server-rendered', // the attribute name that lets vue-meta know that meta info has already been server-rendered
- tagIDKeyName: 'vmid' // the property name that vue-meta uses to determine whether to overwrite or append a tag
-})
-```
+# License
-If you don't care about server-side rendering, you can skip straight to [step 3](#step-3-start-defining-metainfo). Otherwise, continue. :smile:
-
-## Step 2: Server Rendering (Optional)
-
-If you have an isomorphic/universal webapp, you'll likely want to render your metadata on the server side as well. Here's how.
-
-### Step 2.1: Exposing `$meta` to `bundleRenderer`
-
-You'll need to expose the results of the `$meta` method that `vue-meta` adds to the Vue instance to the bundle render context before you can begin injecting your meta information. You'll need to do this in your server entry file:
-
-**server-entry.js:**
-```js
-import app from './app'
-
-const router = app.$router
-const meta = app.$meta() // here
-
-export default (context) => {
- router.push(context.url)
- context.meta = meta // and here
- return app
-}
-```
-
-### Step 2.2: Populating the document meta info with `inject()`
-
-All that's left for you to do now before you can begin using `metaInfo` options in your components is to make sure they work on the server by `inject`-ing them so you can call `text()` on each item to render out the necessary info. You have two methods at your disposal:
-
-#### Simple Rendering with `renderToString()`
-
-Considerably the easiest method to wrap your head around is if your Vue server markup is rendered out as a string:
-
-**server.js:**
-
-```js
-app.get('*', (req, res) => {
- const context = { url: req.url }
- renderer.renderToString(context, (error, html) => {
- if (error) return res.send(error.stack)
- const bodyOpt = { body: true }
- const {
- title, htmlAttrs, headAttrs, bodyAttrs, link, style, script, noscript, meta
- } = context.meta.inject()
- return res.send(`
-
-
-
- ${meta.text()}
- ${title.text()}
- ${link.text()}
- ${style.text()}
- ${script.text()}
- ${noscript.text()}
-
-
- ${html}
-
-
- ${script.text(bodyOpt)}
-
-
- `)
- })
-})
-```
-
-If you are using a separate template file, edit your head tag with
-
-```html
-
- {{{ meta.inject().title.text() }}}
- {{{ meta.inject().meta.text() }}}
-
-```
-
-Notice the use of `{{{` to avoid double escaping. Be extremely cautious when you use `{{{` with `__dangerouslyDisableSanitizers`.
-
-#### Streaming Rendering with `renderToStream()`
-
-A little more complex, but well worth it, is to instead stream your response. `vue-meta` supports streaming with no effort (on it's part :stuck_out_tongue_winking_eye:) thanks to Vue's clever `bundleRenderer` context injection:
-
-**server.js**
-```js
-app.get('*', (req, res) => {
- const context = { url: req.url }
- const renderStream = renderer.renderToStream(context)
- renderStream.once('data', () => {
- const bodyOpt = { body: true }
- const {
- title, htmlAttrs, headAttrs, bodyAttrs, link, style, script, noscript, meta
- } = context.meta.inject()
- res.write(`
-
-
-
- ${meta.text()}
- ${title.text()}
- ${link.text()}
- ${style.text()}
- ${script.text()}
- ${noscript.text()}
-
-
- `)
- })
- renderStream.on('data', (chunk) => {
- res.write(chunk)
- })
- renderStream.on('end', () => {
- res.end(`
-
-
- ${script.text(bodyOpt)}
-
-
- `)
- })
- renderStream.on('error', (error) => res.status(500).end(`
${error.stack}
`))
-})
-```
-
-## Step 3: Start defining `metaInfo`
-
-In any of your components, define a `metaInfo` property:
-
-**App.vue:**
-```html
-
-
-
-
-
-
-
-```
-
-**Home.vue**
-```html
-
-
-
Home Page
-
-
-
-
-```
-
-**About.vue**
-```html
-
-
-
About Page
-
-
-
-
-```
-
-### Recognized `metaInfo` Properties
-
-#### `title` (String)
-
-Maps to the inner-text value of the `` element.
-
-```js
-{
- metaInfo: {
- title: 'Foo Bar'
- }
-}
-```
-
-```html
-Foo Bar
-```
-
-#### `titleTemplate` (String | Function)
-
-The value of `title` will be injected into the `%s` placeholder in `titleTemplate` before being rendered. The original title will be available on `metaInfo.titleChunk`.
-
-```js
-{
- metaInfo: {
- title: 'Foo Bar',
- titleTemplate: '%s - Baz'
- }
-}
-```
-
-```html
-Foo Bar - Baz
-```
-
-The property can also be a function (from [v1.2.0](https://github.com/nuxt/vue-meta/releases/tag/v1.2.0)):
-
-```js
-titleTemplate: (titleChunk) => {
- // If undefined or blank then we don't need the hyphen
- return titleChunk ? `${titleChunk} - Site Title` : 'Site Title';
-}
-```
-
-#### `htmlAttrs` (Object)
-
-Each **key:value** maps to the equivalent **attribute:value** of the `` element.
-
-```js
-{
- metaInfo: {
- htmlAttrs: {
- foo: 'bar',
- amp: undefined
- }
- }
-}
-```
-
-```html
-
-```
-
-#### `headAttrs` (Object)
-
-Each **key:value** maps to the equivalent **attribute:value** of the `` element.
-
-```js
-{
- metaInfo: {
- headAttrs: {
- foo: 'bar'
- }
- }
-}
-```
-
-```html
-
-```
-
-#### `bodyAttrs` (Object)
-
-Each **key:value** maps to the equivalent **attribute:value** of the `` element.
-
-```js
-{
- metaInfo: {
- bodyAttrs: {
- bar: 'baz'
- }
- }
-}
-```
-
-```html
-Foo Bar
-```
-
-#### `base` (Object)
-
-Maps to a newly-created `` element, where object properties map to attributes.
-
-```js
-{
- metaInfo: {
- base: { target: '_blank', href: '/' }
- }
-}
-```
-
-```html
-
-```
-
-#### `meta` ([Object])
-
-Each item in the array maps to a newly-created `` element, where object properties map to attributes.
-
-```js
-{
- metaInfo: {
- meta: [
- { charset: 'utf-8' },
- { name: 'viewport', content: 'width=device-width, initial-scale=1' }
- ]
- }
-}
-```
-
-```html
-
-
-```
-
-Since v1.5.0, you can now set up meta templates that work similar to the titleTemplate:
-
-```js
-{
- metaInfo: {
- meta: [
- { charset: 'utf-8' },
- {
- 'property': 'og:title',
- 'content': 'Test title',
- 'template': chunk => `${chunk} - My page`, //or as string template: '%s - My page',
- 'vmid': 'og:title'
- }
- ]
- }
-}
-```
-
-```html
-
-
-```
-
-
-#### `link` ([Object])
-
-Each item in the array maps to a newly-created `` element, where object properties map to attributes.
-
-```js
-{
- metaInfo: {
- link: [
- { rel: 'stylesheet', href: '/css/index.css' },
- { rel: 'favicon', href: 'favicon.ico' }
- ]
- }
-}
-```
-
-```html
-
-
-```
-
-#### `style` ([Object])
-
-Each item in the array maps to a newly-created `
-```
-
-#### `script` ([Object])
-
-Each item in the array maps to a newly-created `
-```
-
-:warning: You have to disable sanitizers so the content of `innerHTML` won't be escaped. Please refer to [\__dangerouslyDisableSanitizers](#__dangerouslydisablesanitizers-string) section below for more info on related risks.
-
-```js
-{
- metaInfo: {
- script: [
- { innerHTML: '{ "@context": "http://schema.org" }', type: 'application/ld+json' }
- ],
- __dangerouslyDisableSanitizers: ['script'],
- }
-}
-```
-
-```html
-
-```
-
-If your browser doesn't support `defer` or any other reason, you want to put `
-```
-
-**PostContainer.vue:**
-```html
-
-
-
-
-
-
-
-```
-
-## How do I populate `metaInfo` from the result of an asynchronous action?
-
-`vue-meta` will do this for you automatically when your component state changes.
-
-Just make sure that you're using the function form of `metaInfo`:
-
-```js
-{
- data () {
- return {
- title: 'Foo Bar Baz'
- }
- },
- metaInfo () {
- return {
- title: this.title
- }
- }
-}
-```
-
-Check out the [vuex-async](https://github.com/nuxt/vue-meta/tree/master/examples/vuex-async) example for a far more detailed demonstration if you have doubts.
-
-Credit & Thanks for this feature goes to [Sébastien Chopin](https://github.com/Atinux).
-
-## Why doesn't `vue-meta` support `jsnext:main`?
-
-Originally, it did - however, it caused [problems](https://github.com/nuxt/vue-meta/issues/25). Essentially, Vue [does not support](https://github.com/vuejs/vue/issues/2880) `jsnext:main`, and does not introspect for the `default` property that is transpiled from the ES2015 source, thus breaking module resolution.
-
-Given that `jsnext:main` is a non-standard property that won't stick around for long, and `vue-meta` is bundled into one file with no dynamic module internals as well as the fact that if you're using `vue-meta`, you're 99.9% likely to not be using it conditionally - the decision has been made to drop support for it entirely.
-
-If this were not the case, you would have to instruct Babel to convert `default` imports to the proper commonjs module syntax via a plugin, which is not ideal since many users in the Vue landscape write their code in TypeScript, not Babel.
-
-# Examples
-
-To run the examples locally; clone this repository and run `cd examples && yarn install` in the root directory, then run `yarn start`. Head to http://localhost:3000 or run with `HOST=0.0.0.0 PORT=8080 yarn start` to change host or port
-
-If you would like to help to develop vue-meta then run `yarn install` both in the root and examples dir and run `yarn dev`
+[MIT](./LICENSE.md)
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
new file mode 100644
index 0000000..220d480
--- /dev/null
+++ b/docs/.vuepress/config.js
@@ -0,0 +1,70 @@
+module.exports = {
+ locales: {
+ '/': {
+ lang: 'en-US',
+ title: 'Vue Meta',
+ description: 'Metadata manager for Vue.js'
+ },
+ },
+ serviceWorker: true,
+ theme: 'vue',
+ themeConfig: {
+ repo: 'nuxt/vue-meta',
+ docsDir: 'docs',
+ locales: {
+ '/': {
+ label: 'English',
+ selectText: 'Languages',
+ editLinkText: 'Edit this page on GitHub',
+ nav: [{
+ text: 'Guide',
+ link: '/guide/'
+ }, {
+ text: 'API',
+ link: '/api/'
+ }, {
+ text: 'Release Notes',
+ link: 'https://github.com/nuxt/vue-meta/releases'
+ }],
+ sidebar: [
+ '/installation.md',
+ '/',
+ {
+ title: 'Usage',
+ collapsable: false,
+ children: [
+ '/guide/',
+ '/guide/ssr',
+ '/guide/metainfo',
+ '/guide/special',
+ '/guide/caveats',
+ ]
+ },
+ {
+ title: 'FAQ',
+ collapsable: false,
+ children: [
+ '/faq/',
+ '/faq/performance.md',
+ '/faq/prevent-initial.md',
+ '/faq/component-props.md',
+ '/faq/async-action.md',
+ ]
+ },
+ /*{
+ title: 'Advanced',
+ collapsable: false,
+ children: [
+ '/guide/advanced/navigation-guards.md',
+ '/guide/advanced/meta.md',
+ '/guide/advanced/transitions.md',
+ '/guide/advanced/data-fetching.md',
+ '/guide/advanced/scroll-behavior.md',
+ '/guide/advanced/lazy-loading.md'
+ ]
+ }*/
+ ]
+ },
+ }
+ }
+}
diff --git a/docs/.vuepress/public/logo.png b/docs/.vuepress/public/logo.png
new file mode 100644
index 0000000..1b1e1c9
Binary files /dev/null and b/docs/.vuepress/public/logo.png differ
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..70da502
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,14 @@
+
+
+::: tip We need your help
+We are working on defining the RFC for Vue Meta v3.0. It will be a ground-breaking release built from the ground up.
+
+We would like your help with this! Please visit the [Vue Meta v3.0 rfc](https://github.com/nuxt/rfcs/issues/19) and let us know your thoughts.
+:::
+
+# Introduction
+`vue-meta` is a [Vue.js](https://vuejs.org) plugin that allows you to manage your app's metadata, much like [`react-helmet`](https://github.com/nfl/react-helmet) does 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 sub components for more maintainable code.
+
+[Get started](/guide) or play with the [examples](https://github.com/nuxt/vue-meta/tree/master/examples)
diff --git a/docs/api/README.md b/docs/api/README.md
new file mode 100644
index 0000000..403213f
--- /dev/null
+++ b/docs/api/README.md
@@ -0,0 +1,470 @@
+---
+sidebar: auto
+---
+
+# API Reference
+
+## Plugin options
+
+### keyName
+- type `string`
+- default `metaInfo`
+
+The name of the component option that contains all the information that gets converted to the various meta tags & attributes for the page
+
+### attribute
+- type `string`
+- default `data-vue-meta`
+
+The name of the attribute vue-meta arguments on elements to know which it should manage and which it should ignore.
+
+### ssrAttribute
+- type `string`
+- default `data-vue-meta-server-rendered`
+
+The name of the attribute that is added to the `html` tag to inform `vue-meta` that the server has already generated the meta tags for the initial render
+
+See [How to prevent update on page load](/faq/prevent-initial)
+
+### tagIDKeyName
+- type `string`
+- default `vmid`
+
+The property that tells `vue-meta` to overwrite (instead of append) an item in a tag list.
+For example, if you have two `meta` tag list items that both have `vmid` of 'description',
+then vue-meta will overwrite the shallowest one with the deepest one.
+
+### contentKeyName
+- type `string`
+- default `content`
+
+The key name for the content-holding property
+
+### metaTemplateKeyName
+- type `string`
+- default `template`
+
+The key name for possible meta templates
+
+### refreshOnceOnNavigation
+- type `boolean`
+- default `false`
+
+When `true` then `vue-meta` will pause updates once page navigation starts and resumes updates when navigation finishes (resuming also triggers an update).
+This could both be a performance improvement as a possible fix for 'flickering' when you are e.g. replacing stylesheets
+
+## Plugin methods
+
+The `vue-meta` plugin injects a `$meta()` function in the Vue prototype which provides the following methods
+
+:::tip Note
+`$meta()` is a function so we only need to insert it once in the `Vue.prototype`, but still use `this` to reference the component it was called from
+:::
+
+### $meta().getOptions
+- returns [`pluginOptions`](/api/#plugin-options)
+
+Could be used by third-party libraries who wish to interact with `vue-meta`
+
+### $meta().refresh
+- returns [`metaInfo`](/api/#metaInfo-properties)
+
+Updates the current metadata with new metadata.
+Useful when updating metadata as the result of an asynchronous action that resolves after the initial render takes place.
+
+### $meta().inject
+- returns [`metaInfo`](/api/#metaInfo-properties)
+
+:::tip SSR only
+`inject` is available in the server plugin only and is not available on the client
+:::
+
+It returns a special `metaInfo` object where all keys have an object as value which contains a `text()` method for returning html code
+
+See [Rendering with renderToString](/guide/ssr.html#simple-rendering-with-rendertostring) for an example
+
+### $meta().pause
+- arguments:
+ - refresh (type `boolean`, default `false`)
+- returns `resume()`
+
+Pauses global metadata updates until either the returned resume method is called or [resume](/api/#meta-resume)
+
+### $meta().resume
+- arguments:
+ - refresh (type `boolean`, default `false`)
+- returns [`metaInfo`](/api/#metaInfo-properties) (optional)
+
+Resumes metadata updates after they have been paused. If `refresh` is `true` it immediately initiates a metadata update by calling [refresh](/api/#meta-refresh)
+
+## metaInfo properties
+
+::: tip Note
+The documentation below uses `metaInfo` as `keyName` in the examples, please note that this is [configurable](/api/#keyname) and could be different in your case
+:::
+
+### title
+- type `string`
+
+Maps to the inner-text value of the `` element.
+
+```js
+{
+ metaInfo: {
+ title: 'Foo Bar'
+ }
+}
+```
+
+```html
+Foo Bar
+```
+
+### titleTemplate
+- type `string | Function`
+
+The value of `title` will be injected into the `%s` placeholder in `titleTemplate` before being rendered. The original title will be available on `metaInfo.titleChunk`.
+
+```js
+{
+ metaInfo: {
+ title: 'Foo Bar',
+ titleTemplate: '%s - Baz'
+ }
+}
+```
+
+```html
+Foo Bar - Baz
+```
+
+The property can also be a function:
+
+```js
+titleTemplate: (titleChunk) => {
+ // If undefined or blank then we don't need the hyphen
+ return titleChunk ? `${titleChunk} - Site Title` : 'Site Title';
+}
+```
+
+### htmlAttrs
+### headAttrs
+### bodyAttrs
+- type `object`
+
+Each **key:value** maps to the equivalent **attribute:value** of the `` element.
+
+Since `v2.0` value can also be an `Array`
+
+```js
+{
+ metaInfo: {
+ htmlAttrs: {
+ lang: 'en',
+ amp: true
+ },
+ bodyAttrs: {
+ class: ['dark-mode', 'mobile']
+ }
+ }
+}
+```
+
+```html
+
+Foo Bar
+```
+
+### base
+- type `object`
+
+Maps to a newly-created `` element, where object properties map to attributes.
+
+```js
+{
+ metaInfo: {
+ base: { target: '_blank', href: '/' }
+ }
+}
+```
+
+```html
+
+```
+
+### meta
+- type `collection`
+
+Each item in the array maps to a newly-created `` element, where object properties map to attributes.
+
+```js
+{
+ metaInfo: {
+ meta: [
+ { charset: 'utf-8' },
+ { name: 'viewport', content: 'width=device-width, initial-scale=1' }
+ ]
+ }
+}
+```
+
+```html
+
+
+```
+
+#### Content templates
+
+Since `v1.5.0`, you can now set up meta templates that work similar to the titleTemplate:
+
+```js
+{
+ metaInfo: {
+ meta: [
+ { charset: 'utf-8' },
+ {
+ 'property': 'og:title',
+ 'content': 'Test title',
+ 'template': chunk => `${chunk} - My page`, //or as string template: '%s - My page',
+ 'vmid': 'og:title'
+ }
+ ]
+ }
+}
+```
+
+```html
+
+
+```
+
+### link
+- type `collection`
+
+
+Each item in the array maps to a newly-created `` element, where object properties map to attributes.
+
+```js
+{
+ metaInfo: {
+ link: [
+ { rel: 'stylesheet', href: '/css/index.css' },
+ { rel: 'favicon', href: 'favicon.ico' }
+ ]
+ }
+}
+```
+
+```html
+
+
+```
+
+### style
+- type `object`
+
+Each item in the array maps to a newly-created `
+```
+
+### script
+- type `collection`
+
+Each item in the array maps to a newly-created `
+```
+
+#### Add json or other raw data
+::: warning
+You have to disable sanitizers so the content of `innerHTML` won't be escaped. Please see [__dangerouslyDisableSanitizersByTagID](/api/#dangerouslydisablesanitizersbytagid) for more info on related risks
+:::
+
+```js
+{
+ metaInfo: {
+ script: [{
+ vmid: 'ldjson-schema',
+ innerHTML: '{ "@context": "http://schema.org" }',
+ type: 'application/ld+json'
+ }],
+ __dangerouslyDisableSanitizersByTagID: {
+ 'ldjson-schema': ['innerHTML']
+ },
+ }
+}
+```
+
+```html
+
+```
+#### Special attribute: `body: true`
+
+If you e.g. wish to force delayed execution of a script or just want the script to be included in the `` of the page, add `body: true`.
+Script tags with `body: true` are rendered just before ``
+
+```js
+{
+ metaInfo: {
+ script: [{
+ innerHTML: 'console.log("I am in body");',
+ type: 'text/javascript',
+ body: true
+ }]
+ }
+}
+```
+
+### noscript
+- type `collection`
+
+Each item in the array maps to a newly-created `