vue-script2
Advanced tools
Comparing version 2.0.3 to 2.1.0
@@ -0,1 +1,7 @@ | ||
### 2.1.0 | ||
- Better handling of simultaneously loaded components ([#12](https://github.com/taoeffect/vue-script2/issues/12) - thanks **[@vgavro](https://github.com/vgavro)**) | ||
- Emit vue events for `loaded` and `error` ([#31](https://github.com/taoeffect/vue-script2/issues/31) - thanks **[@vgavro](https://github.com/vgavro)**) | ||
- Updated all dev dependencies and switched from uglify to terser | ||
### 2.0.3 | ||
@@ -2,0 +8,0 @@ |
/*! | ||
* vue-script2 v2.0.3 | ||
* (c) 2016-2018 Greg Slepak | ||
* vue-script2 v2.1.0 | ||
* (c) 2016-2019 Greg Slepak | ||
* @license MIT License | ||
@@ -9,4 +9,4 @@ */ | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global.VueScript2 = factory()); | ||
}(this, (function () { 'use strict'; | ||
(global = global || self, global.VueScript2 = factory()); | ||
}(this, function () { 'use strict'; | ||
@@ -16,29 +16,34 @@ var Script2 = { | ||
p: Promise.resolve(), | ||
version: '2.0.3', // grunt will overwrite to match package.json | ||
loaded: {}, // keys are the scripts that have been loaded | ||
install: function install(Vue) { | ||
version: '2.1.0', | ||
// grunt will overwrite to match package.json | ||
loaded: {}, | ||
// keys are the scripts that is loading or loaded, values are promises | ||
install(Vue) { | ||
if (Script2.installed) return; | ||
var customAttrs = ['unload']; | ||
// from: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script | ||
var customAttrs = ['unload']; // from: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script | ||
// 'async' and 'defer' don't allow document.write according to: | ||
// http://www.html5rocks.com/en/tutorials/speed/script-loading/ | ||
// we ignore 'defer' and handle 'async' specially. | ||
var props = customAttrs.concat(['src', 'type', 'async', 'integrity', 'text', 'crossorigin']); | ||
Vue.component('script2', { | ||
props: props, | ||
// <slot> is important, see: http://vuejs.org/guide/components.html#Named-Slots | ||
// template: '<div style="display:none"><slot></slot></div>', | ||
// NOTE: Instead of using `template` we can use the `render` function like so: | ||
render: function render(h) { | ||
return h('div', { style: 'display:none' }, this.$slots.default); | ||
render(h) { | ||
return h('div', { | ||
style: 'display:none' | ||
}, this.$slots.default); | ||
}, | ||
mounted: function mounted() { | ||
var _this = this; | ||
mounted() { | ||
var parent = this.$el.parentElement; | ||
if (!this.src) { | ||
Script2.p = Script2.p.then(function () { | ||
Script2.p = Script2.p.then(() => { | ||
var s = document.createElement('script'); | ||
var h = _this.$el.innerHTML; | ||
var h = this.$el.innerHTML; | ||
h = h.replace(/</gi, '<').replace(/>/gi, '>').replace(/&/gi, '&'); | ||
@@ -48,70 +53,86 @@ s.type = 'text/javascript'; | ||
parent.appendChild(s); | ||
this.$emit('loaded'); // any other proper way to do this or emit error? | ||
}); | ||
} else { | ||
var opts = _.omitBy(_.pick(this, props), _.isUndefined); | ||
opts.parent = parent; | ||
// this syntax results in an implicit return | ||
var load = function load() { | ||
return Script2.load(_this.src, opts); | ||
}; | ||
_.isUndefined(this.async) ? Script2.p = Script2.p.then(load) // serialize execution | ||
opts.parent = parent; // this syntax results in an implicit return | ||
var load = () => Script2.load(this.src, opts).then(() => this.$emit('loaded'), err => this.$emit('error', err)); | ||
_.isUndefined(this.async) || this.async === 'false' ? Script2.p = Script2.p.then(load) // serialize execution | ||
: load(); // inject immediately | ||
} | ||
// see: https://vuejs.org/v2/guide/migration.html#ready-replaced | ||
this.$nextTick(function () { | ||
} // see: https://vuejs.org/v2/guide/migration.html#ready-replaced | ||
this.$nextTick(() => { | ||
// code that assumes this.$el is in-document | ||
// NOTE: we could've done this.$el.remove(), but IE sucks, see: | ||
// https://github.com/taoeffect/vue-script2/pull/17 | ||
_this.$el.parentElement.removeChild(_this.$el); // remove dummy template <div> | ||
this.$el.parentElement.removeChild(this.$el); // remove dummy template <div> | ||
}); | ||
}, | ||
destroyed: function destroyed() { | ||
destroyed() { | ||
if (this.unload) { | ||
new Function(this.unload)(); // eslint-disable-line | ||
delete Script2.loaded[this.src]; | ||
} | ||
} | ||
}); | ||
Script2.installed = true; | ||
}, | ||
load: function load(src) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { parent: document.head }; | ||
return Script2.loaded[src] ? Promise.resolve(src) : new Promise(function (resolve, reject) { | ||
var s = document.createElement('script'); | ||
// omit the special options that Script2 supports | ||
_.defaults2(s, _.omit(opts, ['unload', 'parent']), { type: 'text/javascript' }); | ||
// according to: http://www.html5rocks.com/en/tutorials/speed/script-loading/ | ||
// async does not like 'document.write' usage, which we & vue.js make | ||
// heavy use of based on the SPA style. Also, async can result | ||
// in code getting executed out of order from how it is inlined on the page. | ||
s.async = false; // therefore set this to false | ||
s.src = src; | ||
// crossorigin in HTML and crossOrigin in the DOM per HTML spec | ||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-crossorigin | ||
if (opts.crossorigin) { | ||
s.crossOrigin = opts.crossorigin; | ||
} | ||
// inspiration from: https://github.com/eldargab/load-script/blob/master/index.js | ||
// and: https://github.com/ded/script.js/blob/master/src/script.js#L70-L82 | ||
s.onload = function () { | ||
Script2.loaded[src] = 1;resolve(src); | ||
}; | ||
// IE should now support onerror and onload. If necessary, take a look | ||
// at this to add older IE support: http://stackoverflow.com/a/4845802/1781435 | ||
s.onerror = function () { | ||
return reject(new Error(src)); | ||
}; | ||
opts.parent.appendChild(s); | ||
}); | ||
load(src) { | ||
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { | ||
parent: document.head | ||
}; | ||
if (!Script2.loaded[src]) { | ||
Script2.loaded[src] = new Promise((resolve, reject) => { | ||
var s = document.createElement('script'); // omit the special options that Script2 supports | ||
_.defaults2(s, _.omit(opts, ['unload', 'parent']), { | ||
type: 'text/javascript' | ||
}); // according to: http://www.html5rocks.com/en/tutorials/speed/script-loading/ | ||
// async does not like 'document.write' usage, which we & vue.js make | ||
// heavy use of based on the SPA style. Also, async can result | ||
// in code getting executed out of order from how it is inlined on the page. | ||
s.async = false; // therefore set this to false | ||
s.src = src; // crossorigin in HTML and crossOrigin in the DOM per HTML spec | ||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-crossorigin | ||
if (opts.crossorigin) { | ||
s.crossOrigin = opts.crossorigin; | ||
} // inspiration from: https://github.com/eldargab/load-script/blob/master/index.js | ||
// and: https://github.com/ded/script.js/blob/master/src/script.js#L70-L82 | ||
s.onload = () => resolve(src); // IE should now support onerror and onload. If necessary, take a look | ||
// at this to add older IE support: http://stackoverflow.com/a/4845802/1781435 | ||
s.onerror = () => reject(new Error(src)); | ||
opts.parent.appendChild(s); | ||
}); | ||
} | ||
return Script2.loaded[src]; | ||
} | ||
}; | ||
var _ = { | ||
isUndefined: function isUndefined(x) { | ||
isUndefined(x) { | ||
return x === undefined; | ||
}, | ||
pick: function pick(o, props) { | ||
pick(o, props) { | ||
var x = {}; | ||
props.forEach(function (k) { | ||
props.forEach(k => { | ||
x[k] = o[k]; | ||
@@ -121,5 +142,6 @@ }); | ||
}, | ||
omit: function omit(o, props) { | ||
omit(o, props) { | ||
var x = {}; | ||
Object.keys(o).forEach(function (k) { | ||
Object.keys(o).forEach(k => { | ||
if (props.indexOf(k) === -1) x[k] = o[k]; | ||
@@ -129,5 +151,6 @@ }); | ||
}, | ||
omitBy: function omitBy(o, pred) { | ||
omitBy(o, pred) { | ||
var x = {}; | ||
Object.keys(o).forEach(function (k) { | ||
Object.keys(o).forEach(k => { | ||
if (!pred(o[k])) x[k] = o[k]; | ||
@@ -139,9 +162,9 @@ }); | ||
// custom defaults function suited to our specific purpose | ||
defaults2: function defaults2(o) { | ||
for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
defaults2(o) { | ||
for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
sources[_key - 1] = arguments[_key]; | ||
} | ||
sources.forEach(function (s) { | ||
Object.keys(s).forEach(function (k) { | ||
sources.forEach(s => { | ||
Object.keys(s).forEach(k => { | ||
if (_.isUndefined(o[k]) || o[k] === '') o[k] = s[k]; | ||
@@ -151,2 +174,3 @@ }); | ||
} | ||
}; | ||
@@ -156,2 +180,2 @@ | ||
}))); | ||
})); |
/*! | ||
* vue-script2 v2.0.3 | ||
* (c) 2016-2018 Greg Slepak | ||
* vue-script2 v2.1.0 | ||
* (c) 2016-2019 Greg Slepak | ||
* @license MIT License | ||
*/ | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.VueScript2=n()}(this,function(){"use strict";var e={installed:!1,p:Promise.resolve(),version:"2.0.3",loaded:{},install:function(t){if(!e.installed){var i=["unload"].concat(["src","type","async","integrity","text","crossorigin"]);t.component("script2",{props:i,render:function(e){return e("div",{style:"display:none"},this.$slots.default)},mounted:function(){var t=this,r=this.$el.parentElement;if(this.src){var o=n.omitBy(n.pick(this,i),n.isUndefined);o.parent=r;var c=function(){return e.load(t.src,o)};n.isUndefined(this.async)?e.p=e.p.then(c):c()}else e.p=e.p.then(function(){var e=document.createElement("script"),n=t.$el.innerHTML;n=n.replace(/</gi,"<").replace(/>/gi,">").replace(/&/gi,"&"),e.type="text/javascript",e.appendChild(document.createTextNode(n)),r.appendChild(e)});this.$nextTick(function(){t.$el.parentElement.removeChild(t.$el)})},destroyed:function(){this.unload&&(new Function(this.unload)(),delete e.loaded[this.src])}}),e.installed=!0}},load:function(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{parent:document.head};return e.loaded[t]?Promise.resolve(t):new Promise(function(r,o){var c=document.createElement("script");n.defaults2(c,n.omit(i,["unload","parent"]),{type:"text/javascript"}),c.async=!1,c.src=t,i.crossorigin&&(c.crossOrigin=i.crossorigin),c.onload=function(){e.loaded[t]=1,r(t)},c.onerror=function(){return o(new Error(t))},i.parent.appendChild(c)})}},n={isUndefined:function(e){return void 0===e},pick:function(e,n){var t={};return n.forEach(function(n){t[n]=e[n]}),t},omit:function(e,n){var t={};return Object.keys(e).forEach(function(i){-1===n.indexOf(i)&&(t[i]=e[i])}),t},omitBy:function(e,n){var t={};return Object.keys(e).forEach(function(i){n(e[i])||(t[i]=e[i])}),t},defaults2:function(e){for(var t=arguments.length,i=Array(t>1?t-1:0),r=1;r<t;r++)i[r-1]=arguments[r];i.forEach(function(t){Object.keys(t).forEach(function(i){(n.isUndefined(e[i])||""===e[i])&&(e[i]=t[i])})})}};return e}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).VueScript2=t()}(this,function(){"use strict";var e={installed:!1,p:Promise.resolve(),version:"2.1.0",loaded:{},install(r){if(!e.installed){var n=["unload"].concat(["src","type","async","integrity","text","crossorigin"]);r.component("script2",{props:n,render(e){return e("div",{style:"display:none"},this.$slots.default)},mounted(){var r=this.$el.parentElement;if(this.src){var i=t.omitBy(t.pick(this,n),t.isUndefined);i.parent=r;var s=()=>e.load(this.src,i).then(()=>this.$emit("loaded"),e=>this.$emit("error",e));t.isUndefined(this.async)||"false"===this.async?e.p=e.p.then(s):s()}else e.p=e.p.then(()=>{var e=document.createElement("script"),t=this.$el.innerHTML;t=t.replace(/</gi,"<").replace(/>/gi,">").replace(/&/gi,"&"),e.type="text/javascript",e.appendChild(document.createTextNode(t)),r.appendChild(e),this.$emit("loaded")});this.$nextTick(()=>{this.$el.parentElement.removeChild(this.$el)})},destroyed(){this.unload&&(new Function(this.unload)(),delete e.loaded[this.src])}}),e.installed=!0}},load(r){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{parent:document.head};return e.loaded[r]||(e.loaded[r]=new Promise((e,i)=>{var s=document.createElement("script");t.defaults2(s,t.omit(n,["unload","parent"]),{type:"text/javascript"}),s.async=!1,s.src=r,n.crossorigin&&(s.crossOrigin=n.crossorigin),s.onload=()=>e(r),s.onerror=()=>i(new Error(r)),n.parent.appendChild(s)})),e.loaded[r]}},t={isUndefined:e=>void 0===e,pick(e,t){var r={};return t.forEach(t=>{r[t]=e[t]}),r},omit(e,t){var r={};return Object.keys(e).forEach(n=>{-1===t.indexOf(n)&&(r[n]=e[n])}),r},omitBy(e,t){var r={};return Object.keys(e).forEach(n=>{t(e[n])||(r[n]=e[n])}),r},defaults2(e){for(var r=arguments.length,n=new Array(r>1?r-1:0),i=1;i<r;i++)n[i-1]=arguments[i];n.forEach(r=>{Object.keys(r).forEach(n=>{(t.isUndefined(e[n])||""===e[n])&&(e[n]=r[n])})})}};return e}); |
const rollup = require('rollup') | ||
const babel = require('rollup-plugin-babel') | ||
const uglify = require('rollup-plugin-uglify') | ||
const terser = require('rollup-plugin-terser').terser | ||
const fs = require('fs') | ||
@@ -35,7 +35,10 @@ | ||
pkg: pkg, | ||
checkDependencies: {this: {options: {install: true}}}, | ||
checkDependencies: { this: { options: { install: true } } }, | ||
exec: { | ||
eslint: 'node ./node_modules/eslint/bin/eslint.js "**/*.js"' | ||
}, | ||
rollup: { | ||
umd: { | ||
input: 'src/index.js', | ||
plugins: [babel({exclude: './node_modules/**'})], | ||
plugins: [babel({ exclude: './node_modules/**' })], | ||
output: { | ||
@@ -51,4 +54,4 @@ file: `dist/${pkg.name}.js`, | ||
plugins: [ | ||
babel({exclude: './node_modules/**'}), | ||
uglify({output: {preamble: banner}}) | ||
babel({ exclude: './node_modules/**' }), | ||
terser({ output: { preamble: banner } }) | ||
], | ||
@@ -61,4 +64,3 @@ output: { | ||
} | ||
}, | ||
standard: { dev: {} } | ||
} | ||
}) | ||
@@ -75,3 +77,3 @@ | ||
grunt.registerTask('default', ['standard', 'rollup']) | ||
grunt.registerTask('default', ['exec:eslint', 'rollup']) | ||
} | ||
@@ -78,0 +80,0 @@ |
{ | ||
"name": "vue-script2", | ||
"version": "2.0.3", | ||
"version": "2.1.0", | ||
"description": "Brings back <script> to your favorite Single Page App!", | ||
@@ -40,15 +40,34 @@ "main": "dist/vue-script2.js", | ||
}, | ||
"eslintConfig": { | ||
"root": true, | ||
"parserOptions": { | ||
"parser": "babel-eslint" | ||
}, | ||
"extends": [ | ||
"standard" | ||
] | ||
}, | ||
"eslintIgnore": [ | ||
"dist/*", | ||
"ignored/*" | ||
], | ||
"browserslist": "> 1% and since 2017 and not dead", | ||
"devDependencies": { | ||
"babel-core": "6.26.3", | ||
"babel-eslint": "8.2.3", | ||
"babel-plugin-external-helpers": "6.22.0", | ||
"babel-preset-env": "1.7.0", | ||
"grunt": "1.0.2", | ||
"@babel/core": "7.4.5", | ||
"@babel/preset-env": "7.4.5", | ||
"babel-eslint": "10.0.2", | ||
"eslint": "6.0.1", | ||
"eslint-config-standard": "12.0.0", | ||
"eslint-plugin-import": "2.18.0", | ||
"eslint-plugin-node": "9.1.0", | ||
"eslint-plugin-promise": "4.2.1", | ||
"eslint-plugin-standard": "4.0.0", | ||
"grunt": "1.0.4", | ||
"grunt-check-dependencies": "1.0.0", | ||
"grunt-standard": "3.1.0", | ||
"load-grunt-tasks": "4.0.0", | ||
"rollup": "0.58.2", | ||
"rollup-plugin-babel": "3.0.4", | ||
"rollup-plugin-uglify": "3.0.0" | ||
"grunt-exec": "3.0.0", | ||
"load-grunt-tasks": "5.0.0", | ||
"rollup": "1.16.2", | ||
"rollup-plugin-babel": "4.3.3", | ||
"rollup-plugin-terser": "5.0.0" | ||
} | ||
} |
var Script2 = { | ||
installed: false, | ||
p: Promise.resolve(), | ||
version: '2.0.3', // grunt will overwrite to match package.json | ||
loaded: {}, // keys are the scripts that have been loaded | ||
version: '2.1.0', // grunt will overwrite to match package.json | ||
loaded: {}, // keys are the scripts that is loading or loaded, values are promises | ||
install (Vue, options = {}) { | ||
@@ -19,3 +19,3 @@ if (Script2.installed) return | ||
// NOTE: Instead of using `template` we can use the `render` function like so: | ||
render (h) { return h('div', {style: 'display:none'}, this.$slots.default) }, | ||
render (h) { return h('div', { style: 'display:none' }, this.$slots.default) }, | ||
mounted () { | ||
@@ -31,2 +31,3 @@ var parent = this.$el.parentElement | ||
parent.appendChild(s) | ||
this.$emit('loaded') // any other proper way to do this or emit error? | ||
}) | ||
@@ -37,6 +38,9 @@ } else { | ||
// this syntax results in an implicit return | ||
var load = () => Script2.load(this.src, opts) | ||
_.isUndefined(this.async) | ||
var load = () => Script2.load(this.src, opts).then( | ||
() => this.$emit('loaded'), | ||
(err) => this.$emit('error', err) | ||
) | ||
_.isUndefined(this.async) || this.async === 'false' | ||
? Script2.p = Script2.p.then(load) // serialize execution | ||
: load() // inject immediately | ||
: load() // inject immediately | ||
} | ||
@@ -60,27 +64,29 @@ // see: https://vuejs.org/v2/guide/migration.html#ready-replaced | ||
}, | ||
load (src, opts = {parent: document.head}) { | ||
return Script2.loaded[src] ? Promise.resolve(src) | ||
: new Promise(function (resolve, reject) { | ||
var s = document.createElement('script') | ||
// omit the special options that Script2 supports | ||
_.defaults2(s, _.omit(opts, ['unload', 'parent']), {type: 'text/javascript'}) | ||
// according to: http://www.html5rocks.com/en/tutorials/speed/script-loading/ | ||
// async does not like 'document.write' usage, which we & vue.js make | ||
// heavy use of based on the SPA style. Also, async can result | ||
// in code getting executed out of order from how it is inlined on the page. | ||
s.async = false // therefore set this to false | ||
s.src = src | ||
// crossorigin in HTML and crossOrigin in the DOM per HTML spec | ||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-crossorigin | ||
if (opts.crossorigin) { | ||
s.crossOrigin = opts.crossorigin | ||
} | ||
// inspiration from: https://github.com/eldargab/load-script/blob/master/index.js | ||
// and: https://github.com/ded/script.js/blob/master/src/script.js#L70-L82 | ||
s.onload = () => { Script2.loaded[src] = 1; resolve(src) } | ||
// IE should now support onerror and onload. If necessary, take a look | ||
// at this to add older IE support: http://stackoverflow.com/a/4845802/1781435 | ||
s.onerror = () => reject(new Error(src)) | ||
opts.parent.appendChild(s) | ||
}) | ||
load (src, opts = { parent: document.head }) { | ||
if (!Script2.loaded[src]) { | ||
Script2.loaded[src] = new Promise((resolve, reject) => { | ||
var s = document.createElement('script') | ||
// omit the special options that Script2 supports | ||
_.defaults2(s, _.omit(opts, ['unload', 'parent']), { type: 'text/javascript' }) | ||
// according to: http://www.html5rocks.com/en/tutorials/speed/script-loading/ | ||
// async does not like 'document.write' usage, which we & vue.js make | ||
// heavy use of based on the SPA style. Also, async can result | ||
// in code getting executed out of order from how it is inlined on the page. | ||
s.async = false // therefore set this to false | ||
s.src = src | ||
// crossorigin in HTML and crossOrigin in the DOM per HTML spec | ||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-crossorigin | ||
if (opts.crossorigin) { | ||
s.crossOrigin = opts.crossorigin | ||
} | ||
// inspiration from: https://github.com/eldargab/load-script/blob/master/index.js | ||
// and: https://github.com/ded/script.js/blob/master/src/script.js#L70-L82 | ||
s.onload = () => resolve(src) | ||
// IE should now support onerror and onload. If necessary, take a look | ||
// at this to add older IE support: http://stackoverflow.com/a/4845802/1781435 | ||
s.onerror = () => reject(new Error(src)) | ||
opts.parent.appendChild(s) | ||
}) | ||
} | ||
return Script2.loaded[src] | ||
} | ||
@@ -87,0 +93,0 @@ } |
Sorry, the diff of this file is not supported yet
23990
337
16