edgardleal/require-vuejs

View on GitHub
src/plugin.js

Summary

Maintainability
A
3 hrs
Test Coverage
/*
 * vue.js
 *
 * Distributed under terms of the MIT license.
 */
/* global Promise */
/* jshint ignore:start */
if (typeof define !== "function") {
    var define = require("amdefine")(module);
}
/* jshint ignore:end */

define("plugin", ["css_parser", "template_parser", "template_preprocessor", "style_import"], function (css_parser, template_parser, template_preprocessor, style_import) {
    "use strict";

    var modulesLoaded = {};

    var functionTemplate = ["(function(template){", "})("];

    var parse = function(text) {
        var doc = document.implementation.createHTMLDocument("");
        //doc.body.innerHTML = text;
        /* 单标记、驼峰命名属性等预处理,石永琳,2021-6-15 */
        doc.body.innerHTML = template_preprocessor.handle(text);  //text;
        var scriptElement = doc.getElementsByTagName("script")[0];
        var source = scriptElement.innerHTML;
        var css_result = css_parser.parseElement(doc);
        var template = template_parser.extractTemplate(doc, css_result);
        var functionString = css_result.functionString;
        if (!source || source.length < 10) {
            source = scriptElement.src;
            source = "define(['" + source + "'], function(comp) {\n comp.template = template;\n return comp;\n});\n";
        }
 
        return functionTemplate[0] +
         source +
          functionString +
          functionTemplate[1] +
          template + ");";
    };

    var loadLocal = function(url, name) {
        var fs = require.nodeRequire("fs");
        var text = fs.readFileSync(url, "utf-8");
        if(text[0] === "\uFEFF") { // remove BOM ( Byte Mark Order ) from utf8 files 
            text = text.substring(1);
        }
        var parsed = parse(text).replace(/(define\()\s*(\[.*)/, "$1\"vue!" + name + "\", $2");
        return parsed;
    };

    return {
        /**
         * 暴露 sfc 解析函数, 2023-1-16
         *
        ==================================================================================*/
        parseSfc: parse,
        helper: {
            preprocessor: template_preprocessor,
            css_parser,
            template_parser,
            style_import
        },
        /*=================================================================================*/
        normalize: function(name, normalize) {
            return normalize(name);
        },
        write: function(pluginName, moduleName, write) {
            write.asModule(pluginName + "!" + moduleName, modulesLoaded[moduleName]);
        },
        load: function (name, req, onload, config) {
            var url, extension; 

            if (config.paths && config.paths[name]) {
                name = config.paths[name];
            }

            // 增加对 razor page 的处理,2021-6-29
            if (/.*(\.cs)/.test(name)) {
                name = name.substring(0, name.length - 3);
                extension = "";
            } else
            // if file name has an extension, don't add .vue
            if(/.*(\.vue)|(\.html?)/.test(name)) {
                extension = "";
            } else {
                extension = ".vue";
            }

            url = req.toUrl(name + extension);

            // this is used to browser to create a way to debug the file 
            var sourceHeader = config.isBuild?"" : "//# sourceURL=" + location.origin + url + "\n";
            var loadRemote;

            if(config.isBuild) {
                loadRemote = function(url, callback) {
                    callback = callback || function() {};
                    return new Promise(function(resolve, reject) {
                        try {
                            var fs = require.nodeRequire("fs");
                            var text = fs.readFileSync(url, "utf-8").toString();
                            if(text[0] === "\uFEFF") { // remove BOM ( Byte Mark Order ) from utf8 files 
                                text = text.substring(1);
                            }
                            var parsed = parse(text).replace(/(define\()\s*(\[.*)/, "$1\"" + name + "\", $2");
                            callback(parsed);
                            resolve(parsed);
                        } catch(error) {
                            reject(error);
                        }
                    });
                };
            } else {
                loadRemote = function(path, callback) {
                    callback = callback || function() {};
                    return new Promise(function(resolve, reject) {
                        var xhttp = new XMLHttpRequest();
                        xhttp.timeout = (
                            (config.waitSeconds || config.timeout) || 3
                        ) * 1000;
                        xhttp.onreadystatechange = function() {
                            //if (xhttp.readyState === 4
                            //    && xhttp.status < 400) {
                            //    var result = parse(xhttp.responseText);
                            //    callback(result);
                            //    resolve(result);
                            //}
                            if (xhttp.readyState === 4) {
                                if (xhttp.status < 400) {
                                    style_import.loadAndMerge(path, xhttp.responseText, req)
                                        .then(merged => {
                                            var result = parse(merged);
                                            callback(result);
                                            resolve(result);
                                        })
                                }
                                else {
                                    reject(xhttp.status)
                                    throw "No response available for request:" + path + ", status code: " + xhttp.status
                                }
                            }
                        };
                        xhttp.onerror = function (e) {
                            reject(e)
                            throw "Error loading: " + path;
                        }
                        xhttp.ontimeout = function() {
                            var error = new Error("Timeout loading: " + path);
                            callback({}, error);
                            reject(error);
                            throw error;
                        };
                        xhttp.open("GET", path, true);
                        xhttp.send();
                    });
                };
            }

            req([], function() {
                if(config.isBuild) {
                    var data = loadLocal(url, name);
                    modulesLoaded[name] = data;
                    onload.fromText(data);
                } else {
                    loadRemote(url)
                        .then(function(text, error){
                            if (error) {
                                onload.error(error);
                                throw new Error("Error loading: " + url);
                            }
                            modulesLoaded[name] = sourceHeader + text;
                            onload.fromText(modulesLoaded[name]);
                        })
                        .catch(function(error) {
                            var message = error ? error.message || "Error: " : "Error !";
                            message += "\n Url: " + url;
                            throw new Error(message);
                        });
                }
            });
        }
    };
});
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab : */