From 01edc8c2428984da74c3ebf324ad0db8dc1725dd Mon Sep 17 00:00:00 2001 From: pimlie Date: Fri, 8 Mar 2019 16:40:43 +0100 Subject: [PATCH] feat: attr keys can have array values (resolves #231) --- src/client/updaters/attribute.js | 7 ++++-- src/server/generators/attribute.js | 3 ++- src/shared/escape.js | 6 ++++- test/getMetaInfo.test.js | 40 ++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/client/updaters/attribute.js b/src/client/updaters/attribute.js index 4808f744..79a347b8 100644 --- a/src/client/updaters/attribute.js +++ b/src/client/updaters/attribute.js @@ -1,3 +1,5 @@ +import isArray from '../../shared/isArray' + /** * Updates the document's html tag attributes * @@ -12,8 +14,9 @@ export default function updateAttribute({ attribute } = {}, attrs, tag) { const keepIndexes = [] for (const attr in attrs) { if (attrs.hasOwnProperty(attr)) { - const value = attrs[attr] || '' - tag.setAttribute(attr, value) + const value = isArray(attrs[attr]) ? attrs[attr].join(' ') : attrs[attr] + + tag.setAttribute(attr, value || '') if (!vueMetaAttrs.includes(attr)) { vueMetaAttrs.push(attr) diff --git a/src/server/generators/attribute.js b/src/server/generators/attribute.js index 03e29bfc..9b24b53a 100644 --- a/src/server/generators/attribute.js +++ b/src/server/generators/attribute.js @@ -1,5 +1,6 @@ import { booleanHtmlAttributes } from '../../shared/constants' import { isUndefined } from '../../shared/typeof' +import isArray from '../../shared/isArray' /** * Generates tag attributes for use on the server. @@ -20,7 +21,7 @@ export default function attributeGenerator({ attribute } = {}, type, data) { attributeStr += isUndefined(data[attr]) || booleanHtmlAttributes.includes(attr) ? attr - : `${attr}="${data[attr]}"` + : `${attr}="${isArray(data[attr]) ? data[attr].join(' ') : data[attr]}"` attributeStr += ' ' } diff --git a/src/shared/escape.js b/src/shared/escape.js index 5dfc3d3d..21d1ddd0 100644 --- a/src/shared/escape.js +++ b/src/shared/escape.js @@ -35,7 +35,11 @@ export default function escape(info, { tagIDKeyName }, escapeSequences = []) { if (isString(value)) { escaped[key] = escapeSequences.reduce((val, [v, r]) => val.replace(v, r), value) } else if (isArray(value)) { - escaped[key] = value.map(v => escape(v, { tagIDKeyName }, escapeSequences)) + escaped[key] = value.map((v) => { + return isObject(v) + ? escape(v, { tagIDKeyName }, escapeSequences) + : escapeSequences.reduce((val, [v, r]) => val.replace(v, r), v) + }) } else if (isObject(value)) { escaped[key] = escape(value, { tagIDKeyName }, escapeSequences) } else { diff --git a/test/getMetaInfo.test.js b/test/getMetaInfo.test.js index 65152f92..710e5475 100644 --- a/test/getMetaInfo.test.js +++ b/test/getMetaInfo.test.js @@ -719,4 +719,44 @@ describe('getMetaInfo', () => { __dangerouslyDisableSanitizersByTagID: {} }) }) + + test('attribute values can be an array', () => { + Vue.component('merge-child', { + render: h => h('div'), + metaInfo: { + bodyAttrs: { + class: ['foo'] + } + } + }) + + const component = new Vue({ + metaInfo: { + bodyAttrs: { + class: ['bar'] + } + }, + el: document.createElement('div'), + render: h => h('div', null, [h('merge-child')]) + }) + + expect(getMetaInfo(component)).toEqual({ + title: '', + titleChunk: '', + titleTemplate: '%s', + htmlAttrs: {}, + headAttrs: {}, + bodyAttrs: { + class: ['bar', 'foo'] + }, + meta: [], + base: [], + link: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) })