edgardleal/require-vuejs

View on GitHub
src/css_parser.js

Summary

Maintainability
A
0 mins
Test Coverage
/*globals: define, require */
/*
 * css-parser.js
 *
 * Distributed under terms of the MIT license.
 */
/* jshint ignore:start */
if (typeof define !== "function") {
    var define = require("amdefine")(module);
}
/* jshint ignore:end */

define("css_parser", [], function() {
    "use strict";
    var idCount = 0;

    var appendCSSStyle = function(css, id) {
        if(css && typeof document !== "undefined") {
            var style = document.getElementById("style_" + id);
            if (style) {
                return style;
            }
            style = document.createElement("style");
            var head = document.head || document.getElementsByTagName("head")[0];

            style.type = "text/css";
            style.id = "style_" + id;
            if (style.styleSheet){
                style.styleSheet.cssText = css;
            } else {
                style.appendChild(document.createTextNode(css));
            }
            head.appendChild(style);
            return style;
        }
    };

    var functionString = function(parsed) {
        if (typeof document === "undefined")  // you are running optimization ( r.js )
            var document = createDocumentMock();

        var css = parsed.css;
        var attributeId = "data-style" + idCount;
        if ( css === false ) {
            return "";
        } else {
            if (parsed.scoped) {
                //css = css
                //    .replace(/(^|,)( *)\.([^ \s\n\r\t]+)[\s{]/gm, "$1$2[" + attributeId + "].$3");

                /* 修改 css scoped 实现,2021-6-17 */
                // 匹配html tag或 css类
                // css html tag -- \s+[\w-]+
                // css class -- \.[\w-]+
                css = css.replace(/(\s+[\w-]+|\.[\w-]+)\s*{/gm, "$1[" + attributeId + "] {");
            }
            css = css // turn into one line
                .replace(/([^\\])'/g, "$1\\'")
                .replace(/''/g, "'\\'")
                .replace(/[\n\r]+/g, " ")
                .replace(/ {2,20}/g, " ");
        }

        var result = "(" + appendCSSStyle.toString() + ")('" + css + "', " + idCount + ");\n";
        return result;
    };

    var createDocumentMock = function() {
        return {
            createElement: function() {},
            head: {},
            getElementsByTagName: function() {},
            createTextNode: function() {}
        };
    };

    var parseElement = function (doc) {
        // todo: 以下实现,同一个文件由于加载次序不同,style id会不同
        // 在《systemjs+compiler-sfc 实现浏览器端渲染 .vue 文件》中
        // https://zhuanlan.zhihu.com/p/408745521,用以下算法实现:
        // return res.text().then(function (source) {
        // var id = hash.sum(url + source);
        // var dataVId = 'data-v-' + id;
        // 这样的 style id 只于文件本身有关,与加载次序无关,可以借鉴
        idCount = idCount + 1;
        var queryResult = doc.getElementsByTagName("style");
        if (!queryResult || !queryResult.length) {
            return {
                id: 0,
                css: "",
                scoped: false,
                functionString: ""
            };
        }
        var style = queryResult[0];
        var scoped = style.hasAttribute("scoped");

        var result = {};
        result.css = style.innerHTML;
        result.id = idCount;
        result.scoped = scoped;
        //result.functionString =  functionString(result);

        //return result;

        /* for less.js override */
        if (!checkLess(style)) {
            result.functionString = functionString(result);
            return result
        }

        return parseLess(result);
    };

    // 是否解析less
    var checkLess = function (rawStyle) {
        // 非 less
        if (!rawStyle.hasAttribute("lang")
            || rawStyle.getAttribute("lang").toLowerCase() != "less") {
            return false;
        }
        // 无 less.js
        if (!less || !less.render) {
            return false
        }

        return true
    }

    var parseLess = function (parsedStyle) {
        let parse_result = parsedStyle;

        // 调用 less.js 解析less
        less.render(parse_result.css, function (err, less_result) {
            if (err) {
                console.log(err);
                console.log("parsed style =>");
                console.log(parse_result);
            }
            else {
                parse_result.css = less_result.css;
                parse_result.functionString = functionString(parse_result);
            }
        });

        return parse_result;
    }

    return {
        parseElement: parseElement
    };
});
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab : */