From 62535d47fb51d58134a6141abeaa4a00176556f2 Mon Sep 17 00:00:00 2001 From: pimlie Date: Thu, 11 Jul 2019 20:39:11 +0000 Subject: [PATCH] chore(release): 2.0.5 --- CHANGELOG.md | 17 ++ dist/vue-meta.common.js | 119 +++++++------ dist/vue-meta.esm.browser.js | 94 +++++----- dist/vue-meta.esm.browser.min.js | 2 +- dist/vue-meta.esm.js | 119 +++++++------ dist/vue-meta.js | 293 +++++++++++++++---------------- dist/vue-meta.min.js | 2 +- package.json | 2 +- 8 files changed, 343 insertions(+), 305 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb3b4d3..43a365e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.0.5](https://github.com/nuxt/vue-meta/compare/v2.0.3...v2.0.5) (2019-07-11) + + +### Bug Fixes + +* add warning for v1 boolean attribute syntax ([bfeab17](https://github.com/nuxt/vue-meta/commit/bfeab17)) +* dont change title when value is undefined (fix [#396](https://github.com/nuxt/vue-meta/issues/396)) ([90f9710](https://github.com/nuxt/vue-meta/commit/90f9710)) +* ensure hasAttribute exists on $root.$el ([f1511ac](https://github.com/nuxt/vue-meta/commit/f1511ac)) +* only show boolean attrs with truthy value ([1d9072a](https://github.com/nuxt/vue-meta/commit/1d9072a)) + + +### Tests + +* enable all getMetaInfo tests again ([24d7fee](https://github.com/nuxt/vue-meta/commit/24d7fee)) + + + ### [2.0.4](https://github.com/nuxt/vue-meta/compare/v2.0.3...v2.0.4) (2019-06-22) diff --git a/dist/vue-meta.common.js b/dist/vue-meta.common.js index 7c917b4..e6c2e5b 100644 --- a/dist/vue-meta.common.js +++ b/dist/vue-meta.common.js @@ -1,5 +1,5 @@ /** - * vue-meta v2.0.4 + * vue-meta v2.0.5 * (c) 2019 * - Declan de Wet * - Sébastien Chopin (@Atinux) @@ -13,12 +13,12 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau var deepmerge = _interopDefault(require('deepmerge')); -var version = "2.0.4"; +var version = "2.0.5"; // store an id to keep track of DOM updates var batchId = null; -function triggerUpdate(vm, hookName) { +function triggerUpdate (vm, hookName) { // if an update was triggered during initialization or when an update was triggered by the // metaInfo watcher, set initialized to null // then we keep falsy value but know we need to run a triggerUpdate after initialization @@ -39,7 +39,7 @@ function triggerUpdate(vm, hookName) { * @param {Function} callback - the update to perform * @return {Number} id - a new ID */ -function batchUpdate(callback, timeout) { +function batchUpdate (callback, timeout) { if ( timeout === void 0 ) timeout = 10; clearTimeout(batchId); @@ -56,27 +56,27 @@ function batchUpdate(callback, timeout) { * @param {any} arg - the object to check * @return {Boolean} - true if `arg` is an array */ -function isArray(arg) { +function isArray (arg) { return Array.isArray(arg) } -function isUndefined(arg) { +function isUndefined (arg) { return typeof arg === 'undefined' } -function isObject(arg) { +function isObject (arg) { return typeof arg === 'object' } -function isFunction(arg) { +function isFunction (arg) { return typeof arg === 'function' } -function isString(arg) { +function isString (arg) { return typeof arg === 'string' } -function ensureIsArray(arg, key) { +function ensureIsArray (arg, key) { if (!key || !isObject(arg)) { return isArray(arg) ? arg : [] } @@ -87,27 +87,27 @@ function ensureIsArray(arg, key) { return arg } -function ensuredPush(object, key, el) { +function ensuredPush (object, key, el) { ensureIsArray(object, key); object[key].push(el); } // Vue $root instance has a _vueMeta object property, otherwise its a boolean true -function hasMetaInfo(vm) { +function hasMetaInfo (vm) { if ( vm === void 0 ) vm = this; return vm && (vm._vueMeta === true || isObject(vm._vueMeta)) } // a component is in a metaInfo branch when itself has meta info or one of its (grand-)children has -function inMetaInfoBranch(vm) { +function inMetaInfoBranch (vm) { if ( vm === void 0 ) vm = this; return vm && !isUndefined(vm._vueMeta) } -function addNavGuards(vm) { +function addNavGuards (vm) { // return when nav guards already added or no router exists if (vm.$root._vueMeta.navGuards || !vm.$root.$router) { /* istanbul ignore next */ @@ -135,18 +135,18 @@ function addNavGuards(vm) { var appId = 1; -function createMixin(Vue, options) { +function createMixin (Vue, options) { // for which Vue lifecycle hooks should the metaInfo be refreshed var updateOnLifecycleHook = ['activated', 'deactivated', 'beforeMount']; // watch for client side component updates return { - beforeCreate: function beforeCreate() { + beforeCreate: function beforeCreate () { var this$1 = this; Object.defineProperty(this, '_hasMetaInfo', { configurable: true, - get: function get() { + get: function get () { // Show deprecation warning once when devtools enabled if (Vue.config.devtools && !this.$root._vueMeta.hasMetaInfoDeprecationWarningShown) { console.warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead'); // eslint-disable-line no-console @@ -210,7 +210,7 @@ function createMixin(Vue, options) { ensuredPush(this.$options, 'beforeMount', function () { // if this Vue-app was server rendered, set the appId to 'ssr' // only one SSR app per page is supported - if (this$1.$root.$el && this$1.$root.$el.hasAttribute('data-server-rendered')) { + if (this$1.$root.$el && this$1.$root.$el.hasAttribute && this$1.$root.$el.hasAttribute('data-server-rendered')) { this$1.$root._vueMeta.appId = 'ssr'; } }); @@ -424,7 +424,7 @@ var booleanHtmlAttributes = [ 'visible' ]; -function setOptions(options) { +function setOptions (options) { // combine options options = isObject(options) ? options : {}; @@ -437,7 +437,7 @@ function setOptions(options) { return options } -function getOptions(options) { +function getOptions (options) { var optionsCopy = {}; for (var key in options) { optionsCopy[key] = options[key]; @@ -445,7 +445,7 @@ function getOptions(options) { return optionsCopy } -function pause(refresh) { +function pause (refresh) { if ( refresh === void 0 ) refresh = true; this.$root._vueMeta.paused = true; @@ -453,7 +453,7 @@ function pause(refresh) { return function () { return resume(refresh); } } -function resume(refresh) { +function resume (refresh) { if ( refresh === void 0 ) refresh = true; this.$root._vueMeta.paused = false; @@ -463,7 +463,7 @@ function resume(refresh) { } } -function applyTemplate(ref, headObject, template, chunk) { +function applyTemplate (ref, headObject, template, chunk) { var component = ref.component; var metaTemplateKeyName = ref.metaTemplateKeyName; var contentKeyName = ref.contentKeyName; @@ -498,7 +498,7 @@ function applyTemplate(ref, headObject, template, chunk) { * files in server/ still use normal js function */ -function findIndex(array, predicate) { +function findIndex (array, predicate) { var arguments$1 = arguments; if ( !Array.prototype.findIndex) { @@ -513,14 +513,14 @@ function findIndex(array, predicate) { return array.findIndex(predicate, arguments[2]) } -function toArray(arg) { +function toArray (arg) { if ( !Array.from) { return Array.prototype.slice.call(arg) } return Array.from(arg) } -function includes(array, value) { +function includes (array, value) { if ( !Array.prototype.includes) { for (var idx in array) { if (array[idx] === value) { @@ -543,14 +543,14 @@ var serverSequences = [ var clientSequences = [ [/&/g, '\u0026'], - [//g, '\u003e'], + [//g, '\u003E'], [/"/g, '\u0022'], [/'/g, '\u0027'] ]; // sanitizes potentially dangerous characters -function escape(info, options, escapeOptions) { +function escape (info, options, escapeOptions) { var tagIDKeyName = options.tagIDKeyName; var doEscape = escapeOptions.doEscape; if ( doEscape === void 0 ) doEscape = function (v) { return v; }; var escaped = {}; @@ -600,7 +600,7 @@ function escape(info, options, escapeOptions) { return escaped } -function arrayMerge(ref, target, source) { +function arrayMerge (ref, target, source) { var component = ref.component; var tagIDKeyName = ref.tagIDKeyName; var metaTemplateKeyName = ref.metaTemplateKeyName; @@ -667,7 +667,7 @@ function arrayMerge(ref, target, source) { return destination.concat(source) } -function merge(target, source, options) { +function merge (target, source, options) { if ( options === void 0 ) options = {}; // remove properties explicitly set to false so child components can @@ -712,7 +712,7 @@ function merge(target, source, options) { * @param {Object} [result={}] - result so far * @return {Object} result - final aggregated result */ -function getComponentOption(options, component, result) { +function getComponentOption (options, component, result) { if ( options === void 0 ) options = {}; if ( result === void 0 ) result = {}; @@ -782,7 +782,7 @@ function getComponentOption(options, component, result) { * @param {Object} component - the Vue instance to get meta info from * @return {Object} - returned meta info */ -function getMetaInfo(options, component, escapeSequences) { +function getMetaInfo (options, component, escapeSequences) { if ( options === void 0 ) options = {}; if ( escapeSequences === void 0 ) escapeSequences = []; @@ -840,7 +840,7 @@ function getMetaInfo(options, component, escapeSequences) { * @param {Object} attrs - the new document html attributes * @param {HTMLElement} tag - the HTMLElement tag to update with new attrs */ -function updateAttribute(ref, attrs, tag) { +function updateAttribute (ref, attrs, tag) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; @@ -885,7 +885,7 @@ function updateAttribute(ref, attrs, tag) { * * @param {String} title - the new title of the document */ -function updateTitle(title) { +function updateTitle (title) { if (title === undefined) { return } @@ -901,7 +901,7 @@ function updateTitle(title) { * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base * @return {Object} - a representation of what tags changed */ -function updateTag(appId, ref, type, tags, headTag, bodyTag) { +function updateTag (appId, ref, type, tags, headTag, bodyTag) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; var tagIDKeyName = ref.tagIDKeyName; @@ -947,7 +947,13 @@ function updateTag(appId, ref, type, tags, headTag, bodyTag) { var _attr = includes(dataAttributes, attr) ? ("data-" + attr) : attr; - var value = isUndefined(tag[attr]) || includes(booleanHtmlAttributes, attr) ? '' : tag[attr]; + + var isBooleanAttribute = includes(booleanHtmlAttributes, attr); + if (isBooleanAttribute && !tag[attr]) { + continue + } + + var value = isBooleanAttribute ? '' : tag[attr]; newElement.setAttribute(_attr, value); } } @@ -981,7 +987,7 @@ function updateTag(appId, ref, type, tags, headTag, bodyTag) { return { oldTags: oldTags, newTags: newTags } } -function getTag(tags, tag) { +function getTag (tags, tag) { if (!tags[tag]) { tags[tag] = document.getElementsByTagName(tag)[0]; } @@ -994,7 +1000,7 @@ function getTag(tags, tag) { * * @param {Object} newInfo - the meta info to update to */ -function updateClientMetaInfo(appId, options, newInfo) { +function updateClientMetaInfo (appId, options, newInfo) { if ( options === void 0 ) options = {}; var ssrAttribute = options.ssrAttribute; @@ -1058,7 +1064,7 @@ function updateClientMetaInfo(appId, options, newInfo) { return { addedTags: addedTags, removedTags: removedTags } } -function _refresh(options) { +function _refresh (options) { if ( options === void 0 ) options = {}; /** @@ -1071,7 +1077,7 @@ function _refresh(options) { * * @return {Object} - new meta info */ - return function refresh() { + return function refresh () { var metaInfo = getMetaInfo(options, this.$root, clientSequences); var appId = this.$root._vueMeta.appId; @@ -1092,12 +1098,12 @@ function _refresh(options) { * @param {Object} data - the attributes to generate * @return {Object} - the attribute generator */ -function attributeGenerator(ref, type, data) { +function attributeGenerator (ref, type, data) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; return { - text: function text() { + text: function text () { var attributeStr = ''; var watchedAttrs = []; @@ -1126,12 +1132,12 @@ function attributeGenerator(ref, type, data) { * @param {String} data - the title text * @return {Object} - the title generator */ -function titleGenerator(appId, ref, type, data) { +function titleGenerator (appId, ref, type, data) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; return { - text: function text() { + text: function text () { return ("<" + type + ">" + data + "") } } @@ -1144,13 +1150,13 @@ function titleGenerator(appId, ref, type, data) { * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base * @return {Object} - the tag generator */ -function tagGenerator(appId, ref, type, tags) { +function tagGenerator (appId, ref, type, tags) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; var tagIDKeyName = ref.tagIDKeyName; return { - text: function text(ref) { + text: function text (ref) { if ( ref === void 0 ) ref = {}; var body = ref.body; if ( body === void 0 ) body = false; @@ -1179,7 +1185,12 @@ function tagGenerator(appId, ref, type, tags) { prefix = 'data-'; } - return isUndefined(tag[attr]) || booleanHtmlAttributes.includes(attr) + var isBooleanAttr = booleanHtmlAttributes.includes(attr); + if (isBooleanAttr && !tag[attr]) { + return attrsStr + } + + return isBooleanAttr ? (attrsStr + " " + prefix + attr) : (attrsStr + " " + prefix + attr + "=\"" + (tag[attr]) + "\"") }, ''); @@ -1215,7 +1226,7 @@ function tagGenerator(appId, ref, type, tags) { * @return {Object} - the new injector */ -function generateServerInjector(appId, options, type, data) { +function generateServerInjector (appId, options, type, data) { if (type === 'title') { return titleGenerator(appId, options, type, data) } @@ -1227,7 +1238,7 @@ function generateServerInjector(appId, options, type, data) { return tagGenerator(appId, options, type, data) } -function _inject(options) { +function _inject (options) { if ( options === void 0 ) options = {}; /** @@ -1237,7 +1248,7 @@ function _inject(options) { * @this {Object} - Vue instance - ideally the root component * @return {Object} - server meta info with `toString` methods */ - return function inject() { + return function inject () { // get meta info with sensible defaults var metaInfo = getMetaInfo(options, this.$root, serverSequences); @@ -1252,7 +1263,7 @@ function _inject(options) { } } -function _$meta(options) { +function _$meta (options) { if ( options === void 0 ) options = {}; var _refresh$1 = _refresh(options); @@ -1263,7 +1274,7 @@ function _$meta(options) { * @this {Object} - the Vue instance (a root component) * @return {Object} - injector */ - return function $meta() { + return function $meta () { return { getOptions: function () { return getOptions(options); }, refresh: _refresh$1.bind(this), @@ -1278,7 +1289,7 @@ function _$meta(options) { * Plugin install function. * @param {Function} Vue - the Vue constructor. */ -function install(Vue, options) { +function install (Vue, options) { if ( options === void 0 ) options = {}; if (Vue.__vuemeta_installed) { diff --git a/dist/vue-meta.esm.browser.js b/dist/vue-meta.esm.browser.js index 1bb08a7..c75dcd5 100644 --- a/dist/vue-meta.esm.browser.js +++ b/dist/vue-meta.esm.browser.js @@ -1,5 +1,5 @@ /** - * vue-meta v2.0.4 + * vue-meta v2.0.5 * (c) 2019 * - Declan de Wet * - Sébastien Chopin (@Atinux) @@ -9,12 +9,12 @@ import deepmerge from 'deepmerge'; -var version = "2.0.4"; +var version = "2.0.5"; // store an id to keep track of DOM updates let batchId = null; -function triggerUpdate(vm, hookName) { +function triggerUpdate (vm, hookName) { // if an update was triggered during initialization or when an update was triggered by the // metaInfo watcher, set initialized to null // then we keep falsy value but know we need to run a triggerUpdate after initialization @@ -35,7 +35,7 @@ function triggerUpdate(vm, hookName) { * @param {Function} callback - the update to perform * @return {Number} id - a new ID */ -function batchUpdate(callback, timeout = 10) { +function batchUpdate (callback, timeout = 10) { clearTimeout(batchId); batchId = setTimeout(() => { @@ -50,27 +50,27 @@ function batchUpdate(callback, timeout = 10) { * @param {any} arg - the object to check * @return {Boolean} - true if `arg` is an array */ -function isArray(arg) { +function isArray (arg) { return Array.isArray(arg) } -function isUndefined(arg) { +function isUndefined (arg) { return typeof arg === 'undefined' } -function isObject(arg) { +function isObject (arg) { return typeof arg === 'object' } -function isFunction(arg) { +function isFunction (arg) { return typeof arg === 'function' } -function isString(arg) { +function isString (arg) { return typeof arg === 'string' } -function ensureIsArray(arg, key) { +function ensureIsArray (arg, key) { if (!key || !isObject(arg)) { return isArray(arg) ? arg : [] } @@ -81,23 +81,23 @@ function ensureIsArray(arg, key) { return arg } -function ensuredPush(object, key, el) { +function ensuredPush (object, key, el) { ensureIsArray(object, key); object[key].push(el); } // Vue $root instance has a _vueMeta object property, otherwise its a boolean true -function hasMetaInfo(vm = this) { +function hasMetaInfo (vm = this) { return vm && (vm._vueMeta === true || isObject(vm._vueMeta)) } // a component is in a metaInfo branch when itself has meta info or one of its (grand-)children has -function inMetaInfoBranch(vm = this) { +function inMetaInfoBranch (vm = this) { return vm && !isUndefined(vm._vueMeta) } -function addNavGuards(vm) { +function addNavGuards (vm) { // return when nav guards already added or no router exists if (vm.$root._vueMeta.navGuards || !vm.$root.$router) { /* istanbul ignore next */ @@ -124,16 +124,16 @@ function addNavGuards(vm) { let appId = 1; -function createMixin(Vue, options) { +function createMixin (Vue, options) { // for which Vue lifecycle hooks should the metaInfo be refreshed const updateOnLifecycleHook = ['activated', 'deactivated', 'beforeMount']; // watch for client side component updates return { - beforeCreate() { + beforeCreate () { Object.defineProperty(this, '_hasMetaInfo', { configurable: true, - get() { + get () { // Show deprecation warning once when devtools enabled if (Vue.config.devtools && !this.$root._vueMeta.hasMetaInfoDeprecationWarningShown) { console.warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead'); // eslint-disable-line no-console @@ -197,7 +197,7 @@ function createMixin(Vue, options) { ensuredPush(this.$options, 'beforeMount', () => { // if this Vue-app was server rendered, set the appId to 'ssr' // only one SSR app per page is supported - if (this.$root.$el && this.$root.$el.hasAttribute('data-server-rendered')) { + if (this.$root.$el && this.$root.$el.hasAttribute && this.$root.$el.hasAttribute('data-server-rendered')) { this.$root._vueMeta.appId = 'ssr'; } }); @@ -400,7 +400,7 @@ const booleanHtmlAttributes = [ // eslint-disable-next-line no-console const showWarningNotSupported = () => console.warn('This vue app/component has no vue-meta configuration'); -function setOptions(options) { +function setOptions (options) { // combine options options = isObject(options) ? options : {}; @@ -413,7 +413,7 @@ function setOptions(options) { return options } -function getOptions(options) { +function getOptions (options) { const optionsCopy = {}; for (const key in options) { optionsCopy[key] = options[key]; @@ -421,13 +421,13 @@ function getOptions(options) { return optionsCopy } -function pause(refresh = true) { +function pause (refresh = true) { this.$root._vueMeta.paused = true; return () => resume(refresh) } -function resume(refresh = true) { +function resume (refresh = true) { this.$root._vueMeta.paused = false; if (refresh) { @@ -435,7 +435,7 @@ function resume(refresh = true) { } } -function applyTemplate({ component, metaTemplateKeyName, contentKeyName }, headObject, template, chunk) { +function applyTemplate ({ component, metaTemplateKeyName, contentKeyName }, headObject, template, chunk) { if (isUndefined(template)) { template = headObject[metaTemplateKeyName]; delete headObject[metaTemplateKeyName]; @@ -466,28 +466,28 @@ function applyTemplate({ component, metaTemplateKeyName, contentKeyName }, headO * files in server/ still use normal js function */ -function findIndex(array, predicate) { +function findIndex (array, predicate) { return array.findIndex(predicate, arguments[2]) } -function toArray(arg) { +function toArray (arg) { return Array.from(arg) } -function includes(array, value) { +function includes (array, value) { return array.includes(value) } const clientSequences = [ [/&/g, '\u0026'], - [//g, '\u003e'], + [//g, '\u003E'], [/"/g, '\u0022'], [/'/g, '\u0027'] ]; // sanitizes potentially dangerous characters -function escape(info, options, escapeOptions) { +function escape (info, options, escapeOptions) { const { tagIDKeyName } = options; const { doEscape = v => v } = escapeOptions; const escaped = {}; @@ -537,7 +537,7 @@ function escape(info, options, escapeOptions) { return escaped } -function arrayMerge({ component, tagIDKeyName, metaTemplateKeyName, contentKeyName }, target, source) { +function arrayMerge ({ component, tagIDKeyName, metaTemplateKeyName, contentKeyName }, target, source) { // we concat the arrays without merging objects contained in, // but we check for a `vmid` property on each object in the array // using an O(1) lookup associative array exploit @@ -599,7 +599,7 @@ function arrayMerge({ component, tagIDKeyName, metaTemplateKeyName, contentKeyNa return destination.concat(source) } -function merge(target, source, options = {}) { +function merge (target, source, options = {}) { // remove properties explicitly set to false so child components can // optionally _not_ overwrite the parents content // (for array properties this is checked in arrayMerge) @@ -642,7 +642,7 @@ function merge(target, source, options = {}) { * @param {Object} [result={}] - result so far * @return {Object} result - final aggregated result */ -function getComponentOption(options = {}, component, result = {}) { +function getComponentOption (options = {}, component, result = {}) { const { keyName, metaTemplateKeyName, tagIDKeyName } = options; const { $options, $children } = component; @@ -706,7 +706,7 @@ function getComponentOption(options = {}, component, result = {}) { * @param {Object} component - the Vue instance to get meta info from * @return {Object} - returned meta info */ -function getMetaInfo(options = {}, component, escapeSequences = []) { +function getMetaInfo (options = {}, component, escapeSequences = []) { // collect & aggregate all metaInfo $options let info = getComponentOption(options, component, defaultInfo); @@ -756,7 +756,7 @@ function getMetaInfo(options = {}, component, escapeSequences = []) { * @param {Object} attrs - the new document html attributes * @param {HTMLElement} tag - the HTMLElement tag to update with new attrs */ -function updateAttribute({ attribute } = {}, attrs, tag) { +function updateAttribute ({ attribute } = {}, attrs, tag) { const vueMetaAttrString = tag.getAttribute(attribute); const vueMetaAttrs = vueMetaAttrString ? vueMetaAttrString.split(',') : []; const toRemove = toArray(vueMetaAttrs); @@ -798,7 +798,7 @@ function updateAttribute({ attribute } = {}, attrs, tag) { * * @param {String} title - the new title of the document */ -function updateTitle(title) { +function updateTitle (title) { if (title === undefined) { return } @@ -814,7 +814,7 @@ function updateTitle(title) { * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base * @return {Object} - a representation of what tags changed */ -function updateTag(appId, { attribute, tagIDKeyName } = {}, type, tags, headTag, bodyTag) { +function updateTag (appId, { attribute, tagIDKeyName } = {}, type, tags, headTag, bodyTag) { const oldHeadTags = toArray(headTag.querySelectorAll(`${type}[${attribute}="${appId}"], ${type}[data-${tagIDKeyName}]`)); const oldBodyTags = toArray(bodyTag.querySelectorAll(`${type}[${attribute}="${appId}"][data-body="true"], ${type}[data-${tagIDKeyName}][data-body="true"]`)); const dataAttributes = [tagIDKeyName, 'body']; @@ -856,7 +856,13 @@ function updateTag(appId, { attribute, tagIDKeyName } = {}, type, tags, headTag, const _attr = includes(dataAttributes, attr) ? `data-${attr}` : attr; - const value = isUndefined(tag[attr]) || includes(booleanHtmlAttributes, attr) ? '' : tag[attr]; + + const isBooleanAttribute = includes(booleanHtmlAttributes, attr); + if (isBooleanAttribute && !tag[attr]) { + continue + } + + const value = isBooleanAttribute ? '' : tag[attr]; newElement.setAttribute(_attr, value); } } @@ -890,7 +896,7 @@ function updateTag(appId, { attribute, tagIDKeyName } = {}, type, tags, headTag, return { oldTags, newTags } } -function getTag(tags, tag) { +function getTag (tags, tag) { if (!tags[tag]) { tags[tag] = document.getElementsByTagName(tag)[0]; } @@ -903,7 +909,7 @@ function getTag(tags, tag) { * * @param {Object} newInfo - the meta info to update to */ -function updateClientMetaInfo(appId, options = {}, newInfo) { +function updateClientMetaInfo (appId, options = {}, newInfo) { const { ssrAttribute } = options; // only cache tags for current update @@ -963,7 +969,7 @@ function updateClientMetaInfo(appId, options = {}, newInfo) { return { addedTags, removedTags } } -function _refresh(options = {}) { +function _refresh (options = {}) { /** * When called, will update the current meta info with new meta info. * Useful when updating meta info as the result of an asynchronous @@ -974,7 +980,7 @@ function _refresh(options = {}) { * * @return {Object} - new meta info */ - return function refresh() { + return function refresh () { const metaInfo = getMetaInfo(options, this.$root, clientSequences); const appId = this.$root._vueMeta.appId; @@ -988,7 +994,7 @@ function _refresh(options = {}) { } } -function _$meta(options = {}) { +function _$meta (options = {}) { const _refresh$1 = _refresh(options); const inject = () => {}; @@ -997,7 +1003,7 @@ function _$meta(options = {}) { * @this {Object} - the Vue instance (a root component) * @return {Object} - injector */ - return function $meta() { + return function $meta () { if (!this.$root._vueMeta) { return { getOptions: showWarningNotSupported, @@ -1022,7 +1028,7 @@ function _$meta(options = {}) { * Plugin install function. * @param {Function} Vue - the Vue constructor. */ -function install(Vue, options = {}) { +function install (Vue, options = {}) { if (Vue.__vuemeta_installed) { return } diff --git a/dist/vue-meta.esm.browser.min.js b/dist/vue-meta.esm.browser.min.js index 992c582..01b66f7 100644 --- a/dist/vue-meta.esm.browser.min.js +++ b/dist/vue-meta.esm.browser.min.js @@ -1 +1 @@ -import e from"deepmerge";let t=null;function n(e,n){e.$root._vueMeta.initialized||!e.$root._vueMeta.initializing&&"watcher"!==n||(e.$root._vueMeta.initialized=null),e.$root._vueMeta.initialized&&!e.$root._vueMeta.paused&&function(e,n=10){clearTimeout(t),t=setTimeout(()=>{e()},n)}(()=>e.$meta().refresh())}function i(e){return Array.isArray(e)}function o(e){return void 0===e}function a(e){return"object"==typeof e}function r(e){return"function"==typeof e}function s(e,t){return t&&a(e)?(i(e[t])||(e[t]=[]),e):i(e)?e:[]}function u(e,t,n){s(e,t),e[t].push(n)}function c(e=this){return e&&(!0===e._vueMeta||a(e._vueMeta))}function l(e){if(e.$root._vueMeta.navGuards||!e.$root.$router)return;e.$root._vueMeta.navGuards=!0;const t=e.$root.$router,n=e.$root.$meta();t.beforeEach((e,t,i)=>{n.pause(),i()}),t.afterEach(()=>{const{metaInfo:e}=n.resume();e&&e.afterNavigation&&r(e.afterNavigation)&&e.afterNavigation(e)})}let d=1;const h={title:void 0,titleChunk:"",titleTemplate:"%s",htmlAttrs:{},bodyAttrs:{},headAttrs:{},base:[],link:[],meta:[],style:[],script:[],noscript:[],__dangerouslyDisableSanitizers:[],__dangerouslyDisableSanitizersByTagID:{}},f={keyName:"metaInfo",attribute:"data-vue-meta",ssrAttribute:"data-vue-meta-server-rendered",tagIDKeyName:"vmid",contentKeyName:"content",metaTemplateKeyName:"template"},m=["titleChunk","titleTemplate","changed","__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],p=["__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],v=["htmlAttrs","headAttrs","bodyAttrs"],$=["allowfullscreen","amp","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","truespeed","typemustmatch","visible"],y=()=>console.warn("This vue app/component has no vue-meta configuration");function g(e=!0){return this.$root._vueMeta.paused=!0,()=>b(e)}function b(e=!0){if(this.$root._vueMeta.paused=!1,e)return this.$root.$meta().refresh()}function _({component:e,metaTemplateKeyName:t,contentKeyName:n},i,a,s){return o(a)&&(a=i[t],delete i[t]),!!a&&(o(s)&&(s=i[n]),i[n]=r(a)?a.call(e,s):a.replace(/%s/g,s),!0)}function M(e,t){return e.findIndex(t,arguments[2])}function T(e){return Array.from(e)}function N(e,t){return e.includes(t)}const w=[[/&/g,"&"],[//g,">"],[/"/g,'"'],[/'/g,"'"]];function I(t,n,i={}){return n.hasOwnProperty("title")&&void 0===n.title&&delete n.title,v.forEach(e=>{if(n[e])for(const t in n[e])n[e].hasOwnProperty(t)&&void 0===n[e][t]&&($.includes(t)&&console.warn("VueMeta: Please note that since v2 the value undefined is not used to indicate boolean attributes anymore, see migration guide for details"),delete n[e][t])}),e(t,n,{arrayMerge:(e,t)=>(function({component:e,tagIDKeyName:t,metaTemplateKeyName:n,contentKeyName:i},o,a){const r=[];return o.forEach((o,s)=>{if(!o[t])return void r.push(o);const u=M(a,e=>e[t]===o[t]),c=a[u];if(-1===u)return void r.push(o);if(c.hasOwnProperty(i)&&void 0===c[i]||c.hasOwnProperty("innerHTML")&&void 0===c.innerHTML)return r.push(o),void a.splice(u,1);if(null===c[i]||null===c.innerHTML)return void a.splice(u,1);const l=o[n];l&&(c[n]?c[i]||_({component:e,metaTemplateKeyName:n,contentKeyName:i},c,void 0,o[i]):_({component:e,metaTemplateKeyName:n,contentKeyName:i},c,l))}),r.concat(a)})(i,e,t)})}function A(e={},t,n={}){const{keyName:i,metaTemplateKeyName:s,tagIDKeyName:u}=e,{$options:c,$children:l}=t;if(t._inactive)return n;if(c[i]){let o=c[i];if(r(o)&&(o=o.call(t)),!a(o))return n;n=I(n,o,e)}return l.length&&l.forEach(t=>{(function(e=this){return e&&!o(e._vueMeta)})(t)&&(n=A(e,t,n))}),s&&n.meta&&(n.meta.forEach(t=>_(e,t)),n.meta=n.meta.filter((e,t,n)=>!e.hasOwnProperty(u)||t===M(n,t=>t[u]===e[u]))),n}function z(e={},t,n=[]){let o=A(e,t,h);o.title&&(o.titleChunk=o.title),o.titleTemplate&&"%s"!==o.titleTemplate&&_({component:t,contentKeyName:"title"},o,o.titleTemplate,o.titleChunk||""),o.base&&(o.base=Object.keys(o.base).length?[o.base]:[]);const r={doEscape:e=>n.reduce((e,[t,n])=>e.replace(t,n),e)};return p.forEach((e,t)=>{if(0===t)s(o,e);else if(1===t)for(const t in o[e])s(o[e],t);r[e]=o[e]}),o=function e(t,n,o){const{tagIDKeyName:r}=n,{doEscape:s=(e=>e)}=o,u={};for(const c in t){const l=t[c];if(N(m,c)){u[c]=l;continue}let[d]=p;if(o[d]&&N(o[d],c)){u[c]=l;continue}const h=t[r];h&&(d=p[1],o[d]&&o[d][h]&&N(o[d][h],c))?u[c]=l:"string"==typeof l?u[c]=s(l):i(l)?u[c]=l.map(t=>a(t)?e(t,n,o):s(t)):a(l)?u[c]=e(l,n,o):u[c]=l}return u}(o,e,r)}function D({attribute:e}={},t,n){const o=n.getAttribute(e),a=o?o.split(","):[],r=T(a),s=[];for(const e in t)if(t.hasOwnProperty(e)){const o=N($,e)?"":i(t[e])?t[e].join(" "):t[e];n.setAttribute(e,o||""),N(a,e)||a.push(e),s.push(r.indexOf(e))}const u=r.filter((e,t)=>!N(s,t)).reduce((e,t)=>(n.removeAttribute(t),e+1),0);a.length===u?n.removeAttribute(e):n.setAttribute(e,a.sort().join(","))}function K(e,{attribute:t,tagIDKeyName:n}={},i,a,r,s){const u=T(r.querySelectorAll(`${i}[${t}="${e}"], ${i}[data-${n}]`)),c=T(s.querySelectorAll(`${i}[${t}="${e}"][data-body="true"], ${i}[data-${n}][data-body="true"]`)),l=[n,"body"],d=[];if(a.length>1){const e=[];a=a.filter(t=>{const n=JSON.stringify(t),i=!N(e,n);return e.push(n),i})}a.length&&a.forEach(n=>{const a=document.createElement(i);a.setAttribute(t,e);const r=!0!==n.body?u:c;for(const e in n)if(n.hasOwnProperty(e))if("innerHTML"===e)a.innerHTML=n.innerHTML;else if("cssText"===e)a.styleSheet?a.styleSheet.cssText=n.cssText:a.appendChild(document.createTextNode(n.cssText));else{const t=N(l,e)?`data-${e}`:e,i=o(n[e])||N($,e)?"":n[e];a.setAttribute(t,i)}let s;r.some((e,t)=>(s=t,a.isEqualNode(e)))&&(s||0===s)?r.splice(s,1):d.push(a)});const h=u.concat(c);return h.forEach(e=>e.parentNode.removeChild(e)),d.forEach(e=>{"true"===e.getAttribute("data-body")?s.appendChild(e):r.appendChild(e)}),{oldTags:h,newTags:d}}function O(e,t){return e[t]||(e[t]=document.getElementsByTagName(t)[0]),e[t]}function k(e={}){return function(){const t=z(e,this.$root,w),n=function(e,t={},n){const{ssrAttribute:o}=t,a={},r=O(a,"html");if("ssr"===e&&r.hasAttribute(o))return r.removeAttribute(o),!1;const s={},u={};for(const o in n){if(N(m,o))continue;if("title"===o){void 0!==(c=n.title)&&(document.title=c);continue}if(N(v,o)){const e=o.substr(0,4);D(t,n[o],O(a,e));continue}if(!i(n[o]))continue;const{oldTags:r,newTags:l}=K(e,t,o,n[o],O(a,"head"),O(a,"body"));l.length&&(s[o]=l,u[o]=r)}var c;return{addedTags:s,removedTags:u}}(this.$root._vueMeta.appId,e,t);return n&&r(t.changed)&&t.changed(t,n.addedTags,n.removedTags),{vm:this,metaInfo:t,tags:n}}}function E(e,t={}){e.__vuemeta_installed||(e.__vuemeta_installed=!0,t=function(e){e=a(e)?e:{};for(const t in f)e[t]||(e[t]=f[t]);return e}(t),e.prototype.$meta=function(e={}){const t=k(e),n=()=>{};return function(){return this.$root._vueMeta?{getOptions:()=>(function(e){const t={};for(const n in e)t[n]=e[n];return t})(e),refresh:t.bind(this),inject:n,pause:g.bind(this),resume:b.bind(this)}:{getOptions:y,refresh:y,inject:y,pause:y,resume:y}}}(t),e.mixin(function(e,t){const i=["activated","deactivated","beforeMount"];return{beforeCreate(){if(Object.defineProperty(this,"_hasMetaInfo",{configurable:!0,get(){return e.config.devtools&&!this.$root._vueMeta.hasMetaInfoDeprecationWarningShown&&(console.warn("VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead"),this.$root._vueMeta.hasMetaInfoDeprecationWarningShown=!0),c(this)}}),!o(this.$options[t.keyName])&&null!==this.$options[t.keyName]){if(this.$root._vueMeta||(this.$root._vueMeta={appId:d},d++),!this._vueMeta){this._vueMeta=!0;let e=this.$parent;for(;e&&e!==this.$root;)o(e._vueMeta)&&(e._vueMeta=!1),e=e.$parent}r(this.$options[t.keyName])&&(this.$options.computed||(this.$options.computed={}),this.$options.computed.$metaInfo=this.$options[t.keyName],this.$isServer||u(this.$options,"created",()=>{this.$watch("$metaInfo",function(){n(this,"watcher")})})),o(this.$root._vueMeta.initialized)&&(this.$root._vueMeta.initialized=this.$isServer,this.$root._vueMeta.initialized||(u(this.$options,"beforeMount",()=>{this.$root.$el&&this.$root.$el.hasAttribute("data-server-rendered")&&(this.$root._vueMeta.appId="ssr")}),u(this.$options,"mounted",()=>{this.$root._vueMeta.initialized||(this.$root._vueMeta.initializing=!0,this.$nextTick(function(){const{tags:e,metaInfo:i}=this.$root.$meta().refresh();!1===e&&null===this.$root._vueMeta.initialized&&this.$nextTick(()=>n(this,"initializing")),this.$root._vueMeta.initialized=!0,delete this.$root._vueMeta.initializing,!t.refreshOnceOnNavigation&&i.afterNavigation&&l(this)}))}),t.refreshOnceOnNavigation&&l(this))),this.$isServer||(i.forEach(e=>{u(this.$options,e,()=>n(this,e))}),u(this.$options,"destroyed",()=>{const e=setInterval(()=>{this.$el&&null!==this.$el.offsetParent||(clearInterval(e),this.$parent&&n(this,"destroyed"))},50)}))}}}}(e,t)))}o(window)||o(window.Vue)||E(window.Vue);export default{version:"2.0.4",install:E,hasMetaInfo:c}; +import e from"deepmerge";let t=null;function n(e,n){e.$root._vueMeta.initialized||!e.$root._vueMeta.initializing&&"watcher"!==n||(e.$root._vueMeta.initialized=null),e.$root._vueMeta.initialized&&!e.$root._vueMeta.paused&&function(e,n=10){clearTimeout(t),t=setTimeout(()=>{e()},n)}(()=>e.$meta().refresh())}function i(e){return Array.isArray(e)}function o(e){return void 0===e}function a(e){return"object"==typeof e}function r(e){return"function"==typeof e}function s(e,t){return t&&a(e)?(i(e[t])||(e[t]=[]),e):i(e)?e:[]}function u(e,t,n){s(e,t),e[t].push(n)}function c(e=this){return e&&(!0===e._vueMeta||a(e._vueMeta))}function l(e){if(e.$root._vueMeta.navGuards||!e.$root.$router)return;e.$root._vueMeta.navGuards=!0;const t=e.$root.$router,n=e.$root.$meta();t.beforeEach((e,t,i)=>{n.pause(),i()}),t.afterEach(()=>{const{metaInfo:e}=n.resume();e&&e.afterNavigation&&r(e.afterNavigation)&&e.afterNavigation(e)})}let d=1;const h={title:void 0,titleChunk:"",titleTemplate:"%s",htmlAttrs:{},bodyAttrs:{},headAttrs:{},base:[],link:[],meta:[],style:[],script:[],noscript:[],__dangerouslyDisableSanitizers:[],__dangerouslyDisableSanitizersByTagID:{}},f={keyName:"metaInfo",attribute:"data-vue-meta",ssrAttribute:"data-vue-meta-server-rendered",tagIDKeyName:"vmid",contentKeyName:"content",metaTemplateKeyName:"template"},m=["titleChunk","titleTemplate","changed","__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],p=["__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],v=["htmlAttrs","headAttrs","bodyAttrs"],$=["allowfullscreen","amp","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","truespeed","typemustmatch","visible"],y=()=>console.warn("This vue app/component has no vue-meta configuration");function g(e=!0){return this.$root._vueMeta.paused=!0,()=>b(e)}function b(e=!0){if(this.$root._vueMeta.paused=!1,e)return this.$root.$meta().refresh()}function _({component:e,metaTemplateKeyName:t,contentKeyName:n},i,a,s){return o(a)&&(a=i[t],delete i[t]),!!a&&(o(s)&&(s=i[n]),i[n]=r(a)?a.call(e,s):a.replace(/%s/g,s),!0)}function M(e,t){return e.findIndex(t,arguments[2])}function T(e){return Array.from(e)}function N(e,t){return e.includes(t)}const w=[[/&/g,"&"],[//g,">"],[/"/g,'"'],[/'/g,"'"]];function I(t,n,i={}){return n.hasOwnProperty("title")&&void 0===n.title&&delete n.title,v.forEach(e=>{if(n[e])for(const t in n[e])n[e].hasOwnProperty(t)&&void 0===n[e][t]&&($.includes(t)&&console.warn("VueMeta: Please note that since v2 the value undefined is not used to indicate boolean attributes anymore, see migration guide for details"),delete n[e][t])}),e(t,n,{arrayMerge:(e,t)=>(function({component:e,tagIDKeyName:t,metaTemplateKeyName:n,contentKeyName:i},o,a){const r=[];return o.forEach((o,s)=>{if(!o[t])return void r.push(o);const u=M(a,e=>e[t]===o[t]),c=a[u];if(-1===u)return void r.push(o);if(c.hasOwnProperty(i)&&void 0===c[i]||c.hasOwnProperty("innerHTML")&&void 0===c.innerHTML)return r.push(o),void a.splice(u,1);if(null===c[i]||null===c.innerHTML)return void a.splice(u,1);const l=o[n];l&&(c[n]?c[i]||_({component:e,metaTemplateKeyName:n,contentKeyName:i},c,void 0,o[i]):_({component:e,metaTemplateKeyName:n,contentKeyName:i},c,l))}),r.concat(a)})(i,e,t)})}function A(e={},t,n={}){const{keyName:i,metaTemplateKeyName:s,tagIDKeyName:u}=e,{$options:c,$children:l}=t;if(t._inactive)return n;if(c[i]){let o=c[i];if(r(o)&&(o=o.call(t)),!a(o))return n;n=I(n,o,e)}return l.length&&l.forEach(t=>{(function(e=this){return e&&!o(e._vueMeta)})(t)&&(n=A(e,t,n))}),s&&n.meta&&(n.meta.forEach(t=>_(e,t)),n.meta=n.meta.filter((e,t,n)=>!e.hasOwnProperty(u)||t===M(n,t=>t[u]===e[u]))),n}function z(e={},t,n=[]){let o=A(e,t,h);o.title&&(o.titleChunk=o.title),o.titleTemplate&&"%s"!==o.titleTemplate&&_({component:t,contentKeyName:"title"},o,o.titleTemplate,o.titleChunk||""),o.base&&(o.base=Object.keys(o.base).length?[o.base]:[]);const r={doEscape:e=>n.reduce((e,[t,n])=>e.replace(t,n),e)};return p.forEach((e,t)=>{if(0===t)s(o,e);else if(1===t)for(const t in o[e])s(o[e],t);r[e]=o[e]}),o=function e(t,n,o){const{tagIDKeyName:r}=n,{doEscape:s=(e=>e)}=o,u={};for(const c in t){const l=t[c];if(N(m,c)){u[c]=l;continue}let[d]=p;if(o[d]&&N(o[d],c)){u[c]=l;continue}const h=t[r];h&&(d=p[1],o[d]&&o[d][h]&&N(o[d][h],c))?u[c]=l:"string"==typeof l?u[c]=s(l):i(l)?u[c]=l.map(t=>a(t)?e(t,n,o):s(t)):a(l)?u[c]=e(l,n,o):u[c]=l}return u}(o,e,r)}function D({attribute:e}={},t,n){const o=n.getAttribute(e),a=o?o.split(","):[],r=T(a),s=[];for(const e in t)if(t.hasOwnProperty(e)){const o=N($,e)?"":i(t[e])?t[e].join(" "):t[e];n.setAttribute(e,o||""),N(a,e)||a.push(e),s.push(r.indexOf(e))}const u=r.filter((e,t)=>!N(s,t)).reduce((e,t)=>(n.removeAttribute(t),e+1),0);a.length===u?n.removeAttribute(e):n.setAttribute(e,a.sort().join(","))}function K(e,{attribute:t,tagIDKeyName:n}={},i,o,a,r){const s=T(a.querySelectorAll(`${i}[${t}="${e}"], ${i}[data-${n}]`)),u=T(r.querySelectorAll(`${i}[${t}="${e}"][data-body="true"], ${i}[data-${n}][data-body="true"]`)),c=[n,"body"],l=[];if(o.length>1){const e=[];o=o.filter(t=>{const n=JSON.stringify(t),i=!N(e,n);return e.push(n),i})}o.length&&o.forEach(n=>{const o=document.createElement(i);o.setAttribute(t,e);const a=!0!==n.body?s:u;for(const e in n)if(n.hasOwnProperty(e))if("innerHTML"===e)o.innerHTML=n.innerHTML;else if("cssText"===e)o.styleSheet?o.styleSheet.cssText=n.cssText:o.appendChild(document.createTextNode(n.cssText));else{const t=N(c,e)?`data-${e}`:e,i=N($,e);if(i&&!n[e])continue;const a=i?"":n[e];o.setAttribute(t,a)}let r;a.some((e,t)=>(r=t,o.isEqualNode(e)))&&(r||0===r)?a.splice(r,1):l.push(o)});const d=s.concat(u);return d.forEach(e=>e.parentNode.removeChild(e)),l.forEach(e=>{"true"===e.getAttribute("data-body")?r.appendChild(e):a.appendChild(e)}),{oldTags:d,newTags:l}}function O(e,t){return e[t]||(e[t]=document.getElementsByTagName(t)[0]),e[t]}function k(e={}){return function(){const t=z(e,this.$root,w),n=function(e,t={},n){const{ssrAttribute:o}=t,a={},r=O(a,"html");if("ssr"===e&&r.hasAttribute(o))return r.removeAttribute(o),!1;const s={},u={};for(const o in n){if(N(m,o))continue;if("title"===o){void 0!==(c=n.title)&&(document.title=c);continue}if(N(v,o)){const e=o.substr(0,4);D(t,n[o],O(a,e));continue}if(!i(n[o]))continue;const{oldTags:r,newTags:l}=K(e,t,o,n[o],O(a,"head"),O(a,"body"));l.length&&(s[o]=l,u[o]=r)}var c;return{addedTags:s,removedTags:u}}(this.$root._vueMeta.appId,e,t);return n&&r(t.changed)&&t.changed(t,n.addedTags,n.removedTags),{vm:this,metaInfo:t,tags:n}}}function E(e,t={}){e.__vuemeta_installed||(e.__vuemeta_installed=!0,t=function(e){e=a(e)?e:{};for(const t in f)e[t]||(e[t]=f[t]);return e}(t),e.prototype.$meta=function(e={}){const t=k(e),n=()=>{};return function(){return this.$root._vueMeta?{getOptions:()=>(function(e){const t={};for(const n in e)t[n]=e[n];return t})(e),refresh:t.bind(this),inject:n,pause:g.bind(this),resume:b.bind(this)}:{getOptions:y,refresh:y,inject:y,pause:y,resume:y}}}(t),e.mixin(function(e,t){const i=["activated","deactivated","beforeMount"];return{beforeCreate(){if(Object.defineProperty(this,"_hasMetaInfo",{configurable:!0,get(){return e.config.devtools&&!this.$root._vueMeta.hasMetaInfoDeprecationWarningShown&&(console.warn("VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead"),this.$root._vueMeta.hasMetaInfoDeprecationWarningShown=!0),c(this)}}),!o(this.$options[t.keyName])&&null!==this.$options[t.keyName]){if(this.$root._vueMeta||(this.$root._vueMeta={appId:d},d++),!this._vueMeta){this._vueMeta=!0;let e=this.$parent;for(;e&&e!==this.$root;)o(e._vueMeta)&&(e._vueMeta=!1),e=e.$parent}r(this.$options[t.keyName])&&(this.$options.computed||(this.$options.computed={}),this.$options.computed.$metaInfo=this.$options[t.keyName],this.$isServer||u(this.$options,"created",()=>{this.$watch("$metaInfo",function(){n(this,"watcher")})})),o(this.$root._vueMeta.initialized)&&(this.$root._vueMeta.initialized=this.$isServer,this.$root._vueMeta.initialized||(u(this.$options,"beforeMount",()=>{this.$root.$el&&this.$root.$el.hasAttribute&&this.$root.$el.hasAttribute("data-server-rendered")&&(this.$root._vueMeta.appId="ssr")}),u(this.$options,"mounted",()=>{this.$root._vueMeta.initialized||(this.$root._vueMeta.initializing=!0,this.$nextTick(function(){const{tags:e,metaInfo:i}=this.$root.$meta().refresh();!1===e&&null===this.$root._vueMeta.initialized&&this.$nextTick(()=>n(this,"initializing")),this.$root._vueMeta.initialized=!0,delete this.$root._vueMeta.initializing,!t.refreshOnceOnNavigation&&i.afterNavigation&&l(this)}))}),t.refreshOnceOnNavigation&&l(this))),this.$isServer||(i.forEach(e=>{u(this.$options,e,()=>n(this,e))}),u(this.$options,"destroyed",()=>{const e=setInterval(()=>{this.$el&&null!==this.$el.offsetParent||(clearInterval(e),this.$parent&&n(this,"destroyed"))},50)}))}}}}(e,t)))}o(window)||o(window.Vue)||E(window.Vue);var S={version:"2.0.5",install:E,hasMetaInfo:c};export default S; diff --git a/dist/vue-meta.esm.js b/dist/vue-meta.esm.js index 3d218d8..e83fd1a 100644 --- a/dist/vue-meta.esm.js +++ b/dist/vue-meta.esm.js @@ -1,5 +1,5 @@ /** - * vue-meta v2.0.4 + * vue-meta v2.0.5 * (c) 2019 * - Declan de Wet * - Sébastien Chopin (@Atinux) @@ -9,12 +9,12 @@ import deepmerge from 'deepmerge'; -var version = "2.0.4"; +var version = "2.0.5"; // store an id to keep track of DOM updates var batchId = null; -function triggerUpdate(vm, hookName) { +function triggerUpdate (vm, hookName) { // if an update was triggered during initialization or when an update was triggered by the // metaInfo watcher, set initialized to null // then we keep falsy value but know we need to run a triggerUpdate after initialization @@ -35,7 +35,7 @@ function triggerUpdate(vm, hookName) { * @param {Function} callback - the update to perform * @return {Number} id - a new ID */ -function batchUpdate(callback, timeout) { +function batchUpdate (callback, timeout) { if ( timeout === void 0 ) timeout = 10; clearTimeout(batchId); @@ -52,27 +52,27 @@ function batchUpdate(callback, timeout) { * @param {any} arg - the object to check * @return {Boolean} - true if `arg` is an array */ -function isArray(arg) { +function isArray (arg) { return Array.isArray(arg) } -function isUndefined(arg) { +function isUndefined (arg) { return typeof arg === 'undefined' } -function isObject(arg) { +function isObject (arg) { return typeof arg === 'object' } -function isFunction(arg) { +function isFunction (arg) { return typeof arg === 'function' } -function isString(arg) { +function isString (arg) { return typeof arg === 'string' } -function ensureIsArray(arg, key) { +function ensureIsArray (arg, key) { if (!key || !isObject(arg)) { return isArray(arg) ? arg : [] } @@ -83,27 +83,27 @@ function ensureIsArray(arg, key) { return arg } -function ensuredPush(object, key, el) { +function ensuredPush (object, key, el) { ensureIsArray(object, key); object[key].push(el); } // Vue $root instance has a _vueMeta object property, otherwise its a boolean true -function hasMetaInfo(vm) { +function hasMetaInfo (vm) { if ( vm === void 0 ) vm = this; return vm && (vm._vueMeta === true || isObject(vm._vueMeta)) } // a component is in a metaInfo branch when itself has meta info or one of its (grand-)children has -function inMetaInfoBranch(vm) { +function inMetaInfoBranch (vm) { if ( vm === void 0 ) vm = this; return vm && !isUndefined(vm._vueMeta) } -function addNavGuards(vm) { +function addNavGuards (vm) { // return when nav guards already added or no router exists if (vm.$root._vueMeta.navGuards || !vm.$root.$router) { /* istanbul ignore next */ @@ -131,18 +131,18 @@ function addNavGuards(vm) { var appId = 1; -function createMixin(Vue, options) { +function createMixin (Vue, options) { // for which Vue lifecycle hooks should the metaInfo be refreshed var updateOnLifecycleHook = ['activated', 'deactivated', 'beforeMount']; // watch for client side component updates return { - beforeCreate: function beforeCreate() { + beforeCreate: function beforeCreate () { var this$1 = this; Object.defineProperty(this, '_hasMetaInfo', { configurable: true, - get: function get() { + get: function get () { // Show deprecation warning once when devtools enabled if (Vue.config.devtools && !this.$root._vueMeta.hasMetaInfoDeprecationWarningShown) { console.warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead'); // eslint-disable-line no-console @@ -206,7 +206,7 @@ function createMixin(Vue, options) { ensuredPush(this.$options, 'beforeMount', function () { // if this Vue-app was server rendered, set the appId to 'ssr' // only one SSR app per page is supported - if (this$1.$root.$el && this$1.$root.$el.hasAttribute('data-server-rendered')) { + if (this$1.$root.$el && this$1.$root.$el.hasAttribute && this$1.$root.$el.hasAttribute('data-server-rendered')) { this$1.$root._vueMeta.appId = 'ssr'; } }); @@ -420,7 +420,7 @@ var booleanHtmlAttributes = [ 'visible' ]; -function setOptions(options) { +function setOptions (options) { // combine options options = isObject(options) ? options : {}; @@ -433,7 +433,7 @@ function setOptions(options) { return options } -function getOptions(options) { +function getOptions (options) { var optionsCopy = {}; for (var key in options) { optionsCopy[key] = options[key]; @@ -441,7 +441,7 @@ function getOptions(options) { return optionsCopy } -function pause(refresh) { +function pause (refresh) { if ( refresh === void 0 ) refresh = true; this.$root._vueMeta.paused = true; @@ -449,7 +449,7 @@ function pause(refresh) { return function () { return resume(refresh); } } -function resume(refresh) { +function resume (refresh) { if ( refresh === void 0 ) refresh = true; this.$root._vueMeta.paused = false; @@ -459,7 +459,7 @@ function resume(refresh) { } } -function applyTemplate(ref, headObject, template, chunk) { +function applyTemplate (ref, headObject, template, chunk) { var component = ref.component; var metaTemplateKeyName = ref.metaTemplateKeyName; var contentKeyName = ref.contentKeyName; @@ -494,7 +494,7 @@ function applyTemplate(ref, headObject, template, chunk) { * files in server/ still use normal js function */ -function findIndex(array, predicate) { +function findIndex (array, predicate) { var arguments$1 = arguments; if ( !Array.prototype.findIndex) { @@ -509,14 +509,14 @@ function findIndex(array, predicate) { return array.findIndex(predicate, arguments[2]) } -function toArray(arg) { +function toArray (arg) { if ( !Array.from) { return Array.prototype.slice.call(arg) } return Array.from(arg) } -function includes(array, value) { +function includes (array, value) { if ( !Array.prototype.includes) { for (var idx in array) { if (array[idx] === value) { @@ -539,14 +539,14 @@ var serverSequences = [ var clientSequences = [ [/&/g, '\u0026'], - [//g, '\u003e'], + [//g, '\u003E'], [/"/g, '\u0022'], [/'/g, '\u0027'] ]; // sanitizes potentially dangerous characters -function escape(info, options, escapeOptions) { +function escape (info, options, escapeOptions) { var tagIDKeyName = options.tagIDKeyName; var doEscape = escapeOptions.doEscape; if ( doEscape === void 0 ) doEscape = function (v) { return v; }; var escaped = {}; @@ -596,7 +596,7 @@ function escape(info, options, escapeOptions) { return escaped } -function arrayMerge(ref, target, source) { +function arrayMerge (ref, target, source) { var component = ref.component; var tagIDKeyName = ref.tagIDKeyName; var metaTemplateKeyName = ref.metaTemplateKeyName; @@ -663,7 +663,7 @@ function arrayMerge(ref, target, source) { return destination.concat(source) } -function merge(target, source, options) { +function merge (target, source, options) { if ( options === void 0 ) options = {}; // remove properties explicitly set to false so child components can @@ -708,7 +708,7 @@ function merge(target, source, options) { * @param {Object} [result={}] - result so far * @return {Object} result - final aggregated result */ -function getComponentOption(options, component, result) { +function getComponentOption (options, component, result) { if ( options === void 0 ) options = {}; if ( result === void 0 ) result = {}; @@ -778,7 +778,7 @@ function getComponentOption(options, component, result) { * @param {Object} component - the Vue instance to get meta info from * @return {Object} - returned meta info */ -function getMetaInfo(options, component, escapeSequences) { +function getMetaInfo (options, component, escapeSequences) { if ( options === void 0 ) options = {}; if ( escapeSequences === void 0 ) escapeSequences = []; @@ -836,7 +836,7 @@ function getMetaInfo(options, component, escapeSequences) { * @param {Object} attrs - the new document html attributes * @param {HTMLElement} tag - the HTMLElement tag to update with new attrs */ -function updateAttribute(ref, attrs, tag) { +function updateAttribute (ref, attrs, tag) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; @@ -881,7 +881,7 @@ function updateAttribute(ref, attrs, tag) { * * @param {String} title - the new title of the document */ -function updateTitle(title) { +function updateTitle (title) { if (title === undefined) { return } @@ -897,7 +897,7 @@ function updateTitle(title) { * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base * @return {Object} - a representation of what tags changed */ -function updateTag(appId, ref, type, tags, headTag, bodyTag) { +function updateTag (appId, ref, type, tags, headTag, bodyTag) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; var tagIDKeyName = ref.tagIDKeyName; @@ -943,7 +943,13 @@ function updateTag(appId, ref, type, tags, headTag, bodyTag) { var _attr = includes(dataAttributes, attr) ? ("data-" + attr) : attr; - var value = isUndefined(tag[attr]) || includes(booleanHtmlAttributes, attr) ? '' : tag[attr]; + + var isBooleanAttribute = includes(booleanHtmlAttributes, attr); + if (isBooleanAttribute && !tag[attr]) { + continue + } + + var value = isBooleanAttribute ? '' : tag[attr]; newElement.setAttribute(_attr, value); } } @@ -977,7 +983,7 @@ function updateTag(appId, ref, type, tags, headTag, bodyTag) { return { oldTags: oldTags, newTags: newTags } } -function getTag(tags, tag) { +function getTag (tags, tag) { if (!tags[tag]) { tags[tag] = document.getElementsByTagName(tag)[0]; } @@ -990,7 +996,7 @@ function getTag(tags, tag) { * * @param {Object} newInfo - the meta info to update to */ -function updateClientMetaInfo(appId, options, newInfo) { +function updateClientMetaInfo (appId, options, newInfo) { if ( options === void 0 ) options = {}; var ssrAttribute = options.ssrAttribute; @@ -1054,7 +1060,7 @@ function updateClientMetaInfo(appId, options, newInfo) { return { addedTags: addedTags, removedTags: removedTags } } -function _refresh(options) { +function _refresh (options) { if ( options === void 0 ) options = {}; /** @@ -1067,7 +1073,7 @@ function _refresh(options) { * * @return {Object} - new meta info */ - return function refresh() { + return function refresh () { var metaInfo = getMetaInfo(options, this.$root, clientSequences); var appId = this.$root._vueMeta.appId; @@ -1088,12 +1094,12 @@ function _refresh(options) { * @param {Object} data - the attributes to generate * @return {Object} - the attribute generator */ -function attributeGenerator(ref, type, data) { +function attributeGenerator (ref, type, data) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; return { - text: function text() { + text: function text () { var attributeStr = ''; var watchedAttrs = []; @@ -1122,12 +1128,12 @@ function attributeGenerator(ref, type, data) { * @param {String} data - the title text * @return {Object} - the title generator */ -function titleGenerator(appId, ref, type, data) { +function titleGenerator (appId, ref, type, data) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; return { - text: function text() { + text: function text () { return ("<" + type + ">" + data + "") } } @@ -1140,13 +1146,13 @@ function titleGenerator(appId, ref, type, data) { * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base * @return {Object} - the tag generator */ -function tagGenerator(appId, ref, type, tags) { +function tagGenerator (appId, ref, type, tags) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; var tagIDKeyName = ref.tagIDKeyName; return { - text: function text(ref) { + text: function text (ref) { if ( ref === void 0 ) ref = {}; var body = ref.body; if ( body === void 0 ) body = false; @@ -1175,7 +1181,12 @@ function tagGenerator(appId, ref, type, tags) { prefix = 'data-'; } - return isUndefined(tag[attr]) || booleanHtmlAttributes.includes(attr) + var isBooleanAttr = booleanHtmlAttributes.includes(attr); + if (isBooleanAttr && !tag[attr]) { + return attrsStr + } + + return isBooleanAttr ? (attrsStr + " " + prefix + attr) : (attrsStr + " " + prefix + attr + "=\"" + (tag[attr]) + "\"") }, ''); @@ -1211,7 +1222,7 @@ function tagGenerator(appId, ref, type, tags) { * @return {Object} - the new injector */ -function generateServerInjector(appId, options, type, data) { +function generateServerInjector (appId, options, type, data) { if (type === 'title') { return titleGenerator(appId, options, type, data) } @@ -1223,7 +1234,7 @@ function generateServerInjector(appId, options, type, data) { return tagGenerator(appId, options, type, data) } -function _inject(options) { +function _inject (options) { if ( options === void 0 ) options = {}; /** @@ -1233,7 +1244,7 @@ function _inject(options) { * @this {Object} - Vue instance - ideally the root component * @return {Object} - server meta info with `toString` methods */ - return function inject() { + return function inject () { // get meta info with sensible defaults var metaInfo = getMetaInfo(options, this.$root, serverSequences); @@ -1248,7 +1259,7 @@ function _inject(options) { } } -function _$meta(options) { +function _$meta (options) { if ( options === void 0 ) options = {}; var _refresh$1 = _refresh(options); @@ -1259,7 +1270,7 @@ function _$meta(options) { * @this {Object} - the Vue instance (a root component) * @return {Object} - injector */ - return function $meta() { + return function $meta () { return { getOptions: function () { return getOptions(options); }, refresh: _refresh$1.bind(this), @@ -1274,7 +1285,7 @@ function _$meta(options) { * Plugin install function. * @param {Function} Vue - the Vue constructor. */ -function install(Vue, options) { +function install (Vue, options) { if ( options === void 0 ) options = {}; if (Vue.__vuemeta_installed) { diff --git a/dist/vue-meta.js b/dist/vue-meta.js index 9114006..a255c38 100644 --- a/dist/vue-meta.js +++ b/dist/vue-meta.js @@ -1,5 +1,5 @@ /** - * vue-meta v2.0.4 + * vue-meta v2.0.5 * (c) 2019 * - Declan de Wet * - Sébastien Chopin (@Atinux) @@ -13,12 +13,12 @@ (global = global || self, global.VueMeta = factory()); }(this, function () { 'use strict'; - var version = "2.0.4"; + var version = "2.0.5"; // store an id to keep track of DOM updates var batchId = null; - function triggerUpdate(vm, hookName) { + function triggerUpdate (vm, hookName) { // if an update was triggered during initialization or when an update was triggered by the // metaInfo watcher, set initialized to null // then we keep falsy value but know we need to run a triggerUpdate after initialization @@ -39,7 +39,7 @@ * @param {Function} callback - the update to perform * @return {Number} id - a new ID */ - function batchUpdate(callback, timeout) { + function batchUpdate (callback, timeout) { if ( timeout === void 0 ) timeout = 10; clearTimeout(batchId); @@ -56,27 +56,27 @@ * @param {any} arg - the object to check * @return {Boolean} - true if `arg` is an array */ - function isArray(arg) { + function isArray (arg) { return Array.isArray(arg) } - function isUndefined(arg) { + function isUndefined (arg) { return typeof arg === 'undefined' } - function isObject(arg) { + function isObject (arg) { return typeof arg === 'object' } - function isFunction(arg) { + function isFunction (arg) { return typeof arg === 'function' } - function isString(arg) { + function isString (arg) { return typeof arg === 'string' } - function ensureIsArray(arg, key) { + function ensureIsArray (arg, key) { if (!key || !isObject(arg)) { return isArray(arg) ? arg : [] } @@ -87,27 +87,27 @@ return arg } - function ensuredPush(object, key, el) { + function ensuredPush (object, key, el) { ensureIsArray(object, key); object[key].push(el); } // Vue $root instance has a _vueMeta object property, otherwise its a boolean true - function hasMetaInfo(vm) { + function hasMetaInfo (vm) { if ( vm === void 0 ) vm = this; return vm && (vm._vueMeta === true || isObject(vm._vueMeta)) } // a component is in a metaInfo branch when itself has meta info or one of its (grand-)children has - function inMetaInfoBranch(vm) { + function inMetaInfoBranch (vm) { if ( vm === void 0 ) vm = this; return vm && !isUndefined(vm._vueMeta) } - function addNavGuards(vm) { + function addNavGuards (vm) { // return when nav guards already added or no router exists if (vm.$root._vueMeta.navGuards || !vm.$root.$router) { /* istanbul ignore next */ @@ -135,18 +135,18 @@ var appId = 1; - function createMixin(Vue, options) { + function createMixin (Vue, options) { // for which Vue lifecycle hooks should the metaInfo be refreshed var updateOnLifecycleHook = ['activated', 'deactivated', 'beforeMount']; // watch for client side component updates return { - beforeCreate: function beforeCreate() { + beforeCreate: function beforeCreate () { var this$1 = this; Object.defineProperty(this, '_hasMetaInfo', { configurable: true, - get: function get() { + get: function get () { // Show deprecation warning once when devtools enabled if (Vue.config.devtools && !this.$root._vueMeta.hasMetaInfoDeprecationWarningShown) { console.warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead'); // eslint-disable-line no-console @@ -210,7 +210,7 @@ ensuredPush(this.$options, 'beforeMount', function () { // if this Vue-app was server rendered, set the appId to 'ssr' // only one SSR app per page is supported - if (this$1.$root.$el && this$1.$root.$el.hasAttribute('data-server-rendered')) { + if (this$1.$root.$el && this$1.$root.$el.hasAttribute && this$1.$root.$el.hasAttribute('data-server-rendered')) { this$1.$root._vueMeta.appId = 'ssr'; } }); @@ -417,7 +417,7 @@ // eslint-disable-next-line no-console var showWarningNotSupported = function () { return console.warn('This vue app/component has no vue-meta configuration'); }; - function setOptions(options) { + function setOptions (options) { // combine options options = isObject(options) ? options : {}; @@ -430,7 +430,7 @@ return options } - function getOptions(options) { + function getOptions (options) { var optionsCopy = {}; for (var key in options) { optionsCopy[key] = options[key]; @@ -438,7 +438,7 @@ return optionsCopy } - function pause(refresh) { + function pause (refresh) { if ( refresh === void 0 ) refresh = true; this.$root._vueMeta.paused = true; @@ -446,7 +446,7 @@ return function () { return resume(refresh); } } - function resume(refresh) { + function resume (refresh) { if ( refresh === void 0 ) refresh = true; this.$root._vueMeta.paused = false; @@ -456,7 +456,7 @@ } } - function applyTemplate(ref, headObject, template, chunk) { + function applyTemplate (ref, headObject, template, chunk) { var component = ref.component; var metaTemplateKeyName = ref.metaTemplateKeyName; var contentKeyName = ref.contentKeyName; @@ -491,7 +491,7 @@ * files in server/ still use normal js function */ - function findIndex(array, predicate) { + function findIndex (array, predicate) { var arguments$1 = arguments; if ( !Array.prototype.findIndex) { @@ -506,14 +506,14 @@ return array.findIndex(predicate, arguments[2]) } - function toArray(arg) { + function toArray (arg) { if ( !Array.from) { return Array.prototype.slice.call(arg) } return Array.from(arg) } - function includes(array, value) { + function includes (array, value) { if ( !Array.prototype.includes) { for (var idx in array) { if (array[idx] === value) { @@ -528,14 +528,14 @@ var clientSequences = [ [/&/g, '\u0026'], - [//g, '\u003e'], + [//g, '\u003E'], [/"/g, '\u0022'], [/'/g, '\u0027'] ]; // sanitizes potentially dangerous characters - function escape(info, options, escapeOptions) { + function escape (info, options, escapeOptions) { var tagIDKeyName = options.tagIDKeyName; var doEscape = escapeOptions.doEscape; if ( doEscape === void 0 ) doEscape = function (v) { return v; }; var escaped = {}; @@ -585,130 +585,117 @@ return escaped } - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + var isMergeableObject = function isMergeableObject(value) { + return isNonNullObject(value) + && !isSpecial(value) + }; - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; + function isNonNullObject(value) { + return !!value && typeof value === 'object' } - var umd = createCommonjsModule(function (module, exports) { - (function (global, factory) { - module.exports = factory() ; - }(commonjsGlobal, function () { - var isMergeableObject = function isMergeableObject(value) { - return isNonNullObject(value) - && !isSpecial(value) - }; + function isSpecial(value) { + var stringValue = Object.prototype.toString.call(value); - function isNonNullObject(value) { - return !!value && typeof value === 'object' + return stringValue === '[object RegExp]' + || stringValue === '[object Date]' + || isReactElement(value) + } + + // see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25 + var canUseSymbol = typeof Symbol === 'function' && Symbol.for; + var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7; + + function isReactElement(value) { + return value.$$typeof === REACT_ELEMENT_TYPE + } + + function emptyTarget(val) { + return Array.isArray(val) ? [] : {} + } + + function cloneUnlessOtherwiseSpecified(value, options) { + return (options.clone !== false && options.isMergeableObject(value)) + ? deepmerge(emptyTarget(value), value, options) + : value + } + + function defaultArrayMerge(target, source, options) { + return target.concat(source).map(function(element) { + return cloneUnlessOtherwiseSpecified(element, options) + }) + } + + function getMergeFunction(key, options) { + if (!options.customMerge) { + return deepmerge } + var customMerge = options.customMerge(key); + return typeof customMerge === 'function' ? customMerge : deepmerge + } - function isSpecial(value) { - var stringValue = Object.prototype.toString.call(value); - - return stringValue === '[object RegExp]' - || stringValue === '[object Date]' - || isReactElement(value) - } - - // see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25 - var canUseSymbol = typeof Symbol === 'function' && Symbol.for; - var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7; - - function isReactElement(value) { - return value.$$typeof === REACT_ELEMENT_TYPE - } - - function emptyTarget(val) { - return Array.isArray(val) ? [] : {} - } - - function cloneUnlessOtherwiseSpecified(value, options) { - return (options.clone !== false && options.isMergeableObject(value)) - ? deepmerge(emptyTarget(value), value, options) - : value - } - - function defaultArrayMerge(target, source, options) { - return target.concat(source).map(function(element) { - return cloneUnlessOtherwiseSpecified(element, options) + function getEnumerableOwnPropertySymbols(target) { + return Object.getOwnPropertySymbols + ? Object.getOwnPropertySymbols(target).filter(function(symbol) { + return target.propertyIsEnumerable(symbol) }) - } + : [] + } - function getMergeFunction(key, options) { - if (!options.customMerge) { - return deepmerge - } - var customMerge = options.customMerge(key); - return typeof customMerge === 'function' ? customMerge : deepmerge - } + function getKeys(target) { + return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target)) + } - function getEnumerableOwnPropertySymbols(target) { - return Object.getOwnPropertySymbols - ? Object.getOwnPropertySymbols(target).filter(function(symbol) { - return target.propertyIsEnumerable(symbol) - }) - : [] - } - - function getKeys(target) { - return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target)) - } - - function mergeObject(target, source, options) { - var destination = {}; - if (options.isMergeableObject(target)) { - getKeys(target).forEach(function(key) { - destination[key] = cloneUnlessOtherwiseSpecified(target[key], options); - }); - } - getKeys(source).forEach(function(key) { - if (!options.isMergeableObject(source[key]) || !target[key]) { - destination[key] = cloneUnlessOtherwiseSpecified(source[key], options); - } else { - destination[key] = getMergeFunction(key, options)(target[key], source[key], options); - } + function mergeObject(target, source, options) { + var destination = {}; + if (options.isMergeableObject(target)) { + getKeys(target).forEach(function(key) { + destination[key] = cloneUnlessOtherwiseSpecified(target[key], options); }); - return destination } - - function deepmerge(target, source, options) { - options = options || {}; - options.arrayMerge = options.arrayMerge || defaultArrayMerge; - options.isMergeableObject = options.isMergeableObject || isMergeableObject; - - var sourceIsArray = Array.isArray(source); - var targetIsArray = Array.isArray(target); - var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray; - - if (!sourceAndTargetTypesMatch) { - return cloneUnlessOtherwiseSpecified(source, options) - } else if (sourceIsArray) { - return options.arrayMerge(target, source, options) + getKeys(source).forEach(function(key) { + if (!options.isMergeableObject(source[key]) || !target[key]) { + destination[key] = cloneUnlessOtherwiseSpecified(source[key], options); } else { - return mergeObject(target, source, options) + destination[key] = getMergeFunction(key, options)(target[key], source[key], options); } + }); + return destination + } + + function deepmerge(target, source, options) { + options = options || {}; + options.arrayMerge = options.arrayMerge || defaultArrayMerge; + options.isMergeableObject = options.isMergeableObject || isMergeableObject; + + var sourceIsArray = Array.isArray(source); + var targetIsArray = Array.isArray(target); + var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray; + + if (!sourceAndTargetTypesMatch) { + return cloneUnlessOtherwiseSpecified(source, options) + } else if (sourceIsArray) { + return options.arrayMerge(target, source, options) + } else { + return mergeObject(target, source, options) + } + } + + deepmerge.all = function deepmergeAll(array, options) { + if (!Array.isArray(array)) { + throw new Error('first argument should be an array') } - deepmerge.all = function deepmergeAll(array, options) { - if (!Array.isArray(array)) { - throw new Error('first argument should be an array') - } + return array.reduce(function(prev, next) { + return deepmerge(prev, next, options) + }, {}) + }; - return array.reduce(function(prev, next) { - return deepmerge(prev, next, options) - }, {}) - }; + var deepmerge_1 = deepmerge; - var deepmerge_1 = deepmerge; + var cjs = deepmerge_1; - return deepmerge_1; - - })); - }); - - function arrayMerge(ref, target, source) { + function arrayMerge (ref, target, source) { var component = ref.component; var tagIDKeyName = ref.tagIDKeyName; var metaTemplateKeyName = ref.metaTemplateKeyName; @@ -775,7 +762,7 @@ return destination.concat(source) } - function merge(target, source, options) { + function merge (target, source, options) { if ( options === void 0 ) options = {}; // remove properties explicitly set to false so child components can @@ -801,7 +788,7 @@ } }); - return umd(target, source, { + return cjs(target, source, { arrayMerge: function (t, s) { return arrayMerge(options, t, s); } }) } @@ -820,7 +807,7 @@ * @param {Object} [result={}] - result so far * @return {Object} result - final aggregated result */ - function getComponentOption(options, component, result) { + function getComponentOption (options, component, result) { if ( options === void 0 ) options = {}; if ( result === void 0 ) result = {}; @@ -890,7 +877,7 @@ * @param {Object} component - the Vue instance to get meta info from * @return {Object} - returned meta info */ - function getMetaInfo(options, component, escapeSequences) { + function getMetaInfo (options, component, escapeSequences) { if ( options === void 0 ) options = {}; if ( escapeSequences === void 0 ) escapeSequences = []; @@ -948,7 +935,7 @@ * @param {Object} attrs - the new document html attributes * @param {HTMLElement} tag - the HTMLElement tag to update with new attrs */ - function updateAttribute(ref, attrs, tag) { + function updateAttribute (ref, attrs, tag) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; @@ -993,7 +980,7 @@ * * @param {String} title - the new title of the document */ - function updateTitle(title) { + function updateTitle (title) { if (title === undefined) { return } @@ -1009,7 +996,7 @@ * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base * @return {Object} - a representation of what tags changed */ - function updateTag(appId, ref, type, tags, headTag, bodyTag) { + function updateTag (appId, ref, type, tags, headTag, bodyTag) { if ( ref === void 0 ) ref = {}; var attribute = ref.attribute; var tagIDKeyName = ref.tagIDKeyName; @@ -1055,7 +1042,13 @@ var _attr = includes(dataAttributes, attr) ? ("data-" + attr) : attr; - var value = isUndefined(tag[attr]) || includes(booleanHtmlAttributes, attr) ? '' : tag[attr]; + + var isBooleanAttribute = includes(booleanHtmlAttributes, attr); + if (isBooleanAttribute && !tag[attr]) { + continue + } + + var value = isBooleanAttribute ? '' : tag[attr]; newElement.setAttribute(_attr, value); } } @@ -1089,7 +1082,7 @@ return { oldTags: oldTags, newTags: newTags } } - function getTag(tags, tag) { + function getTag (tags, tag) { if (!tags[tag]) { tags[tag] = document.getElementsByTagName(tag)[0]; } @@ -1102,7 +1095,7 @@ * * @param {Object} newInfo - the meta info to update to */ - function updateClientMetaInfo(appId, options, newInfo) { + function updateClientMetaInfo (appId, options, newInfo) { if ( options === void 0 ) options = {}; var ssrAttribute = options.ssrAttribute; @@ -1166,7 +1159,7 @@ return { addedTags: addedTags, removedTags: removedTags } } - function _refresh(options) { + function _refresh (options) { if ( options === void 0 ) options = {}; /** @@ -1179,7 +1172,7 @@ * * @return {Object} - new meta info */ - return function refresh() { + return function refresh () { var metaInfo = getMetaInfo(options, this.$root, clientSequences); var appId = this.$root._vueMeta.appId; @@ -1193,7 +1186,7 @@ } } - function _$meta(options) { + function _$meta (options) { if ( options === void 0 ) options = {}; var _refresh$1 = _refresh(options); @@ -1204,7 +1197,7 @@ * @this {Object} - the Vue instance (a root component) * @return {Object} - injector */ - return function $meta() { + return function $meta () { if (!this.$root._vueMeta) { return { getOptions: showWarningNotSupported, @@ -1229,7 +1222,7 @@ * Plugin install function. * @param {Function} Vue - the Vue constructor. */ - function install(Vue, options) { + function install (Vue, options) { if ( options === void 0 ) options = {}; if (Vue.__vuemeta_installed) { diff --git a/dist/vue-meta.min.js b/dist/vue-meta.min.js index 4bf20a6..9d2cd25 100644 --- a/dist/vue-meta.min.js +++ b/dist/vue-meta.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).VueMeta=t()}(this,function(){"use strict";var e=null;function t(t,n){t.$root._vueMeta.initialized||!t.$root._vueMeta.initializing&&"watcher"!==n||(t.$root._vueMeta.initialized=null),t.$root._vueMeta.initialized&&!t.$root._vueMeta.paused&&function(t,n){void 0===n&&(n=10);clearTimeout(e),e=setTimeout(function(){t()},n)}(function(){return t.$meta().refresh()})}function n(e){return Array.isArray(e)}function r(e){return void 0===e}function i(e){return"object"==typeof e}function o(e){return"function"==typeof e}function a(e,t){return t&&i(e)?(n(e[t])||(e[t]=[]),e):n(e)?e:[]}function u(e,t,n){a(e,t),e[t].push(n)}function s(e){return void 0===e&&(e=this),e&&(!0===e._vueMeta||i(e._vueMeta))}function c(e){if(!e.$root._vueMeta.navGuards&&e.$root.$router){e.$root._vueMeta.navGuards=!0;var t=e.$root.$router,n=e.$root.$meta();t.beforeEach(function(e,t,r){n.pause(),r()}),t.afterEach(function(){var e=n.resume().metaInfo;e&&e.afterNavigation&&o(e.afterNavigation)&&e.afterNavigation(e)})}}var f=1;var l={title:void 0,titleChunk:"",titleTemplate:"%s",htmlAttrs:{},bodyAttrs:{},headAttrs:{},base:[],link:[],meta:[],style:[],script:[],noscript:[],__dangerouslyDisableSanitizers:[],__dangerouslyDisableSanitizersByTagID:{}},d={keyName:"metaInfo",attribute:"data-vue-meta",ssrAttribute:"data-vue-meta-server-rendered",tagIDKeyName:"vmid",contentKeyName:"content",metaTemplateKeyName:"template"},v=["titleChunk","titleTemplate","changed","__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],h=["__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],p=["htmlAttrs","headAttrs","bodyAttrs"],m=["allowfullscreen","amp","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","truespeed","typemustmatch","visible"],y=function(){return console.warn("This vue app/component has no vue-meta configuration")};function g(e){return void 0===e&&(e=!0),this.$root._vueMeta.paused=!0,function(){return b(e)}}function b(e){if(void 0===e&&(e=!0),this.$root._vueMeta.paused=!1,e)return this.$root.$meta().refresh()}function $(e,t,n,i){var a=e.component,u=e.metaTemplateKeyName,s=e.contentKeyName;return r(n)&&(n=t[u],delete t[u]),!!n&&(r(i)&&(i=t[s]),t[s]=o(n)?n.call(a,i):n.replace(/%s/g,i),!0)}function M(e,t){var n=arguments;if(!Array.prototype.findIndex){for(var r=0;r/g,">"],[/"/g,'"'],[/'/g,"'"]];"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var w=function(e,t){return e(t={exports:{}},t.exports),t.exports}(function(e,t){e.exports=function(){var e=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var n=Object.prototype.toString.call(e);return"[object RegExp]"===n||"[object Date]"===n||function(e){return e.$$typeof===t}(e)}(e)},t="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function n(e,t){return!1!==t.clone&&t.isMergeableObject(e)?a((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function r(e,t,r){return e.concat(t).map(function(e){return n(e,r)})}function i(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return e.propertyIsEnumerable(t)}):[]}(e))}function o(e,t,r){var o={};return r.isMergeableObject(e)&&i(e).forEach(function(t){o[t]=n(e[t],r)}),i(t).forEach(function(i){r.isMergeableObject(t[i])&&e[i]?o[i]=function(e,t){if(!t.customMerge)return a;var n=t.customMerge(e);return"function"==typeof n?n:a}(i,r)(e[i],t[i],r):o[i]=n(t[i],r)}),o}function a(t,i,a){(a=a||{}).arrayMerge=a.arrayMerge||r,a.isMergeableObject=a.isMergeableObject||e;var u=Array.isArray(i),s=Array.isArray(t),c=u===s;return c?u?a.arrayMerge(t,i,a):o(t,i,a):n(i,a)}return a.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce(function(e,n){return a(e,n,t)},{})},a}()});function N(e,t,n){return void 0===n&&(n={}),t.hasOwnProperty("title")&&void 0===t.title&&delete t.title,p.forEach(function(e){if(t[e])for(var n in t[e])t[e].hasOwnProperty(n)&&void 0===t[e][n]&&(m.includes(n)&&console.warn("VueMeta: Please note that since v2 the value undefined is not used to indicate boolean attributes anymore, see migration guide for details"),delete t[e][n])}),w(e,t,{arrayMerge:function(e,t){return function(e,t,n){var r=e.component,i=e.tagIDKeyName,o=e.metaTemplateKeyName,a=e.contentKeyName,u=[];return t.forEach(function(e,t){if(e[i]){var s=M(n,function(t){return t[i]===e[i]}),c=n[s];if(-1!==s){if(c.hasOwnProperty(a)&&void 0===c[a]||c.hasOwnProperty("innerHTML")&&void 0===c.innerHTML)return u.push(e),void n.splice(s,1);if(null!==c[a]&&null!==c.innerHTML){var f=e[o];f&&(c[o]?c[a]||$({component:r,metaTemplateKeyName:o,contentKeyName:a},c,void 0,e[a]):$({component:r,metaTemplateKeyName:o,contentKeyName:a},c,f))}else n.splice(s,1)}else u.push(e)}else u.push(e)}),u.concat(n)}(n,e,t)}})}function I(e,t,n){void 0===e&&(e={}),void 0===n&&(n={});var a=e.keyName,u=e.metaTemplateKeyName,s=e.tagIDKeyName,c=t.$options,f=t.$children;if(t._inactive)return n;if(c[a]){var l=c[a];if(o(l)&&(l=l.call(t)),!i(l))return n;n=N(n,l,e)}return f.length&&f.forEach(function(t){(function(e){return void 0===e&&(e=this),e&&!r(e._vueMeta)})(t)&&(n=I(e,t,n))}),u&&n.meta&&(n.meta.forEach(function(t){return $(e,t)}),n.meta=n.meta.filter(function(e,t,n){return!e.hasOwnProperty(s)||t===M(n,function(t){return t[s]===e[s]})})),n}function O(e,t,r){void 0===e&&(e={}),void 0===r&&(r=[]);var o=I(e,t,l);o.title&&(o.titleChunk=o.title),o.titleTemplate&&"%s"!==o.titleTemplate&&$({component:t,contentKeyName:"title"},o,o.titleTemplate,o.titleChunk||""),o.base&&(o.base=Object.keys(o.base).length?[o.base]:[]);var u={doEscape:function(e){return r.reduce(function(e,t){var n=t[0],r=t[1];return e.replace(n,r)},e)}};return h.forEach(function(e,t){if(0===t)a(o,e);else if(1===t)for(var n in o[e])a(o[e],n);u[e]=o[e]}),o=function e(t,r,o){var a=r.tagIDKeyName,u=o.doEscape;void 0===u&&(u=function(e){return e});var s={};for(var c in t){var f=t[c];if(T(v,c))s[c]=f;else{var l=h[0];if(o[l]&&T(o[l],c))s[c]=f;else{var d=t[a];d&&(l=h[1],o[l]&&o[l][d]&&T(o[l][d],c))?s[c]=f:"string"==typeof f?s[c]=u(f):n(f)?s[c]=f.map(function(t){return i(t)?e(t,r,o):u(t)}):i(f)?s[c]=e(f,r,o):s[c]=f}}}return s}(o,e,u)}function S(e,t,r){void 0===e&&(e={});var i=e.attribute,o=r.getAttribute(i),a=o?o.split(","):[],u=_(a),s=[];for(var c in t)if(t.hasOwnProperty(c)){var f=T(m,c)?"":n(t[c])?t[c].join(" "):t[c];r.setAttribute(c,f||""),T(a,c)||a.push(c),s.push(u.indexOf(c))}var l=u.filter(function(e,t){return!T(s,t)}).reduce(function(e,t){return r.removeAttribute(t),e+1},0);a.length===l?r.removeAttribute(i):r.setAttribute(i,a.sort().join(","))}function E(e,t,n,i,o,a){void 0===t&&(t={});var u=t.attribute,s=t.tagIDKeyName,c=_(o.querySelectorAll(n+"["+u+'="'+e+'"], '+n+"[data-"+s+"]")),f=_(a.querySelectorAll(n+"["+u+'="'+e+'"][data-body="true"], '+n+"[data-"+s+'][data-body="true"]')),l=[s,"body"],d=[];if(i.length>1){var v=[];i=i.filter(function(e){var t=JSON.stringify(e),n=!T(v,t);return v.push(t),n})}i.length&&i.forEach(function(t){var i=document.createElement(n);i.setAttribute(u,e);var o,a=!0!==t.body?c:f;for(var s in t)if(t.hasOwnProperty(s))if("innerHTML"===s)i.innerHTML=t.innerHTML;else if("cssText"===s)i.styleSheet?i.styleSheet.cssText=t.cssText:i.appendChild(document.createTextNode(t.cssText));else{var v=T(l,s)?"data-"+s:s,h=r(t[s])||T(m,s)?"":t[s];i.setAttribute(v,h)}a.some(function(e,t){return o=t,i.isEqualNode(e)})&&(o||0===o)?a.splice(o,1):d.push(i)});var h=c.concat(f);return h.forEach(function(e){return e.parentNode.removeChild(e)}),d.forEach(function(e){"true"===e.getAttribute("data-body")?a.appendChild(e):o.appendChild(e)}),{oldTags:h,newTags:d}}function j(e,t){return e[t]||(e[t]=document.getElementsByTagName(t)[0]),e[t]}function z(e){return void 0===e&&(e={}),function(){var t=O(e,this.$root,A),r=function(e,t,r){void 0===t&&(t={});var i=t.ssrAttribute,o={},a=j(o,"html");if("ssr"===e&&a.hasAttribute(i))return a.removeAttribute(i),!1;var u,s={},c={};for(var f in r)if(!T(v,f))if("title"!==f){if(T(p,f)){var l=f.substr(0,4);S(t,r[f],j(o,l))}else if(n(r[f])){var d=E(e,t,f,r[f],j(o,"head"),j(o,"body")),h=d.oldTags,m=d.newTags;m.length&&(s[f]=m,c[f]=h)}}else void 0!==(u=r.title)&&(document.title=u);return{addedTags:s,removedTags:c}}(this.$root._vueMeta.appId,e,t);return r&&o(t.changed)&&t.changed(t,r.addedTags,r.removedTags),{vm:this,metaInfo:t,tags:r}}}function x(e,n){void 0===n&&(n={}),e.__vuemeta_installed||(e.__vuemeta_installed=!0,n=function(e){for(var t in e=i(e)?e:{},d)e[t]||(e[t]=d[t]);return e}(n),e.prototype.$meta=function(e){void 0===e&&(e={});var t=z(e),n=function(){};return function(){return this.$root._vueMeta?{getOptions:function(){return function(e){var t={};for(var n in e)t[n]=e[n];return t}(e)},refresh:t.bind(this),inject:n,pause:g.bind(this),resume:b.bind(this)}:{getOptions:y,refresh:y,inject:y,pause:y,resume:y}}}(n),e.mixin(function(e,n){var i=["activated","deactivated","beforeMount"];return{beforeCreate:function(){var a=this;if(Object.defineProperty(this,"_hasMetaInfo",{configurable:!0,get:function(){return e.config.devtools&&!this.$root._vueMeta.hasMetaInfoDeprecationWarningShown&&(console.warn("VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead"),this.$root._vueMeta.hasMetaInfoDeprecationWarningShown=!0),s(this)}}),!r(this.$options[n.keyName])&&null!==this.$options[n.keyName]){if(this.$root._vueMeta||(this.$root._vueMeta={appId:f},f++),!this._vueMeta){this._vueMeta=!0;for(var l=this.$parent;l&&l!==this.$root;)r(l._vueMeta)&&(l._vueMeta=!1),l=l.$parent}o(this.$options[n.keyName])&&(this.$options.computed||(this.$options.computed={}),this.$options.computed.$metaInfo=this.$options[n.keyName],this.$isServer||u(this.$options,"created",function(){a.$watch("$metaInfo",function(){t(this,"watcher")})})),r(this.$root._vueMeta.initialized)&&(this.$root._vueMeta.initialized=this.$isServer,this.$root._vueMeta.initialized||(u(this.$options,"beforeMount",function(){a.$root.$el&&a.$root.$el.hasAttribute("data-server-rendered")&&(a.$root._vueMeta.appId="ssr")}),u(this.$options,"mounted",function(){a.$root._vueMeta.initialized||(a.$root._vueMeta.initializing=!0,a.$nextTick(function(){var e=this,r=this.$root.$meta().refresh(),i=r.tags,o=r.metaInfo;!1===i&&null===this.$root._vueMeta.initialized&&this.$nextTick(function(){return t(e,"initializing")}),this.$root._vueMeta.initialized=!0,delete this.$root._vueMeta.initializing,!n.refreshOnceOnNavigation&&o.afterNavigation&&c(this)}))}),n.refreshOnceOnNavigation&&c(this))),this.$isServer||(i.forEach(function(e){u(a.$options,e,function(){return t(a,e)})}),u(this.$options,"destroyed",function(){var e=setInterval(function(){a.$el&&null!==a.$el.offsetParent||(clearInterval(e),a.$parent&&t(a,"destroyed"))},50)}))}}}}(e,n)))}return r(window)||r(window.Vue)||x(window.Vue),{version:"2.0.4",install:x,hasMetaInfo:s}}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).VueMeta=t()}(this,function(){"use strict";var e=null;function t(t,n){t.$root._vueMeta.initialized||!t.$root._vueMeta.initializing&&"watcher"!==n||(t.$root._vueMeta.initialized=null),t.$root._vueMeta.initialized&&!t.$root._vueMeta.paused&&function(t,n){void 0===n&&(n=10);clearTimeout(e),e=setTimeout(function(){t()},n)}(function(){return t.$meta().refresh()})}function n(e){return Array.isArray(e)}function r(e){return void 0===e}function i(e){return"object"==typeof e}function o(e){return"function"==typeof e}function a(e,t){return t&&i(e)?(n(e[t])||(e[t]=[]),e):n(e)?e:[]}function u(e,t,n){a(e,t),e[t].push(n)}function s(e){return void 0===e&&(e=this),e&&(!0===e._vueMeta||i(e._vueMeta))}function c(e){if(!e.$root._vueMeta.navGuards&&e.$root.$router){e.$root._vueMeta.navGuards=!0;var t=e.$root.$router,n=e.$root.$meta();t.beforeEach(function(e,t,r){n.pause(),r()}),t.afterEach(function(){var e=n.resume().metaInfo;e&&e.afterNavigation&&o(e.afterNavigation)&&e.afterNavigation(e)})}}var f=1;var l={title:void 0,titleChunk:"",titleTemplate:"%s",htmlAttrs:{},bodyAttrs:{},headAttrs:{},base:[],link:[],meta:[],style:[],script:[],noscript:[],__dangerouslyDisableSanitizers:[],__dangerouslyDisableSanitizersByTagID:{}},d={keyName:"metaInfo",attribute:"data-vue-meta",ssrAttribute:"data-vue-meta-server-rendered",tagIDKeyName:"vmid",contentKeyName:"content",metaTemplateKeyName:"template"},v=["titleChunk","titleTemplate","changed","__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],h=["__dangerouslyDisableSanitizers","__dangerouslyDisableSanitizersByTagID"],p=["htmlAttrs","headAttrs","bodyAttrs"],m=["allowfullscreen","amp","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","truespeed","typemustmatch","visible"],y=function(){return console.warn("This vue app/component has no vue-meta configuration")};function g(e){return void 0===e&&(e=!0),this.$root._vueMeta.paused=!0,function(){return b(e)}}function b(e){if(void 0===e&&(e=!0),this.$root._vueMeta.paused=!1,e)return this.$root.$meta().refresh()}function $(e,t,n,i){var a=e.component,u=e.metaTemplateKeyName,s=e.contentKeyName;return r(n)&&(n=t[u],delete t[u]),!!n&&(r(i)&&(i=t[s]),t[s]=o(n)?n.call(a,i):n.replace(/%s/g,i),!0)}function M(e,t){var n=arguments;if(!Array.prototype.findIndex){for(var r=0;r/g,">"],[/"/g,'"'],[/'/g,"'"]];var N=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===w}(e)}(e)};var w="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function I(e,t){return!1!==t.clone&&t.isMergeableObject(e)?j((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function O(e,t,n){return e.concat(t).map(function(e){return I(e,n)})}function S(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return e.propertyIsEnumerable(t)}):[]}(e))}function E(e,t,n){var r={};return n.isMergeableObject(e)&&S(e).forEach(function(t){r[t]=I(e[t],n)}),S(t).forEach(function(i){n.isMergeableObject(t[i])&&e[i]?r[i]=function(e,t){if(!t.customMerge)return j;var n=t.customMerge(e);return"function"==typeof n?n:j}(i,n)(e[i],t[i],n):r[i]=I(t[i],n)}),r}function j(e,t,n){(n=n||{}).arrayMerge=n.arrayMerge||O,n.isMergeableObject=n.isMergeableObject||N;var r=Array.isArray(t);return r===Array.isArray(e)?r?n.arrayMerge(e,t,n):E(e,t,n):I(t,n)}j.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce(function(e,n){return j(e,n,t)},{})};var z=j;function D(e,t,n){return void 0===n&&(n={}),t.hasOwnProperty("title")&&void 0===t.title&&delete t.title,p.forEach(function(e){if(t[e])for(var n in t[e])t[e].hasOwnProperty(n)&&void 0===t[e][n]&&(m.includes(n)&&console.warn("VueMeta: Please note that since v2 the value undefined is not used to indicate boolean attributes anymore, see migration guide for details"),delete t[e][n])}),z(e,t,{arrayMerge:function(e,t){return function(e,t,n){var r=e.component,i=e.tagIDKeyName,o=e.metaTemplateKeyName,a=e.contentKeyName,u=[];return t.forEach(function(e,t){if(e[i]){var s=M(n,function(t){return t[i]===e[i]}),c=n[s];if(-1!==s){if(c.hasOwnProperty(a)&&void 0===c[a]||c.hasOwnProperty("innerHTML")&&void 0===c.innerHTML)return u.push(e),void n.splice(s,1);if(null!==c[a]&&null!==c.innerHTML){var f=e[o];f&&(c[o]?c[a]||$({component:r,metaTemplateKeyName:o,contentKeyName:a},c,void 0,e[a]):$({component:r,metaTemplateKeyName:o,contentKeyName:a},c,f))}else n.splice(s,1)}else u.push(e)}else u.push(e)}),u.concat(n)}(n,e,t)}})}function k(e,t,n){void 0===e&&(e={}),void 0===n&&(n={});var a=e.keyName,u=e.metaTemplateKeyName,s=e.tagIDKeyName,c=t.$options,f=t.$children;if(t._inactive)return n;if(c[a]){var l=c[a];if(o(l)&&(l=l.call(t)),!i(l))return n;n=D(n,l,e)}return f.length&&f.forEach(function(t){(function(e){return void 0===e&&(e=this),e&&!r(e._vueMeta)})(t)&&(n=k(e,t,n))}),u&&n.meta&&(n.meta.forEach(function(t){return $(e,t)}),n.meta=n.meta.filter(function(e,t,n){return!e.hasOwnProperty(s)||t===M(n,function(t){return t[s]===e[s]})})),n}function K(e,t,r){void 0===e&&(e={}),void 0===r&&(r=[]);var o=k(e,t,l);o.title&&(o.titleChunk=o.title),o.titleTemplate&&"%s"!==o.titleTemplate&&$({component:t,contentKeyName:"title"},o,o.titleTemplate,o.titleChunk||""),o.base&&(o.base=Object.keys(o.base).length?[o.base]:[]);var u={doEscape:function(e){return r.reduce(function(e,t){var n=t[0],r=t[1];return e.replace(n,r)},e)}};return h.forEach(function(e,t){if(0===t)a(o,e);else if(1===t)for(var n in o[e])a(o[e],n);u[e]=o[e]}),o=function e(t,r,o){var a=r.tagIDKeyName,u=o.doEscape;void 0===u&&(u=function(e){return e});var s={};for(var c in t){var f=t[c];if(T(v,c))s[c]=f;else{var l=h[0];if(o[l]&&T(o[l],c))s[c]=f;else{var d=t[a];d&&(l=h[1],o[l]&&o[l][d]&&T(o[l][d],c))?s[c]=f:"string"==typeof f?s[c]=u(f):n(f)?s[c]=f.map(function(t){return i(t)?e(t,r,o):u(t)}):i(f)?s[c]=e(f,r,o):s[c]=f}}}return s}(o,e,u)}function x(e,t,r){void 0===e&&(e={});var i=e.attribute,o=r.getAttribute(i),a=o?o.split(","):[],u=_(a),s=[];for(var c in t)if(t.hasOwnProperty(c)){var f=T(m,c)?"":n(t[c])?t[c].join(" "):t[c];r.setAttribute(c,f||""),T(a,c)||a.push(c),s.push(u.indexOf(c))}var l=u.filter(function(e,t){return!T(s,t)}).reduce(function(e,t){return r.removeAttribute(t),e+1},0);a.length===l?r.removeAttribute(i):r.setAttribute(i,a.sort().join(","))}function P(e,t,n,r,i,o){void 0===t&&(t={});var a=t.attribute,u=t.tagIDKeyName,s=_(i.querySelectorAll(n+"["+a+'="'+e+'"], '+n+"[data-"+u+"]")),c=_(o.querySelectorAll(n+"["+a+'="'+e+'"][data-body="true"], '+n+"[data-"+u+'][data-body="true"]')),f=[u,"body"],l=[];if(r.length>1){var d=[];r=r.filter(function(e){var t=JSON.stringify(e),n=!T(d,t);return d.push(t),n})}r.length&&r.forEach(function(t){var r=document.createElement(n);r.setAttribute(a,e);var i,o=!0!==t.body?s:c;for(var u in t)if(t.hasOwnProperty(u))if("innerHTML"===u)r.innerHTML=t.innerHTML;else if("cssText"===u)r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText));else{var d=T(f,u)?"data-"+u:u,v=T(m,u);if(v&&!t[u])continue;var h=v?"":t[u];r.setAttribute(d,h)}o.some(function(e,t){return i=t,r.isEqualNode(e)})&&(i||0===i)?o.splice(i,1):l.push(r)});var v=s.concat(c);return v.forEach(function(e){return e.parentNode.removeChild(e)}),l.forEach(function(e){"true"===e.getAttribute("data-body")?o.appendChild(e):i.appendChild(e)}),{oldTags:v,newTags:l}}function C(e,t){return e[t]||(e[t]=document.getElementsByTagName(t)[0]),e[t]}function H(e){return void 0===e&&(e={}),function(){var t=K(e,this.$root,A),r=function(e,t,r){void 0===t&&(t={});var i=t.ssrAttribute,o={},a=C(o,"html");if("ssr"===e&&a.hasAttribute(i))return a.removeAttribute(i),!1;var u,s={},c={};for(var f in r)if(!T(v,f))if("title"!==f){if(T(p,f)){var l=f.substr(0,4);x(t,r[f],C(o,l))}else if(n(r[f])){var d=P(e,t,f,r[f],C(o,"head"),C(o,"body")),h=d.oldTags,m=d.newTags;m.length&&(s[f]=m,c[f]=h)}}else void 0!==(u=r.title)&&(document.title=u);return{addedTags:s,removedTags:c}}(this.$root._vueMeta.appId,e,t);return r&&o(t.changed)&&t.changed(t,r.addedTags,r.removedTags),{vm:this,metaInfo:t,tags:r}}}function L(e,n){void 0===n&&(n={}),e.__vuemeta_installed||(e.__vuemeta_installed=!0,n=function(e){for(var t in e=i(e)?e:{},d)e[t]||(e[t]=d[t]);return e}(n),e.prototype.$meta=function(e){void 0===e&&(e={});var t=H(e),n=function(){};return function(){return this.$root._vueMeta?{getOptions:function(){return function(e){var t={};for(var n in e)t[n]=e[n];return t}(e)},refresh:t.bind(this),inject:n,pause:g.bind(this),resume:b.bind(this)}:{getOptions:y,refresh:y,inject:y,pause:y,resume:y}}}(n),e.mixin(function(e,n){var i=["activated","deactivated","beforeMount"];return{beforeCreate:function(){var a=this;if(Object.defineProperty(this,"_hasMetaInfo",{configurable:!0,get:function(){return e.config.devtools&&!this.$root._vueMeta.hasMetaInfoDeprecationWarningShown&&(console.warn("VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead"),this.$root._vueMeta.hasMetaInfoDeprecationWarningShown=!0),s(this)}}),!r(this.$options[n.keyName])&&null!==this.$options[n.keyName]){if(this.$root._vueMeta||(this.$root._vueMeta={appId:f},f++),!this._vueMeta){this._vueMeta=!0;for(var l=this.$parent;l&&l!==this.$root;)r(l._vueMeta)&&(l._vueMeta=!1),l=l.$parent}o(this.$options[n.keyName])&&(this.$options.computed||(this.$options.computed={}),this.$options.computed.$metaInfo=this.$options[n.keyName],this.$isServer||u(this.$options,"created",function(){a.$watch("$metaInfo",function(){t(this,"watcher")})})),r(this.$root._vueMeta.initialized)&&(this.$root._vueMeta.initialized=this.$isServer,this.$root._vueMeta.initialized||(u(this.$options,"beforeMount",function(){a.$root.$el&&a.$root.$el.hasAttribute&&a.$root.$el.hasAttribute("data-server-rendered")&&(a.$root._vueMeta.appId="ssr")}),u(this.$options,"mounted",function(){a.$root._vueMeta.initialized||(a.$root._vueMeta.initializing=!0,a.$nextTick(function(){var e=this,r=this.$root.$meta().refresh(),i=r.tags,o=r.metaInfo;!1===i&&null===this.$root._vueMeta.initialized&&this.$nextTick(function(){return t(e,"initializing")}),this.$root._vueMeta.initialized=!0,delete this.$root._vueMeta.initializing,!n.refreshOnceOnNavigation&&o.afterNavigation&&c(this)}))}),n.refreshOnceOnNavigation&&c(this))),this.$isServer||(i.forEach(function(e){u(a.$options,e,function(){return t(a,e)})}),u(this.$options,"destroyed",function(){var e=setInterval(function(){a.$el&&null!==a.$el.offsetParent||(clearInterval(e),a.$parent&&t(a,"destroyed"))},50)}))}}}}(e,n)))}return r(window)||r(window.Vue)||L(window.Vue),{version:"2.0.5",install:L,hasMetaInfo:s}}); diff --git a/package.json b/package.json index 6233d09..056896c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-meta", - "version": "2.0.4", + "version": "2.0.5", "description": "Manage HTML metadata in Vue.js components with ssr support", "keywords": [ "attribute",