123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- (function umd(root,factory){
- if(typeof module==='object' && typeof exports === 'object' )
- module.exports=factory()
- else if(typeof define==='function' && define.amd)
- define([],factory)
- else
- root.httpVueLoader=factory()
- })(this,function factory() {
- 'use strict';
- var scopeIndex = 0;
- StyleContext.prototype = {
- withBase: function(callback) {
- var tmpBaseElt;
- if ( this.component.baseURI ) {
- // firefox and chrome need the <base> to be set while inserting or modifying <style> in a document.
- tmpBaseElt = document.createElement('base');
- tmpBaseElt.href = this.component.baseURI;
- var headElt = this.component.getHead();
- headElt.insertBefore(tmpBaseElt, headElt.firstChild);
- }
- callback.call(this);
- if ( tmpBaseElt )
- this.component.getHead().removeChild(tmpBaseElt);
- },
- scopeStyles: function(styleElt, scopeName) {
- function process() {
- var sheet = styleElt.sheet;
- var rules = sheet.cssRules;
- for ( var i = 0; i < rules.length; ++i ) {
- var rule = rules[i];
- if ( rule.type !== 1 )
- continue;
- var scopedSelectors = [];
- rule.selectorText.split(/\s*,\s*/).forEach(function(sel) {
- scopedSelectors.push(scopeName+' '+sel);
- var segments = sel.match(/([^ :]+)(.+)?/);
- scopedSelectors.push(segments[1] + scopeName + (segments[2]||''));
- });
- var scopedRule = scopedSelectors.join(',') + rule.cssText.substr(rule.selectorText.length);
- sheet.deleteRule(i);
- sheet.insertRule(scopedRule, i);
- }
- }
- try {
- // firefox may fail sheet.cssRules with InvalidAccessError
- process();
- } catch (ex) {
- if ( ex instanceof DOMException && ex.code === DOMException.INVALID_ACCESS_ERR ) {
- styleElt.sheet.disabled = true;
- styleElt.addEventListener('load', function onStyleLoaded() {
- styleElt.removeEventListener('load', onStyleLoaded);
- // firefox need this timeout otherwise we have to use document.importNode(style, true)
- setTimeout(function() {
- process();
- styleElt.sheet.disabled = false;
- });
- });
- return;
- }
- throw ex;
- }
- },
- compile: function() {
- var hasTemplate = this.template !== null;
- var scoped = this.elt.hasAttribute('scoped');
- if ( scoped ) {
- // no template, no scopable style needed
- if ( !hasTemplate )
- return;
- // firefox does not tolerate this attribute
- this.elt.removeAttribute('scoped');
- }
- this.withBase(function() {
- this.component.getHead().appendChild(this.elt);
- });
- if ( scoped )
- this.scopeStyles(this.elt, '['+this.component.getScopeId()+']');
- return Promise.resolve();
- },
- getContent: function() {
- return this.elt.textContent;
- },
- setContent: function(content) {
- this.withBase(function() {
- this.elt.textContent = content;
- });
- }
- };
- function StyleContext(component, elt) {
- this.component = component;
- this.elt = elt;
- }
- ScriptContext.prototype = {
- getContent: function() {
- return this.elt.textContent;
- },
- setContent: function(content) {
- this.elt.textContent = content;
- },
- compile: function(module) {
- var childModuleRequire = function(childURL) {
- return httpVueLoader.require(resolveURL(this.component.baseURI, childURL));
- }.bind(this);
- var childLoader = function(childURL, childName) {
- return httpVueLoader(resolveURL(this.component.baseURI, childURL), childName);
- }.bind(this);
- try {
- Function('exports', 'require', 'httpVueLoader', 'module', this.getContent()).call(this.module.exports, this.module.exports, childModuleRequire, childLoader, this.module);
- } catch(ex) {
- if ( !('lineNumber' in ex) ) {
- return Promise.reject(ex);
- }
- var vueFileData = responseText.replace(/\r?\n/g, '\n');
- var lineNumber = vueFileData.substr(0, vueFileData.indexOf(script)).split('\n').length + ex.lineNumber - 1;
- throw new (ex.constructor)(ex.message, url, lineNumber);
- }
- return Promise.resolve(this.module.exports)
- .then(httpVueLoader.scriptExportsHandler.bind(this))
- .then(function(exports) {
- this.module.exports = exports;
- }.bind(this));
- }
- };
- function ScriptContext(component, elt) {
- this.component = component;
- this.elt = elt;
- this.module = { exports:{} };
- }
- TemplateContext.prototype = {
- getContent: function() {
- return this.elt.innerHTML;
- },
- setContent: function(content) {
- this.elt.innerHTML = content;
- },
- getRootElt: function() {
- var tplElt = this.elt.content || this.elt;
- if ( 'firstElementChild' in tplElt )
- return tplElt.firstElementChild;
- for ( tplElt = tplElt.firstChild; tplElt !== null; tplElt = tplElt.nextSibling )
- if ( tplElt.nodeType === Node.ELEMENT_NODE )
- return tplElt;
- return null;
- },
- compile: function() {
- return Promise.resolve();
- }
- };
- function TemplateContext(component, elt) {
- this.component = component;
- this.elt = elt;
- }
- Component.prototype = {
- getHead: function() {
- return document.head || document.getElementsByTagName('head')[0];
- },
- getScopeId: function() {
- if ( this._scopeId === '' ) {
- this._scopeId = 'data-s-' + (scopeIndex++).toString(36);
- this.template.getRootElt().setAttribute(this._scopeId, '');
- }
- return this._scopeId;
- },
- load: function(componentURL) {
- return httpVueLoader.httpRequest(componentURL)
- .then(function(responseText) {
- this.baseURI = componentURL.substr(0, componentURL.lastIndexOf('/')+1);
- var doc = document.implementation.createHTMLDocument('');
- // IE requires the <base> to come with <style>
- doc.body.innerHTML = (this.baseURI ? '<base href="'+this.baseURI+'">' : '') + responseText;
- for ( var it = doc.body.firstChild; it; it = it.nextSibling ) {
- switch ( it.nodeName ) {
- case 'TEMPLATE':
- this.template = new TemplateContext(this, it);
- break;
- case 'SCRIPT':
- this.script = new ScriptContext(this, it);
- break;
- case 'STYLE':
- this.styles.push(new StyleContext(this, it));
- break;
- }
- }
- return this;
- }.bind(this));
- },
- _normalizeSection: function(eltCx) {
- var p;
- if ( eltCx === null || !eltCx.elt.hasAttribute('src') ) {
- p = Promise.resolve(null);
- } else {
- p = httpVueLoader.httpRequest(eltCx.elt.getAttribute('src'))
- .then(function(content) {
- eltCx.elt.removeAttribute('src');
- return content;
- });
- }
- return p
- .then(function(content) {
- if ( eltCx !== null && eltCx.elt.hasAttribute('lang') ) {
- var lang = eltCx.elt.getAttribute('lang');
- eltCx.elt.removeAttribute('lang');
- return httpVueLoader.langProcessor[lang.toLowerCase()].call(this, content === null ? eltCx.getContent() : content);
- }
- return content;
- }.bind(this))
- .then(function(content) {
- if ( content !== null )
- eltCx.setContent(content);
- });
- },
- normalize: function() {
- return Promise.all(Array.prototype.concat(
- this._normalizeSection(this.template),
- this._normalizeSection(this.script),
- this.styles.map(this._normalizeSection)
- ))
- .then(function() {
- return this;
- }.bind(this));
- },
- compile: function() {
- return Promise.all(Array.prototype.concat(
- this.template && this.template.compile(),
- this.script && this.script.compile(),
- this.styles.map(function(style) { return style.compile(); })
- ))
- .then(function() {
- return this;
- }.bind(this));
- }
- };
- function Component(name) {
- this.name = name;
- this.template = null;
- this.script = null;
- this.styles = [];
- this._scopeId = '';
- }
- function identity(value) {
- return value;
- }
- function parseComponentURL(url) {
- var comp = url.match(/(.*?)([^/]+?)\/?(\.vue)?(\?.*|#.*|$)/);
- return {
- name: comp[2],
- url: comp[1] + comp[2] + (comp[3] === undefined ? '/index.vue' : comp[3]) + comp[4]
- };
- }
- function resolveURL(baseURL, url) {
- if (url.substr(0, 2) === './' || url.substr(0, 3) === '../') {
- return baseURL + url;
- }
- return url;
- }
- httpVueLoader.load = function(url, name) {
- return function() {
- return new Component(name).load(url)
- .then(function(component) {
- return component.normalize();
- })
- .then(function(component) {
- return component.compile();
- })
- .then(function(component) {
- var exports = component.script !== null ? component.script.module.exports : {};
- if ( component.template !== null )
- exports.template = component.template.getContent();
- if ( exports.name === undefined )
- if ( component.name !== undefined )
- exports.name = component.name;
- exports._baseURI = component.baseURI;
- return exports;
- });
- };
- };
- httpVueLoader.register = function(Vue, url) {
- var comp = parseComponentURL(url);
- Vue.component(comp.name, httpVueLoader.load(comp.url));
- };
- httpVueLoader.install = function(Vue) {
- Vue.mixin({
- beforeCreate: function () {
- var components = this.$options.components;
- for ( var componentName in components ) {
- if ( typeof(components[componentName]) === 'string' && components[componentName].substr(0, 4) === 'url:' ) {
- var comp = parseComponentURL(components[componentName].substr(4));
- var componentURL = ('_baseURI' in this.$options) ? resolveURL(this.$options._baseURI, comp.url) : comp.url;
- if ( isNaN(componentName) )
- components[componentName] = httpVueLoader.load(componentURL, componentName);
- else
- components[componentName] = Vue.component(comp.name, httpVueLoader.load(componentURL, comp.name));
- }
- }
- }
- });
- };
- httpVueLoader.require = function(moduleName) {
- return window[moduleName];
- };
- httpVueLoader.httpRequest = function(url) {
- return new Promise(function(resolve, reject) {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url);
- xhr.responseType = 'text';
- xhr.onreadystatechange = function() {
- if ( xhr.readyState === 4 ) {
- if ( xhr.status >= 200 && xhr.status < 300 )
- resolve(xhr.responseText);
- else
- reject(xhr.status);
- }
- };
- xhr.send(null);
- });
- };
- httpVueLoader.langProcessor = {
- html: identity,
- js: identity,
- css: identity
- };
- httpVueLoader.scriptExportsHandler = identity;
- function httpVueLoader(url, name) {
- var comp = parseComponentURL(url);
- return httpVueLoader.load(comp.url, name);
- }
- return httpVueLoader;
- });
|