├── .gitignore ├── v-runtime-template.d.ts ├── .vscode └── settings.json ├── Test.vue ├── main.js ├── vue.config.js ├── test.plugin.js ├── LICENSE ├── package.json ├── App.vue ├── dist ├── v-runtime-template.es.js ├── v-runtime-template.js ├── v-runtime-template.umd.js ├── v-runtime-template.js.map ├── v-runtime-template.es.js.map └── v-runtime-template.umd.js.map ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /v-runtime-template.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'v-runtime-template' 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | } -------------------------------------------------------------------------------- /Test.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App.vue"; 3 | 4 | import testPlugin from "./test.plugin.js"; //testing mixins 5 | 6 | Vue.use(testPlugin); 7 | 8 | new Vue({ 9 | render: h => h(App) 10 | }).$mount("#app"); -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | // vue.config.js 2 | 3 | module.exports = { 4 | runtimeCompiler: true, 5 | configureWebpack: { 6 | resolve: { 7 | alias: { 8 | vue$: "vue/dist/vue.common" 9 | } 10 | } 11 | } 12 | }; -------------------------------------------------------------------------------- /test.plugin.js: -------------------------------------------------------------------------------- 1 | //https://vuejs.org/v2/guide/plugins.html 2 | //https://dev.to/nkoik/writing-a-very-simple-plugin-in-vuejs---example-8g8 3 | // This exports the plugin object. 4 | 5 | import Test from "./Test.vue" 6 | 7 | export default { 8 | // The install method will be called with the Vue constructor as 9 | // the first argument, along with possible options 10 | install(Vue) { 11 | Vue.mixin({ 12 | components:{Test}, 13 | props: { 14 | testingProp: { 15 | default: "mixinTest: testingProp" 16 | } 17 | }, 18 | data() { 19 | return { 20 | testingData: "mixinTest: testingData" 21 | }; 22 | }, 23 | computed: { 24 | testingComputed() { 25 | return "mixinTest: testingComputed"; 26 | } 27 | }, 28 | methods: { 29 | testingMethod() { 30 | return "mixinTest: testingMethod"; 31 | } 32 | } 33 | }); //end mixin 34 | 35 | Vue.prototype.$testProto = function (str) { 36 | return "mixinTest: testingProto=" + str; 37 | }; //end $testProto 38 | 39 | } 40 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alex Jover 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "v-runtime-template", 3 | "version": "1.10.0", 4 | "description": "Create Vue components by compiling templates on the fly", 5 | "main": "dist/v-runtime-template.umd.js", 6 | "scripts": { 7 | "prepublishOnly": "npm run build", 8 | "build": "microbundle index.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/alexjoverm/v-runtime-template.git" 14 | }, 15 | "keywords": [ 16 | "vuejs", 17 | "dynamic", 18 | "runtime", 19 | "template" 20 | ], 21 | "author": { 22 | "name": "Alex J", 23 | "email": "alexjovermorales@gmail.com" 24 | }, 25 | "license": "MIT", 26 | "devDependencies": { 27 | "microbundle": "^0.11.0" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/alexjoverm/v-runtime-template/issues" 31 | }, 32 | "homepage": "https://github.com/alexjoverm/v-runtime-template#readme", 33 | "module": "dist/v-runtime-template.es.js", 34 | "unpkg": "dist/v-runtime-template.umd.js", 35 | "browser": "dist/v-runtime-template.es.js", 36 | "types": "v-runtime-template.d.ts" 37 | } 38 | -------------------------------------------------------------------------------- /App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 53 | 54 | 56 | -------------------------------------------------------------------------------- /dist/v-runtime-template.es.js: -------------------------------------------------------------------------------- 1 | var t=function(t,o,e){if(!o.hasOwnProperty(e)){var r=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(o,e,r)}};export default{props:{template:String,parent:Object,templateProps:{type:Object,default:function(){return{}}}},render:function(o){if(this.template){var e=this.parent||this.$parent,r=e.$data;void 0===r&&(r={});var n=e.$props;void 0===n&&(n={});var a=e.$options;void 0===a&&(a={});var c=a.components;void 0===c&&(c={});var p=a.computed;void 0===p&&(p={});var i=a.methods;void 0===i&&(i={});var s=this.$data;void 0===s&&(s={});var d=this.$props;void 0===d&&(d={});var v=this.$options;void 0===v&&(v={});var f=v.methods;void 0===f&&(f={});var m=v.computed;void 0===m&&(m={});var u=v.components;void 0===u&&(u={});var h={$data:{},$props:{},$options:{},components:{},computed:{},methods:{}};Object.keys(r).forEach(function(t){void 0===s[t]&&(h.$data[t]=r[t])}),Object.keys(n).forEach(function(t){void 0===d[t]&&(h.$props[t]=n[t])}),Object.keys(i).forEach(function(t){void 0===f[t]&&(h.methods[t]=i[t])}),Object.keys(p).forEach(function(t){void 0===m[t]&&(h.computed[t]=p[t])}),Object.keys(c).forEach(function(t){void 0===u[t]&&(h.components[t]=c[t])});var O=Object.keys(h.methods||{}),$=Object.keys(h.$data||{}),b=Object.keys(h.$props||{}),j=Object.keys(this.templateProps),y=$.concat(b).concat(O).concat(j),k=(E=e,P={},O.forEach(function(o){return t(E,P,o)}),P),l=function(o){var e={};return o.forEach(function(o){o&&Object.getOwnPropertyNames(o).forEach(function(r){return t(o,e,r)})}),e}([h.$data,h.$props,k,this.templateProps]);return o({template:this.template||"
",props:y,computed:h.computed,components:h.components},{props:l})}var E,P}}; 2 | //# sourceMappingURL=v-runtime-template.es.js.map 3 | -------------------------------------------------------------------------------- /dist/v-runtime-template.js: -------------------------------------------------------------------------------- 1 | var t=function(t,o,e){if(!o.hasOwnProperty(e)){var r=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(o,e,r)}},o={props:{template:String,parent:Object,templateProps:{type:Object,default:function(){return{}}}},render:function(o){if(this.template){var e=this.parent||this.$parent,r=e.$data;void 0===r&&(r={});var n=e.$props;void 0===n&&(n={});var a=e.$options;void 0===a&&(a={});var c=a.components;void 0===c&&(c={});var p=a.computed;void 0===p&&(p={});var i=a.methods;void 0===i&&(i={});var s=this.$data;void 0===s&&(s={});var d=this.$props;void 0===d&&(d={});var v=this.$options;void 0===v&&(v={});var m=v.methods;void 0===m&&(m={});var u=v.computed;void 0===u&&(u={});var f=v.components;void 0===f&&(f={});var h={$data:{},$props:{},$options:{},components:{},computed:{},methods:{}};Object.keys(r).forEach(function(t){void 0===s[t]&&(h.$data[t]=r[t])}),Object.keys(n).forEach(function(t){void 0===d[t]&&(h.$props[t]=n[t])}),Object.keys(i).forEach(function(t){void 0===m[t]&&(h.methods[t]=i[t])}),Object.keys(p).forEach(function(t){void 0===u[t]&&(h.computed[t]=p[t])}),Object.keys(c).forEach(function(t){void 0===f[t]&&(h.components[t]=c[t])});var O=Object.keys(h.methods||{}),$=Object.keys(h.$data||{}),b=Object.keys(h.$props||{}),j=Object.keys(this.templateProps),y=$.concat(b).concat(O).concat(j),k=(E=e,P={},O.forEach(function(o){return t(E,P,o)}),P),l=function(o){var e={};return o.forEach(function(o){o&&Object.getOwnPropertyNames(o).forEach(function(r){return t(o,e,r)})}),e}([h.$data,h.$props,k,this.templateProps]);return o({template:this.template||"
",props:y,computed:h.computed,components:h.components},{props:l})}var E,P}};module.exports=o; 2 | //# sourceMappingURL=v-runtime-template.js.map 3 | -------------------------------------------------------------------------------- /dist/v-runtime-template.umd.js: -------------------------------------------------------------------------------- 1 | !function(t,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o():"function"==typeof define&&define.amd?define(o):t.vRuntimeTemplate=o()}(this,function(){var t=function(t,o,e){if(!o.hasOwnProperty(e)){var n=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(o,e,n)}};return{props:{template:String,parent:Object,templateProps:{type:Object,default:function(){return{}}}},render:function(o){if(this.template){var e=this.parent||this.$parent,n=e.$data;void 0===n&&(n={});var r=e.$props;void 0===r&&(r={});var p=e.$options;void 0===p&&(p={});var c=p.components;void 0===c&&(c={});var i=p.computed;void 0===i&&(i={});var a=p.methods;void 0===a&&(a={});var s=this.$data;void 0===s&&(s={});var d=this.$props;void 0===d&&(d={});var v=this.$options;void 0===v&&(v={});var f=v.methods;void 0===f&&(f={});var u=v.computed;void 0===u&&(u={});var m=v.components;void 0===m&&(m={});var h={$data:{},$props:{},$options:{},components:{},computed:{},methods:{}};Object.keys(n).forEach(function(t){void 0===s[t]&&(h.$data[t]=n[t])}),Object.keys(r).forEach(function(t){void 0===d[t]&&(h.$props[t]=r[t])}),Object.keys(a).forEach(function(t){void 0===f[t]&&(h.methods[t]=a[t])}),Object.keys(i).forEach(function(t){void 0===u[t]&&(h.computed[t]=i[t])}),Object.keys(c).forEach(function(t){void 0===m[t]&&(h.components[t]=c[t])});var y=Object.keys(h.methods||{}),O=Object.keys(h.$data||{}),$=Object.keys(h.$props||{}),b=Object.keys(this.templateProps),j=O.concat($).concat(y).concat(b),l=(E=e,P={},y.forEach(function(o){return t(E,P,o)}),P),k=function(o){var e={};return o.forEach(function(o){o&&Object.getOwnPropertyNames(o).forEach(function(n){return t(o,e,n)})}),e}([h.$data,h.$props,l,this.templateProps]);return o({template:this.template||"
",props:j,computed:h.computed,components:h.components},{props:k})}var E,P}}}); 2 | //# sourceMappingURL=v-runtime-template.umd.js.map 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const defineDescriptor = (src, dest, name) => { 2 | if (!dest.hasOwnProperty(name)) { 3 | const descriptor = Object.getOwnPropertyDescriptor(src, name); 4 | Object.defineProperty(dest, name, descriptor); 5 | } 6 | }; 7 | 8 | const merge = objs => { 9 | const res = {}; 10 | objs.forEach(obj => { 11 | obj && 12 | Object.getOwnPropertyNames(obj).forEach(name => 13 | defineDescriptor(obj, res, name) 14 | ); 15 | }); 16 | return res; 17 | }; 18 | 19 | const buildFromProps = (obj, props) => { 20 | const res = {}; 21 | props.forEach(prop => defineDescriptor(obj, res, prop)); 22 | return res; 23 | }; 24 | 25 | export default { 26 | props: { 27 | template: String, 28 | parent: Object, 29 | templateProps: { 30 | type: Object, 31 | default: () => ({}) 32 | } 33 | }, 34 | render(h) { 35 | if (this.template) { 36 | const parent = this.parent || this.$parent 37 | const { 38 | $data: parentData = {}, 39 | $props: parentProps = {}, 40 | $options: parentOptions = {} 41 | } = parent; 42 | const { 43 | components: parentComponents = {}, 44 | computed: parentComputed = {}, 45 | methods: parentMethods = {} 46 | } = parentOptions; 47 | const { 48 | $data = {}, 49 | $props = {}, 50 | $options: { methods = {}, computed = {}, components = {} } = {} 51 | } = this; 52 | const passthrough = { 53 | $data: {}, 54 | $props: {}, 55 | $options: {}, 56 | components: {}, 57 | computed: {}, 58 | methods: {} 59 | }; 60 | 61 | //build new objects by removing keys if already exists (e.g. created by mixins) 62 | Object.keys(parentData).forEach(e => { 63 | if (typeof $data[e] === "undefined") 64 | passthrough.$data[e] = parentData[e]; 65 | }); 66 | Object.keys(parentProps).forEach(e => { 67 | if (typeof $props[e] === "undefined") 68 | passthrough.$props[e] = parentProps[e]; 69 | }); 70 | Object.keys(parentMethods).forEach(e => { 71 | if (typeof methods[e] === "undefined") 72 | passthrough.methods[e] = parentMethods[e]; 73 | }); 74 | Object.keys(parentComputed).forEach(e => { 75 | if (typeof computed[e] === "undefined") 76 | passthrough.computed[e] = parentComputed[e]; 77 | }); 78 | Object.keys(parentComponents).forEach(e => { 79 | if (typeof components[e] === "undefined") 80 | passthrough.components[e] = parentComponents[e]; 81 | }); 82 | 83 | const methodKeys = Object.keys(passthrough.methods || {}); 84 | const dataKeys = Object.keys(passthrough.$data || {}); 85 | const propKeys = Object.keys(passthrough.$props || {}); 86 | const templatePropKeys = Object.keys(this.templateProps); 87 | const allKeys = dataKeys.concat(propKeys).concat(methodKeys).concat(templatePropKeys); 88 | const methodsFromProps = buildFromProps(parent, methodKeys); 89 | const finalProps = merge([ 90 | passthrough.$data, 91 | passthrough.$props, 92 | methodsFromProps, 93 | this.templateProps 94 | ]); 95 | const provide = this.$parent._provided; 96 | 97 | const dynamic = { 98 | template: this.template || "
", 99 | props: allKeys, 100 | computed: passthrough.computed, 101 | components: passthrough.components, 102 | provide: provide 103 | }; 104 | 105 | return h(dynamic, { props: finalProps }); 106 | } 107 | } 108 | }; 109 | -------------------------------------------------------------------------------- /dist/v-runtime-template.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"v-runtime-template.js","sources":["../index.js"],"sourcesContent":["const defineDescriptor = (src, dest, name) => {\n if (!dest.hasOwnProperty(name)) {\n const descriptor = Object.getOwnPropertyDescriptor(src, name);\n Object.defineProperty(dest, name, descriptor);\n }\n};\n\nconst merge = objs => {\n const res = {};\n objs.forEach(obj => {\n obj &&\n Object.getOwnPropertyNames(obj).forEach(name =>\n defineDescriptor(obj, res, name)\n );\n });\n return res;\n};\n\nconst buildFromProps = (obj, props) => {\n const res = {};\n props.forEach(prop => defineDescriptor(obj, res, prop));\n return res;\n};\n\nexport default {\n props: {\n template: String,\n parent: Object,\n templateProps: {\n type: Object,\n default: () => ({})\n }\n },\n render(h) {\n if (this.template) {\n const parent = this.parent || this.$parent\n const {\n $data: parentData = {},\n $props: parentProps = {},\n $options: parentOptions = {}\n } = parent;\n const {\n components: parentComponents = {},\n computed: parentComputed = {},\n methods: parentMethods = {}\n } = parentOptions;\n const {\n $data = {},\n $props = {},\n $options: { methods = {}, computed = {}, components = {} } = {}\n } = this;\n const passthrough = {\n $data: {},\n $props: {},\n $options: {},\n components: {},\n computed: {},\n methods: {}\n };\n\n //build new objects by removing keys if already exists (e.g. created by mixins)\n Object.keys(parentData).forEach(e => {\n if (typeof $data[e] === \"undefined\")\n passthrough.$data[e] = parentData[e];\n });\n Object.keys(parentProps).forEach(e => {\n if (typeof $props[e] === \"undefined\")\n passthrough.$props[e] = parentProps[e];\n });\n Object.keys(parentMethods).forEach(e => {\n if (typeof methods[e] === \"undefined\")\n passthrough.methods[e] = parentMethods[e];\n });\n Object.keys(parentComputed).forEach(e => {\n if (typeof computed[e] === \"undefined\")\n passthrough.computed[e] = parentComputed[e];\n });\n Object.keys(parentComponents).forEach(e => {\n if (typeof components[e] === \"undefined\")\n passthrough.components[e] = parentComponents[e];\n });\n\n const methodKeys = Object.keys(passthrough.methods || {});\n const dataKeys = Object.keys(passthrough.$data || {});\n const propKeys = Object.keys(passthrough.$props || {});\n const templatePropKeys = Object.keys(this.templateProps);\n const allKeys = dataKeys.concat(propKeys).concat(methodKeys).concat(templatePropKeys);\n const methodsFromProps = buildFromProps(parent, methodKeys);\n const finalProps = merge([\n passthrough.$data,\n passthrough.$props,\n methodsFromProps,\n this.templateProps\n ]);\n\n const dynamic = {\n template: this.template || \"
\",\n props: allKeys,\n computed: passthrough.computed,\n components: passthrough.components\n };\n\n return h(dynamic, { props: finalProps });\n }\n }\n};\n"],"names":["const","defineDescriptor","src","dest","name","hasOwnProperty","descriptor","Object","getOwnPropertyDescriptor","defineProperty","props","template","String","parent","templateProps","type","default","render","h","this","$parent","passthrough","$data","$props","$options","components","computed","methods","keys","parentData","forEach","e","parentProps","parentMethods","parentComputed","parentComponents","methodKeys","dataKeys","propKeys","templatePropKeys","allKeys","concat","methodsFromProps","obj","res","prop","finalProps","objs","getOwnPropertyNames","merge"],"mappings":"AAAAA,IAAMC,WAAoBC,EAAKC,EAAMC,OAC9BD,EAAKE,eAAeD,GAAO,KACxBE,EAAaC,OAAOC,yBAAyBN,EAAKE,GACxDG,OAAOE,eAAeN,EAAMC,EAAME,OAqBvB,CACbI,MAAO,CACLC,SAAUC,OACVC,OAAQN,OACRO,cAAe,CACbC,KAAMR,OACNS,+BAGJC,gBAAOC,MACDC,KAAKR,SAAU,KACXE,EAASM,KAAKN,QAAUM,KAAKC,iCAEb,kCACE,oCACI,sCAGK,oCACJ,mCACF,UAMvBD,0BAHM,UAGNA,2BAFO,UAEPA,6BAD2D,IAAnD,+BAAY,oCAAe,sCAAiB,QAElDE,EAAc,CAClBC,MAAO,GACPC,OAAQ,GACRC,SAAU,GACVC,WAAY,GACZC,SAAU,GACVC,QAAS,IAIXpB,OAAOqB,KAAKC,GAAYC,iBAAQC,QACN,IAAbT,EAAMS,KACfV,EAAYC,MAAMS,GAAKF,EAAWE,MAEtCxB,OAAOqB,KAAKI,GAAaF,iBAAQC,QACN,IAAdR,EAAOQ,KAChBV,EAAYE,OAAOQ,GAAKC,EAAYD,MAExCxB,OAAOqB,KAAKK,GAAeH,iBAAQC,QACP,IAAfJ,EAAQI,KACjBV,EAAYM,QAAQI,GAAKE,EAAcF,MAE3CxB,OAAOqB,KAAKM,GAAgBJ,iBAAQC,QACP,IAAhBL,EAASK,KAClBV,EAAYK,SAASK,GAAKG,EAAeH,MAE7CxB,OAAOqB,KAAKO,GAAkBL,iBAAQC,QACP,IAAlBN,EAAWM,KACpBV,EAAYI,WAAWM,GAAKI,EAAiBJ,UAG3CK,EAAa7B,OAAOqB,KAAKP,EAAYM,SAAW,IAChDU,EAAW9B,OAAOqB,KAAKP,EAAYC,OAAS,IAC5CgB,EAAW/B,OAAOqB,KAAKP,EAAYE,QAAU,IAC7CgB,EAAmBhC,OAAOqB,KAAKT,KAAKL,eACpC0B,EAAUH,EAASI,OAAOH,GAAUG,OAAOL,GAAYK,OAAOF,GAC9DG,GArEYC,EAqEsB9B,EApEtC+B,EAAM,GAoEwCR,EAnE9CN,iBAAQe,UAAQ5C,EAAiB0C,EAAKC,EAAKC,KAC1CD,GAmEGE,WAjFEC,OACNH,EAAM,UACZG,EAAKjB,iBAAQa,GACXA,GACEpC,OAAOyC,oBAAoBL,GAAKb,iBAAQ1B,UACtCH,EAAiB0C,EAAKC,EAAKxC,OAG1BwC,EAyEgBK,CAAM,CACvB5B,EAAYC,MACZD,EAAYE,OACZmB,EACAvB,KAAKL,uBAUAI,EAPS,CACdP,SAAUQ,KAAKR,UAAY,cAC3BD,MAAO8B,EACPd,SAAUL,EAAYK,SACtBD,WAAYJ,EAAYI,YAGR,CAAEf,MAAOoC,QApFTH,EAChBC"} -------------------------------------------------------------------------------- /dist/v-runtime-template.es.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"v-runtime-template.es.js","sources":["../index.js"],"sourcesContent":["const defineDescriptor = (src, dest, name) => {\n if (!dest.hasOwnProperty(name)) {\n const descriptor = Object.getOwnPropertyDescriptor(src, name);\n Object.defineProperty(dest, name, descriptor);\n }\n};\n\nconst merge = objs => {\n const res = {};\n objs.forEach(obj => {\n obj &&\n Object.getOwnPropertyNames(obj).forEach(name =>\n defineDescriptor(obj, res, name)\n );\n });\n return res;\n};\n\nconst buildFromProps = (obj, props) => {\n const res = {};\n props.forEach(prop => defineDescriptor(obj, res, prop));\n return res;\n};\n\nexport default {\n props: {\n template: String,\n parent: Object,\n templateProps: {\n type: Object,\n default: () => ({})\n }\n },\n render(h) {\n if (this.template) {\n const parent = this.parent || this.$parent\n const {\n $data: parentData = {},\n $props: parentProps = {},\n $options: parentOptions = {}\n } = parent;\n const {\n components: parentComponents = {},\n computed: parentComputed = {},\n methods: parentMethods = {}\n } = parentOptions;\n const {\n $data = {},\n $props = {},\n $options: { methods = {}, computed = {}, components = {} } = {}\n } = this;\n const passthrough = {\n $data: {},\n $props: {},\n $options: {},\n components: {},\n computed: {},\n methods: {}\n };\n\n //build new objects by removing keys if already exists (e.g. created by mixins)\n Object.keys(parentData).forEach(e => {\n if (typeof $data[e] === \"undefined\")\n passthrough.$data[e] = parentData[e];\n });\n Object.keys(parentProps).forEach(e => {\n if (typeof $props[e] === \"undefined\")\n passthrough.$props[e] = parentProps[e];\n });\n Object.keys(parentMethods).forEach(e => {\n if (typeof methods[e] === \"undefined\")\n passthrough.methods[e] = parentMethods[e];\n });\n Object.keys(parentComputed).forEach(e => {\n if (typeof computed[e] === \"undefined\")\n passthrough.computed[e] = parentComputed[e];\n });\n Object.keys(parentComponents).forEach(e => {\n if (typeof components[e] === \"undefined\")\n passthrough.components[e] = parentComponents[e];\n });\n\n const methodKeys = Object.keys(passthrough.methods || {});\n const dataKeys = Object.keys(passthrough.$data || {});\n const propKeys = Object.keys(passthrough.$props || {});\n const templatePropKeys = Object.keys(this.templateProps);\n const allKeys = dataKeys.concat(propKeys).concat(methodKeys).concat(templatePropKeys);\n const methodsFromProps = buildFromProps(parent, methodKeys);\n const finalProps = merge([\n passthrough.$data,\n passthrough.$props,\n methodsFromProps,\n this.templateProps\n ]);\n\n const dynamic = {\n template: this.template || \"
\",\n props: allKeys,\n computed: passthrough.computed,\n components: passthrough.components\n };\n\n return h(dynamic, { props: finalProps });\n }\n }\n};\n"],"names":["const","defineDescriptor","src","dest","name","hasOwnProperty","descriptor","Object","getOwnPropertyDescriptor","defineProperty","props","template","String","parent","templateProps","type","default","render","h","this","$parent","passthrough","$data","$props","$options","components","computed","methods","keys","parentData","forEach","e","parentProps","parentMethods","parentComputed","parentComponents","methodKeys","dataKeys","propKeys","templatePropKeys","allKeys","concat","methodsFromProps","obj","res","prop","finalProps","objs","getOwnPropertyNames","merge"],"mappings":"AAAAA,IAAMC,WAAoBC,EAAKC,EAAMC,OAC9BD,EAAKE,eAAeD,GAAO,KACxBE,EAAaC,OAAOC,yBAAyBN,EAAKE,GACxDG,OAAOE,eAAeN,EAAMC,EAAME,mBAqBvB,CACbI,MAAO,CACLC,SAAUC,OACVC,OAAQN,OACRO,cAAe,CACbC,KAAMR,OACNS,+BAGJC,gBAAOC,MACDC,KAAKR,SAAU,KACXE,EAASM,KAAKN,QAAUM,KAAKC,iCAEb,kCACE,oCACI,sCAGK,oCACJ,mCACF,UAMvBD,0BAHM,UAGNA,2BAFO,UAEPA,6BAD2D,IAAnD,+BAAY,oCAAe,sCAAiB,QAElDE,EAAc,CAClBC,MAAO,GACPC,OAAQ,GACRC,SAAU,GACVC,WAAY,GACZC,SAAU,GACVC,QAAS,IAIXpB,OAAOqB,KAAKC,GAAYC,iBAAQC,QACN,IAAbT,EAAMS,KACfV,EAAYC,MAAMS,GAAKF,EAAWE,MAEtCxB,OAAOqB,KAAKI,GAAaF,iBAAQC,QACN,IAAdR,EAAOQ,KAChBV,EAAYE,OAAOQ,GAAKC,EAAYD,MAExCxB,OAAOqB,KAAKK,GAAeH,iBAAQC,QACP,IAAfJ,EAAQI,KACjBV,EAAYM,QAAQI,GAAKE,EAAcF,MAE3CxB,OAAOqB,KAAKM,GAAgBJ,iBAAQC,QACP,IAAhBL,EAASK,KAClBV,EAAYK,SAASK,GAAKG,EAAeH,MAE7CxB,OAAOqB,KAAKO,GAAkBL,iBAAQC,QACP,IAAlBN,EAAWM,KACpBV,EAAYI,WAAWM,GAAKI,EAAiBJ,UAG3CK,EAAa7B,OAAOqB,KAAKP,EAAYM,SAAW,IAChDU,EAAW9B,OAAOqB,KAAKP,EAAYC,OAAS,IAC5CgB,EAAW/B,OAAOqB,KAAKP,EAAYE,QAAU,IAC7CgB,EAAmBhC,OAAOqB,KAAKT,KAAKL,eACpC0B,EAAUH,EAASI,OAAOH,GAAUG,OAAOL,GAAYK,OAAOF,GAC9DG,GArEYC,EAqEsB9B,EApEtC+B,EAAM,GAoEwCR,EAnE9CN,iBAAQe,UAAQ5C,EAAiB0C,EAAKC,EAAKC,KAC1CD,GAmEGE,WAjFEC,OACNH,EAAM,UACZG,EAAKjB,iBAAQa,GACXA,GACEpC,OAAOyC,oBAAoBL,GAAKb,iBAAQ1B,UACtCH,EAAiB0C,EAAKC,EAAKxC,OAG1BwC,EAyEgBK,CAAM,CACvB5B,EAAYC,MACZD,EAAYE,OACZmB,EACAvB,KAAKL,uBAUAI,EAPS,CACdP,SAAUQ,KAAKR,UAAY,cAC3BD,MAAO8B,EACPd,SAAUL,EAAYK,SACtBD,WAAYJ,EAAYI,YAGR,CAAEf,MAAOoC,QApFTH,EAChBC"} -------------------------------------------------------------------------------- /dist/v-runtime-template.umd.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"v-runtime-template.umd.js","sources":["../index.js"],"sourcesContent":["const defineDescriptor = (src, dest, name) => {\n if (!dest.hasOwnProperty(name)) {\n const descriptor = Object.getOwnPropertyDescriptor(src, name);\n Object.defineProperty(dest, name, descriptor);\n }\n};\n\nconst merge = objs => {\n const res = {};\n objs.forEach(obj => {\n obj &&\n Object.getOwnPropertyNames(obj).forEach(name =>\n defineDescriptor(obj, res, name)\n );\n });\n return res;\n};\n\nconst buildFromProps = (obj, props) => {\n const res = {};\n props.forEach(prop => defineDescriptor(obj, res, prop));\n return res;\n};\n\nexport default {\n props: {\n template: String,\n parent: Object,\n templateProps: {\n type: Object,\n default: () => ({})\n }\n },\n render(h) {\n if (this.template) {\n const parent = this.parent || this.$parent\n const {\n $data: parentData = {},\n $props: parentProps = {},\n $options: parentOptions = {}\n } = parent;\n const {\n components: parentComponents = {},\n computed: parentComputed = {},\n methods: parentMethods = {}\n } = parentOptions;\n const {\n $data = {},\n $props = {},\n $options: { methods = {}, computed = {}, components = {} } = {}\n } = this;\n const passthrough = {\n $data: {},\n $props: {},\n $options: {},\n components: {},\n computed: {},\n methods: {}\n };\n\n //build new objects by removing keys if already exists (e.g. created by mixins)\n Object.keys(parentData).forEach(e => {\n if (typeof $data[e] === \"undefined\")\n passthrough.$data[e] = parentData[e];\n });\n Object.keys(parentProps).forEach(e => {\n if (typeof $props[e] === \"undefined\")\n passthrough.$props[e] = parentProps[e];\n });\n Object.keys(parentMethods).forEach(e => {\n if (typeof methods[e] === \"undefined\")\n passthrough.methods[e] = parentMethods[e];\n });\n Object.keys(parentComputed).forEach(e => {\n if (typeof computed[e] === \"undefined\")\n passthrough.computed[e] = parentComputed[e];\n });\n Object.keys(parentComponents).forEach(e => {\n if (typeof components[e] === \"undefined\")\n passthrough.components[e] = parentComponents[e];\n });\n\n const methodKeys = Object.keys(passthrough.methods || {});\n const dataKeys = Object.keys(passthrough.$data || {});\n const propKeys = Object.keys(passthrough.$props || {});\n const templatePropKeys = Object.keys(this.templateProps);\n const allKeys = dataKeys.concat(propKeys).concat(methodKeys).concat(templatePropKeys);\n const methodsFromProps = buildFromProps(parent, methodKeys);\n const finalProps = merge([\n passthrough.$data,\n passthrough.$props,\n methodsFromProps,\n this.templateProps\n ]);\n\n const dynamic = {\n template: this.template || \"
\",\n props: allKeys,\n computed: passthrough.computed,\n components: passthrough.components\n };\n\n return h(dynamic, { props: finalProps });\n }\n }\n};\n"],"names":["const","defineDescriptor","src","dest","name","hasOwnProperty","descriptor","Object","getOwnPropertyDescriptor","defineProperty","props","template","String","parent","templateProps","type","default","render","h","this","$parent","passthrough","$data","$props","$options","components","computed","methods","keys","parentData","forEach","e","parentProps","parentMethods","parentComputed","parentComponents","methodKeys","dataKeys","propKeys","templatePropKeys","allKeys","concat","methodsFromProps","obj","res","prop","finalProps","objs","getOwnPropertyNames","merge"],"mappings":"+KAAAA,IAAMC,WAAoBC,EAAKC,EAAMC,OAC9BD,EAAKE,eAAeD,GAAO,KACxBE,EAAaC,OAAOC,yBAAyBN,EAAKE,GACxDG,OAAOE,eAAeN,EAAMC,EAAME,WAqBvB,CACbI,MAAO,CACLC,SAAUC,OACVC,OAAQN,OACRO,cAAe,CACbC,KAAMR,OACNS,+BAGJC,gBAAOC,MACDC,KAAKR,SAAU,KACXE,EAASM,KAAKN,QAAUM,KAAKC,iCAEb,kCACE,oCACI,sCAGK,oCACJ,mCACF,UAMvBD,0BAHM,UAGNA,2BAFO,UAEPA,6BAD2D,IAAnD,+BAAY,oCAAe,sCAAiB,QAElDE,EAAc,CAClBC,MAAO,GACPC,OAAQ,GACRC,SAAU,GACVC,WAAY,GACZC,SAAU,GACVC,QAAS,IAIXpB,OAAOqB,KAAKC,GAAYC,iBAAQC,QACN,IAAbT,EAAMS,KACfV,EAAYC,MAAMS,GAAKF,EAAWE,MAEtCxB,OAAOqB,KAAKI,GAAaF,iBAAQC,QACN,IAAdR,EAAOQ,KAChBV,EAAYE,OAAOQ,GAAKC,EAAYD,MAExCxB,OAAOqB,KAAKK,GAAeH,iBAAQC,QACP,IAAfJ,EAAQI,KACjBV,EAAYM,QAAQI,GAAKE,EAAcF,MAE3CxB,OAAOqB,KAAKM,GAAgBJ,iBAAQC,QACP,IAAhBL,EAASK,KAClBV,EAAYK,SAASK,GAAKG,EAAeH,MAE7CxB,OAAOqB,KAAKO,GAAkBL,iBAAQC,QACP,IAAlBN,EAAWM,KACpBV,EAAYI,WAAWM,GAAKI,EAAiBJ,UAG3CK,EAAa7B,OAAOqB,KAAKP,EAAYM,SAAW,IAChDU,EAAW9B,OAAOqB,KAAKP,EAAYC,OAAS,IAC5CgB,EAAW/B,OAAOqB,KAAKP,EAAYE,QAAU,IAC7CgB,EAAmBhC,OAAOqB,KAAKT,KAAKL,eACpC0B,EAAUH,EAASI,OAAOH,GAAUG,OAAOL,GAAYK,OAAOF,GAC9DG,GArEYC,EAqEsB9B,EApEtC+B,EAAM,GAoEwCR,EAnE9CN,iBAAQe,UAAQ5C,EAAiB0C,EAAKC,EAAKC,KAC1CD,GAmEGE,WAjFEC,OACNH,EAAM,UACZG,EAAKjB,iBAAQa,GACXA,GACEpC,OAAOyC,oBAAoBL,GAAKb,iBAAQ1B,UACtCH,EAAiB0C,EAAKC,EAAKxC,OAG1BwC,EAyEgBK,CAAM,CACvB5B,EAAYC,MACZD,EAAYE,OACZmB,EACAvB,KAAKL,uBAUAI,EAPS,CACdP,SAAUQ,KAAKR,UAAY,cAC3BD,MAAO8B,EACPd,SAAUL,EAAYK,SACtBD,WAAYJ,EAAYI,YAGR,CAAEf,MAAOoC,QApFTH,EAChBC"} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v-runtime-template 2 | 3 | [![npm](https://img.shields.io/npm/v/v-runtime-template.svg)](https://www.npmjs.com/package/v-runtime-template) 4 | [![npm](https://img.shields.io/npm/dm/v-runtime-template.svg)](https://www.npmjs.com/package/v-runtime-template) 5 | [![Donate](https://img.shields.io/badge/donate-paypal-blue.svg)](https://paypal.me/AJoverMorales) 6 | 7 | A Vue.js components that makes easy compiling and interpreting a Vue.js template at runtime by using a `v-html` like API. 8 | 9 | > Do you know **[VueDose](https://vuedose.tips)**? It's where you can learn tips about the Vue.js ecosystem in a concise format, perfect for busy devs! 🦄 10 | 11 | *[See Demo on CodeSandbox](https://codesandbox.io/s/884v9kq790)* 12 | 13 | ## Motivation 14 | 15 | This library solves the case where you get a vue-syntax template string on runtime, usually from a server. Think of a feature where you allow the user to create their own interfaces and structures. You save that as a vue template in your database, which your UI will request later. While components are pre-compiled at build time, this case isn't (since the template is received at runtime) and needs to be compiled at runtime. 16 | 17 | v-runtime-template compiles that template and attaches it to the scope of the component that uses it, so it has access to its data, props, methods and computed properties. 18 | 19 | Think of it as the `v-html` equivalent that also understands vue template syntax (while `v-html` is just for plain HTML). 20 | 21 | ## Getting Started 22 | 23 | Install it: 24 | 25 | ``` 26 | npm install v-runtime-template 27 | ``` 28 | 29 | You must **use the with-compiler Vue.js version**. This is needed in order to compile on-the-fly Vue.js templates. For that, you can set a webpack alias for `vue` to the `vue/dist/vue.common` file. 30 | 31 | For example, if you use the [Vue CLI](https://github.com/vuejs/vue-cli), create or modify the `vue.config.js` file adding the following alias: 32 | 33 | ```js 34 | // vue.config.js 35 | module.exports = { 36 | runtimeCompiler: true 37 | }; 38 | ``` 39 | 40 | And in [Nuxt](http://nuxtjs.org/), open the `nuxt.config.js` file and extend the webpack config by adding the following line to the `extend` key: 41 | 42 | ```js 43 | // nuxt.config.js 44 | { 45 | build: { 46 | extend(config, { isDev, isClient }) { 47 | config.resolve.alias["vue"] = "vue/dist/vue.common"; 48 | // ... 49 | ``` 50 | 51 | ## Usage 52 | 53 | You just need to import the `v-runtime-template` component, and pass the template you want: 54 | 55 | ```html 56 | 61 | 62 | 79 | ``` 80 | 81 | The template you pass **have access to the parent component instance**. For example, in the last example we're using the `AppMessage` component and accessing the `{{ name }}` state variable. 82 | 83 | But you can access computed properties and methods as well from the template: 84 | 85 | ```js 86 | export default { 87 | data: () => ({ 88 | name: "Mellow", 89 | template: ` 90 |
91 | Hello {{ name }}! 92 | 93 |

{{ someComputed }}

94 |
95 | `, 96 | }), 97 | computed: { 98 | someComputed() { 99 | return "Wow, I'm computed"; 100 | }, 101 | }, 102 | methods: { 103 | sayHi() { 104 | console.log("Hi"); 105 | }, 106 | }, 107 | }; 108 | ``` 109 | 110 | ## Limitations 111 | 112 | Keep in mind that the template can only access the instance properties of the component who is using it. Read [this issue](https://github.com/alexjoverm/v-runtime-template/issues/9) for more information. 113 | 114 | ## Comparison 115 | 116 | ### v-runtime-template VS v-html 117 | 118 | _TL;DR: If you need to interpret only HTML, use `v-html`. Use this library otherwise._ 119 | 120 | They both have the same goal: to interpret and attach a piece of structure to a scope at runtime. The difference is, `[v-html](https://vuejs.org/v2/api/#v-html)` doesn't understand vue template syntax, but only HTML. So, while this code works: 121 | 122 | ```html 123 | 126 | 127 |