vue-script2
Advanced tools
Comparing version 1.1.2 to 1.2.0
/*! | ||
* vue-script2 v1.1.2 | ||
* vue-script2 v1.2.0 | ||
* (c) 2016 Greg Slepak | ||
@@ -20,53 +20,81 @@ * @license MIT License | ||
p: Promise.resolve(), | ||
version: '1.1.2', // grunt will over write to match package.json | ||
loaded: {} // keys are the scripts that have been loaded | ||
}; | ||
version: '1.2.0', // grunt will over write to match package.json | ||
loaded: {}, // keys are the scripts that have been loaded | ||
install: function install(Vue) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
Script2.install = function (Vue) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
if (Script2.installed) return; | ||
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>', | ||
ready: function ready() { | ||
var _this = this; | ||
if (Script2.installed) return; | ||
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>', | ||
ready: function ready() { | ||
var _this = this; | ||
var parent = this.$el.parentElement; | ||
if (!this.src) { | ||
Script2.p = Script2.p.then(function () { | ||
var s = document.createElement('script'); | ||
s.type = 'text/javascript'; | ||
s.appendChild(document.createTextNode(_this.$el.innerHTML)); | ||
parent.appendChild(s); | ||
}); | ||
} else if (!Script2.loaded[this.src]) { | ||
var params = _.omitBy(_.pick(this, props), _.isUndefined); | ||
// this syntax results in an implicit return | ||
var load = function load() { | ||
return inject(parent, _this.src, params).then(function () { | ||
return Script2.loaded[_this.src] = 1; | ||
var parent = this.$el.parentElement; | ||
if (!this.src) { | ||
Script2.p = Script2.p.then(function () { | ||
var s = document.createElement('script'); | ||
s.type = 'text/javascript'; | ||
s.appendChild(document.createTextNode(_this.$el.innerHTML)); | ||
parent.appendChild(s); | ||
}); | ||
}; | ||
_.isUndefined(this.async) ? Script2.p = Script2.p.then(load) // serialize execution | ||
: load(); // inject immediately | ||
} 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 | ||
: load(); // inject immediately | ||
} | ||
Vue.util.remove(this.$el); // remove dummy template <div> | ||
}, | ||
destroyed: function destroyed() { | ||
if (this.unload) { | ||
new Function(this.unload)(); // eslint-disable-line | ||
delete Script2.loaded[this.src]; | ||
} | ||
} | ||
Vue.util.remove(this.$el); // remove dummy template <div> | ||
}, | ||
destroyed: function 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 ? { parent: document.head } : arguments[1]; | ||
if (Script2.loaded[src]) return Promise.resolve(src); | ||
return new Promise(function (resolve, reject) { | ||
var _this2 = this; | ||
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; | ||
// 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 | ||
function success() { | ||
Script2.loaded[src] = 1;resolve(src); | ||
} | ||
} | ||
}); | ||
Script2.installed = true; | ||
s.onload = success; | ||
s.onreadystatechange = function () { | ||
return _this2.readyState === 'complete' && success(); | ||
}; // IE | ||
s.onerror = function () { | ||
return reject(new Error(src)); | ||
}; | ||
opts.parent.appendChild(s); | ||
}); | ||
} | ||
}; | ||
@@ -108,5 +136,3 @@ | ||
Object.keys(s).forEach(function (k) { | ||
if ((_.isUndefined(o[k]) || o[k] === '') && s[k] !== '') { | ||
o[k] = s[k]; | ||
} | ||
if (_.isUndefined(o[k]) || o[k] === '') o[k] = s[k]; | ||
}); | ||
@@ -117,37 +143,4 @@ }); | ||
function inject(el, src) { | ||
var opts = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; | ||
return new Promise(function (resolve, reject) { | ||
var _this2 = this; | ||
var s = document.createElement('script'); | ||
// omit the special options that Script2 supports | ||
_.defaults2(s, _.omit(opts, ['unload']), { | ||
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; | ||
// 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 | ||
function success() { | ||
resolve(src); | ||
} | ||
s.onload = success; | ||
s.onreadystatechange = function () { | ||
return _this2.readyState === 'complete' && success(); | ||
}; // IE | ||
s.onerror = function () { | ||
return reject(new Error('failed to load:' + src)); | ||
}; | ||
el.appendChild(s); | ||
}); | ||
} | ||
return Script2; | ||
})); |
/*! | ||
* vue-script2 v1.1.2 | ||
* vue-script2 v1.2.0 | ||
* (c) 2016 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";function e(e,n){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2];return new Promise(function(o,r){function c(){o(n)}var a=this,d=document.createElement("script");t.defaults2(d,t.omit(i,["unload"]),{type:"text/javascript"}),d.async=!1,d.src=n,d.onload=c,d.onreadystatechange=function(){return"complete"===a.readyState&&c()},d.onerror=function(){return r(new Error("failed to load:"+n))},e.appendChild(d)})}var n={installed:!1,p:Promise.resolve(),version:"1.1.2",loaded:{}};n.install=function(i){arguments.length<=1||void 0===arguments[1]?{}:arguments[1];if(!n.installed){var o=["unload"],r=o.concat(["src","type","async","integrity","text","crossorigin"]);i.component("script2",{props:r,template:'<div style="display:none"><slot></slot></div>',ready:function(){var o=this,c=this.$el.parentElement;if(this.src){if(!n.loaded[this.src]){var a=t.omitBy(t.pick(this,r),t.isUndefined),d=function(){return e(c,o.src,a).then(function(){return n.loaded[o.src]=1})};t.isUndefined(this.async)?n.p=n.p.then(d):d()}}else n.p=n.p.then(function(){var e=document.createElement("script");e.type="text/javascript",e.appendChild(document.createTextNode(o.$el.innerHTML)),c.appendChild(e)});i.util.remove(this.$el)},destroyed:function(){this.unload&&(new Function(this.unload)(),delete n.loaded[this.src])}}),n.installed=!0}};var t={isUndefined:function(e){return void 0===e},pick:function(e,n){var t={};return n.forEach(function(n){return 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 n=arguments.length,i=Array(n>1?n-1:0),o=1;n>o;o++)i[o-1]=arguments[o];i.forEach(function(n){Object.keys(n).forEach(function(i){!t.isUndefined(e[i])&&""!==e[i]||""===n[i]||(e[i]=n[i])})})}};return n}); | ||
!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:"1.2.0",loaded:{},install:function(t){arguments.length<=1||void 0===arguments[1]?{}:arguments[1];if(!e.installed){var i=["unload"],o=i.concat(["src","type","async","integrity","text","crossorigin"]);t.component("script2",{props:o,template:'<div style="display:none"><slot></slot></div>',ready:function(){var i=this,r=this.$el.parentElement;if(this.src){var a=n.omitBy(n.pick(this,o),n.isUndefined);a.parent=r;var c=function(){return e.load(i.src,a)};n.isUndefined(this.async)?e.p=e.p.then(c):c()}else e.p=e.p.then(function(){var e=document.createElement("script");e.type="text/javascript",e.appendChild(document.createTextNode(i.$el.innerHTML)),r.appendChild(e)});t.util.remove(this.$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]?{parent:document.head}:arguments[1];return e.loaded[t]?Promise.resolve(t):new Promise(function(o,r){function a(){e.loaded[t]=1,o(t)}var c=this,d=document.createElement("script");n.defaults2(d,n.omit(i,["unload","parent"]),{type:"text/javascript"}),d.async=!1,d.src=t,d.onload=a,d.onreadystatechange=function(){return"complete"===c.readyState&&a()},d.onerror=function(){return r(new Error(t))},i.parent.appendChild(d)})}},n={isUndefined:function(e){return void 0===e},pick:function(e,n){var t={};return n.forEach(function(n){return 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),o=1;t>o;o++)i[o-1]=arguments[o];i.forEach(function(t){Object.keys(t).forEach(function(i){(n.isUndefined(e[i])||""===e[i])&&(e[i]=t[i])})})}};return e}); |
{ | ||
"name": "vue-script2", | ||
"version": "1.1.2", | ||
"description": "Standardized, designer-friendly <script> behavior for your Single Page App", | ||
"version": "1.2.0", | ||
"description": "Brings back <script> to your favorite Single Page App!", | ||
"main": "dist/vue-script2.js", | ||
@@ -26,2 +26,3 @@ "jsnext:main": "src/index.js", | ||
"loader", | ||
"load", | ||
"spa", | ||
@@ -28,0 +29,0 @@ "vuejs", |
@@ -1,10 +0,14 @@ | ||
# vue-script2 | ||
# VueScript2 - Simple, Familiar Asynchronous Script Loading | ||
Fully restores the `<script>` tag to front-end single-page-app (SPA) frameworks! This version is for [Vue.js](http://vuejs.org), but it's easy to port to [Riot.js](http://riotjs.com) and others. | ||
VueScript2 brings back the `<script>` tag to your SPA (Single Page App)! | ||
It's meant for internal use, not for standalone components that are being shared publicly. Those should be "self-contained" and come with all the JS they need. | ||
This tiny library should take care of all your [declarative](#familiar-declarative-asynchronous-loading-of-scripts) and [imperative](#promise-based-imperative-loading-too) asynchronous loading needs. Web designers can rest easy that their existing knowledge of web development is still useful! | ||
This version is tailored for the [Vue.js](http://vuejs.org) framework, but it's easy to port to [Riot.js](http://riotjs.com) and others. | ||
VueScript2 is primarily for internal use and not for standalone components that are being shared publicly. Those should be "self-contained" and come with all the JS they need. | ||
## Features | ||
- Just like `<script>` except with a `2`, but [even that can be fixed!](#using-script-via-browserify-transform) | ||
- Just like `<script>` except with a `2`, but [even that can be fixed!](#writing-script-instead-of-script2-using-script2ify) | ||
- Keep your `app.js` bundle small! | ||
@@ -17,4 +21,7 @@ - Embrace Web Standards™ everyone knows and loves! | ||
- Ordered execution based on position in markup! | ||
- Special `unload` attribute can be used to keep your app's memory usage low! | ||
- Special [`unload` attribute](#cleanup-unused-resources-with-the-unload-attribute) can be used to keep your app's memory usage low! | ||
- Does [imperative loading](#promise-based-imperative-loading-too) too, no need for RequireJS/SystemJS/etc.! | ||
Oh, and it's easy to modify this library to also support imperative loading of | ||
## Installation | ||
@@ -34,5 +41,5 @@ | ||
*Note: all of the examples below use `<script2>`, but you can write `<script>` instead by using the [`script2ify` browserify transform provided below!](#using-script-via-browserify-transform)* :smile: | ||
_Note: you can write_ __*`<script>`*__ *instead of* __*`<script2>`*__ _using [`script2ify`!](#writing-script-instead-of-script2-using-script2ify)_ :smile: | ||
__Simple, Traditional, Asynchronous Loading of Scripts__ | ||
##### Familiar, declarative, asynchronous loading of scripts | ||
@@ -49,6 +56,18 @@ Using `vue-script2` with [`vue-router`](https://github.com/vuejs/vue-router) is simple. Say that only one of your routes displays a "page" that makes use of jQuery. Well, no need to include all of jQuery in your `app.js` bundle, now you can throw this in: | ||
__Delayed Execution of Inlined JavaScript__ | ||
##### Promise-based imperative loading too! | ||
Want to run some JavaScript only when a certain "page"/route is loaded? | ||
No need to bundle RequireJS/SystemJS or whatever else. Call `VueScript2.load` to immediately load a script. | ||
```js | ||
VueScript2.load('/path/to/jquery.min.js').then(function () { | ||
$('#msg').text('Hello from VueScript2!') | ||
}) | ||
``` | ||
_All scripts injected using `VueScript2.load` are [`async`](#special-support-for-async-attribute)._ | ||
##### Delayed execution of inlined JavaScript | ||
Want to run some JavaScript only when a specific "page"/route is visited and only after a library has finished loading? Simple! | ||
```html | ||
@@ -59,4 +78,4 @@ <script2 src="/path/to/jquery.min.js"></script2> | ||
$(document).ready(function () { | ||
// this code runs *only* when the route | ||
// that contains this code is loaded! :D->-< | ||
// this code runs *only* when the route | ||
// that contains this code is loaded! :D->-< | ||
}) | ||
@@ -66,3 +85,3 @@ </script2> | ||
__Cleaning Up Resources On Route Change__ | ||
##### Cleanup unused resources with the `unload` attribute | ||
@@ -75,3 +94,3 @@ The `unload` attribute accepts JS expressions to run when the component is destroyed. This prevents your SPA from accumulating stuff in memory that's not being used: | ||
__Special support for `async` attribute__ | ||
##### Special support for `async` attribute | ||
@@ -91,5 +110,5 @@ Although technically all scripts are inserted with `s.async = false` (since we're using `document.write`, see [this wonderful article](http://www.html5rocks.com/en/tutorials/speed/script-loading/) by [Jake Archibald](https://twitter.com/jaffathecake) for details), setting the `async` attribute does make a meaningful difference. | ||
## Using `<script>` via browserify transform | ||
## Writing `<script>` instead of `<script2>` using `script2ify` | ||
The `script2ify` browserify transform below will (fairly safely) dynamically replace `<script>` tags with `<script2>` tags within `.ejs`, `.html`, and even `.vue` files! | ||
The `script2ify` [browserify](https://github.com/substack/node-browserify) transform below will (fairly safely) dynamically replace `<script>` tags with `<script2>` tags within `.ejs`, `.html`, and even `.vue` files! | ||
@@ -124,2 +143,3 @@ ```js | ||
- __1.2.0__ - Added `VueScript2.load` imperative loading | ||
- __1.1.2__ - Another bump to get npm.org to display `script2ify` in the README | ||
@@ -126,0 +146,0 @@ - __1.1.1__ - Identical to `1.1.0`, just adds needed package.json info. |
133
src/index.js
@@ -9,46 +9,66 @@ // To use, just: | ||
p: Promise.resolve(), | ||
version: '1.1.2', // grunt will over write to match package.json | ||
loaded: {} // keys are the scripts that have been loaded | ||
} | ||
Script2.install = function (Vue, options = {}) { | ||
if (Script2.installed) return | ||
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>', | ||
ready () { | ||
var parent = this.$el.parentElement | ||
if (!this.src) { | ||
Script2.p = Script2.p.then(() => { | ||
var s = document.createElement('script') | ||
s.type = 'text/javascript' | ||
s.appendChild(document.createTextNode(this.$el.innerHTML)) | ||
parent.appendChild(s) | ||
}) | ||
} else if (!Script2.loaded[this.src]) { | ||
var params = _.omitBy(_.pick(this, props), _.isUndefined) | ||
// this syntax results in an implicit return | ||
var load = () => inject(parent, this.src, params).then(() => Script2.loaded[this.src] = 1) | ||
_.isUndefined(this.async) | ||
? Script2.p = Script2.p.then(load) // serialize execution | ||
: load() // inject immediately | ||
version: '1.2.0', // grunt will over write to match package.json | ||
loaded: {}, // keys are the scripts that have been loaded | ||
install (Vue, options = {}) { | ||
if (Script2.installed) return | ||
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>', | ||
ready () { | ||
var parent = this.$el.parentElement | ||
if (!this.src) { | ||
Script2.p = Script2.p.then(() => { | ||
var s = document.createElement('script') | ||
s.type = 'text/javascript' | ||
s.appendChild(document.createTextNode(this.$el.innerHTML)) | ||
parent.appendChild(s) | ||
}) | ||
} else { | ||
var opts = _.omitBy(_.pick(this, props), _.isUndefined) | ||
opts.parent = parent | ||
// this syntax results in an implicit return | ||
var load = () => Script2.load(this.src, opts) | ||
_.isUndefined(this.async) | ||
? Script2.p = Script2.p.then(load) // serialize execution | ||
: load() // inject immediately | ||
} | ||
Vue.util.remove(this.$el) // remove dummy template <div> | ||
}, | ||
destroyed () { | ||
if (this.unload) { | ||
new Function(this.unload)() // eslint-disable-line | ||
delete Script2.loaded[this.src] | ||
} | ||
} | ||
Vue.util.remove(this.$el) // remove dummy template <div> | ||
}, | ||
destroyed () { | ||
if (this.unload) { | ||
new Function(this.unload)() // eslint-disable-line | ||
delete Script2.loaded[this.src] | ||
} | ||
} | ||
}) | ||
Script2.installed = true | ||
}) | ||
Script2.installed = true | ||
}, | ||
load (src, opts = {parent: document.head}) { | ||
if (Script2.loaded[src]) return Promise.resolve(src) | ||
return 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 | ||
// 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 | ||
function success () { Script2.loaded[src] = 1; resolve(src) } | ||
s.onload = success | ||
s.onreadystatechange = () => this.readyState === 'complete' && success() // IE | ||
s.onerror = () => reject(new Error(src)) | ||
opts.parent.appendChild(s) | ||
}) | ||
} | ||
} | ||
@@ -77,5 +97,3 @@ | ||
Object.keys(s).forEach((k) => { | ||
if ((_.isUndefined(o[k]) || o[k] === '') && s[k] !== '') { | ||
o[k] = s[k] | ||
} | ||
if (_.isUndefined(o[k]) || o[k] === '') o[k] = s[k] | ||
}) | ||
@@ -86,25 +104,2 @@ }) | ||
function inject (el, src, opts = {}) { | ||
return new Promise(function (resolve, reject) { | ||
var s = document.createElement('script') | ||
// omit the special options that Script2 supports | ||
_.defaults2(s, _.omit(opts, ['unload']), { | ||
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 | ||
// 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 | ||
function success () { resolve(src) } | ||
s.onload = success | ||
s.onreadystatechange = () => this.readyState === 'complete' && success() // IE | ||
s.onerror = () => reject(new Error('failed to load:' + src)) | ||
el.appendChild(s) | ||
}) | ||
} | ||
export default Script2 |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
20068
145
289