diff --git a/src/shared/getComponentOption.js b/src/shared/getComponentOption.js index 7c7274e..a2ffd51 100644 --- a/src/shared/getComponentOption.js +++ b/src/shared/getComponentOption.js @@ -14,7 +14,7 @@ import deepmerge from 'deepmerge' * @return {Object} - final aggregated result */ export default function getComponentOption (opts, result = {}) { - const { component, option, deep } = opts + const { component, option, deep, arrayMerge } = opts const { $options } = component // only collect option data if it exists @@ -34,7 +34,7 @@ export default function getComponentOption (opts, result = {}) { } // merge with existing options - result = deepmerge(result, data) + result = deepmerge(result, data, { arrayMerge }) } // collect & aggregate child options if deep = true @@ -42,7 +42,7 @@ export default function getComponentOption (opts, result = {}) { const { $children } = component for (let i = 0, len = $children.length; i < len; i++) { const component = $children[i] - result = getComponentOption({ option, deep, component }, result) + result = getComponentOption({ option, deep, component, arrayMerge }, result) } } diff --git a/src/shared/getMetaInfo.js b/src/shared/getMetaInfo.js index feb1e85..7c5bb57 100644 --- a/src/shared/getMetaInfo.js +++ b/src/shared/getMetaInfo.js @@ -9,7 +9,41 @@ import getComponentOption from './getComponentOption' */ export default function getMetaInfo (component) { // collect & aggregate all metaInfo $options - const info = getComponentOption({ component, option: 'metaInfo', deep: true }) + const info = getComponentOption({ + component, + option: 'metaInfo', + deep: true, + // In order to prevent certain tags from being overwritten, + // (like being overwritten by + // ), we need to specify a different + // array merge strategy. This strategy exploits a trick + // with associative arrays in JS using O(1) lookup + + /* eslint-disable no-labels */ + arrayMerge (oldTags, newTags) { + const updatedTags = [] + for (let oldTagIndex in oldTags) { + const oldTag = oldTags[oldTagIndex] + let sharedAttributes = false + ifTagsHaveEqualSharedAttributeValues: for (let newTagIndex in newTags) { + const newTag = newTags[newTagIndex] + for (let attribute in newTag) { + if (newTag.hasOwnProperty(attribute) && oldTag.hasOwnProperty(attribute)) { + if (oldTag[attribute] === newTag[attribute]) { + sharedAttributes = true + break ifTagsHaveEqualSharedAttributeValues + } + } + } + } + if (!sharedAttributes) { + updatedTags.push(oldTag) + } + } + return updatedTags.concat(newTags) + } + /* eslint-enable no-labels */ + }) // if any info options are a function, coerce them to the result of a call for (let key in info) {