diff --git a/index.js b/index.js index 63ed9fb..efa56e2 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,47 @@ // set installation inspection flag VueMeta.install.installed = true - // TODO: implement plugin + /** + * Does the grunt work of exposing component meta options + * to the server-rendered context + * @return {Object} - all the meta info for currently matched components + */ + Vue.prototype.$meta = function $meta () { + return getMetaInfoDefinition(Vue, this) + } + } + + /** + * Recursively traverses each component, checking for a `metaInfo` + * option. It then merges all these options into one object, giving + * higher priority to deeply nested components. + * @param {Function} Vue - the Vue constructor + * @param {Object} $instance - the current instance + * @param {Object} [metaInfo={}] - the merged options + * @return {Object} metaInfo - the merged options + */ + function getMetaInfoDefinition (Vue, $instance, metaInfo) { + // set default for first run + metaInfo = metaInfo || {} + + // if current instance has a metaInfo option, merge it in + if ($instance.$options.metaInfo) { + metaInfo = Vue.util.mergeOptions(metaInfo, $instance.$options.metaInfo) + } + + // check if any children also have a metaInfo option + // NOTE: since the order of $instance.$children cannot be gauranteed, + // you should be careful about non-unique meta properties in + // sibling components + var len = $instance.$children.length + if (len) { + var i = 0 + for (; i < len; i++) { + metaInfo = getMetaInfoDefinition(Vue, $instance.$children[i], metaInfo) + } + } + + return metaInfo } // automatic installation when global context