diff --git a/src/server/generateServerInjector.js b/src/server/generateServerInjector.js index d77e4ba..43f98dc 100644 --- a/src/server/generateServerInjector.js +++ b/src/server/generateServerInjector.js @@ -1,5 +1,6 @@ import titleGenerator from './generators/titleGenerator' import attrsGenerator from './generators/attrsGenerator' +import tagGenerator from './generators/tagGenerator' /** * Converts a meta info property to one that can be stringified on the server @@ -15,5 +16,7 @@ export default function generateServerInjector (type, data) { case 'htmlAttrs': case 'bodyAttrs': return attrsGenerator(type, data) + default: + return tagGenerator(type, data) } } diff --git a/src/server/generators/tagGenerator.js b/src/server/generators/tagGenerator.js new file mode 100644 index 0000000..6517e7a --- /dev/null +++ b/src/server/generators/tagGenerator.js @@ -0,0 +1,49 @@ +import { VUE_META_ATTRIBUTE } from '../../shared/constants' + +/** + * Generates meta, base, link, style, script, noscript tags for use on the server + * + * @param {('meta'|'base'|'link'|'style'|'script'|'noscript')} the name of the tag + * @param {(Array|Object)} tags - an array of tag objects or a single object in case of base + * @return {Object} - the tag generator + */ +export default function tagGenerator (type, tags) { + return { + text () { + // there can only be one `base` tag on a page, so we give it special treatment + if (type === 'base') { + tags = Object.keys(tags).length ? [tags] : [] + } + + // build a string containing all tags of this type + return tags.reduce((tagsStr, tag) => { + // build a string containing all attributes of this tag + const attrs = Object.keys(tag).reduce((attrsStr, attr) => { + switch (attr) { + // these attributes are treated as children on the tag + case 'innerHTML': + case 'cssText': + return attrsStr + + // these form the attribute list for this tag + default: + return typeof tag[attr] === 'undefined' + ? `${attrsStr} ${attr}` + : `${attrsStr} ${attr}="${tag[attr]}"` + } + }, '').trim() + + // grab child content from one of these attributes, if possible + const content = tag.innerHTML || tag.cssText || '' + + // these tag types will have content inserted + const closed = ['noscript', 'script', 'style'].indexOf(type) === -1 + + // the final string for this specific tag + return closed + ? `${tagsStr}<${type} ${VUE_META_ATTRIBUTE}="true" ${attrs}/>` + : `${tagsStr}<${type} ${VUE_META_ATTRIBUTE}="true" ${attrs}>${content}` + }, '') + } + } +} diff --git a/src/server/inject.js b/src/server/inject.js index d42e59e..b46fc59 100644 --- a/src/server/inject.js +++ b/src/server/inject.js @@ -15,7 +15,13 @@ export default function inject () { const info = Vue.util.extend({ title: '', htmlAttrs: {}, - bodyAttrs: {} + bodyAttrs: {}, + meta: [], + script: [], + noscript: [], + style: [], + link: [], + base: {} }, getMetaInfo(this.$root)) // generate server injectors