提交 b9d4e395 编写于 作者: Y yylgit

delete

上级 93333b1f
......@@ -30,7 +30,10 @@ module.exports = function(options) {
]
},
plugins: [
new MvvmGraphPlugin()
new MvvmGraphPlugin({
cmlType: type,
media
})
]
};
// options.moduleIdType = 'hash';
......
const CMLNode = require('./cmlNode.js');
const path = require('path');
const MvvmCompiler = require('./compiler.js');
class mvvmGraphPlugin {
constructor() {
this.moduleRule = [ // 文件后缀对应module信息
{
test: /\.css|\.less$/,
moduleType: 'style',
attrs: {
lang: 'less'
}
},
{
test: /\.stylus|\.styls$/,
moduleType: 'style',
attrs: {
lang: 'stylus'
}
},
{
test: /\.js|\.interface$/,
moduleType: 'script'
},
{
test: /\.json$/,
moduleType: 'json'
},
{
test: /\.(png|jpe?g|gif|svg|mp4|webm|ogg|mp3|wav|flac|aac|woff|woff2?|eot|ttf|otf)(\?.*)?$/,
moduleType: 'asset'
}
]
constructor(options = {}) {
this.options = options;
}
apply(compiler) {
let npmName = cml.config.get().extPlatform[this.options.cmlType];
let PlatformPlugin = require(path.join(cml.projectRoot, 'node_modules', npmName)); // eslint-disable-line
let plugin = new PlatformPlugin(this.options);
let mvvmCompiler = new MvvmCompiler(compiler);
plugin.register(mvvmCompiler);
compiler.plugin('should-emit', function(compilation) {
mvvmCompiler.run(compilation.modules);
......
{
// 在配置文件里配置全局变量时,使用 globals 指出你要使用的全局变量。将变量设置为 true 将允许变量被重写,或 false 将不允许被重写
"globals": {
"cml": false
},
// 环境定义了预定义的全局变量。
"env": {
//环境定义了预定义的全局变量。更多在官网查看
"browser": true,
"node": true,
"commonjs": true,
"amd": true,
"es6": true,
"mocha": true
},
// JavaScript 语言选项
"parserOptions": {
// ECMAScript 版本
"ecmaVersion": 9,
"sourceType": "module", //设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)。
//想使用的额外的语言特性:
"ecmaFeatures": {
// 允许在全局作用域下使用 return 语句
"globalReturn": true,
// impliedStric
"impliedStrict": true,
// 启用 JSX
"jsx": true,
"modules": true
}
},
//-----让eslint支持 JSX start
"plugins": [
],
"extends": [
"eslint:recommended"
],
//-----让eslint支持 JSX end
/**
* "off" 或 0 - 关闭规则
* "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出),
* "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
*/
"rules": {
////////////////
// 可能的错误 //
////////////////
// 禁止条件表达式中出现赋值操作符
"no-cond-assign": 2,
// 禁用 console
"no-console": 0,
// 禁止在条件中使用常量表达式
// if (false) {
// doSomethingUnfinished();
// } //cuowu
"no-constant-condition": 2,
// 禁止在正则表达式中使用控制字符 :new RegExp("\x1f")
"no-control-regex": 2,
// 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,
// always-multiline:多行模式必须带逗号,单行模式不能带逗号
"comma-dangle": [1, "never"],
// 禁用 debugger
"no-debugger": 2,
// 禁止 function 定义中出现重名参数
"no-dupe-args": 2,
// 禁止对象字面量中出现重复的 key
"no-dupe-keys": 2,
// 禁止重复的 case 标签
"no-duplicate-case": 2,
// 禁止空语句块
"no-empty": 2,
// 禁止在正则表达式中使用空字符集 (/^abc[]/)
"no-empty-character-class": 2,
// 禁止对 catch 子句的参数重新赋值
"no-ex-assign": 2,
// 禁止不必要的布尔转换
"no-extra-boolean-cast": 2,
// 禁止不必要的括号 //(a * b) + c;//报错
"no-extra-parens": 0,
// 禁止不必要的分号
"no-extra-semi": 2,
// 禁止对 function 声明重新赋值
"no-func-assign": 2,
// 禁止在嵌套的块中出现 function 或 var 声明
"no-inner-declarations": [2, "functions"],
// 禁止 RegExp 构造函数中无效的正则表达式字符串
"no-invalid-regexp": 2,
// 禁止在字符串和注释之外不规则的空白
"no-irregular-whitespace": 2,
// 禁止在 in 表达式中出现否定的左操作数
"no-negated-in-lhs": 2,
// 禁止把全局对象 (Math 和 JSON) 作为函数调用 错误:var math = Math();
"no-obj-calls": 2,
// 禁止直接使用 Object.prototypes 的内置属性
"no-prototype-builtins": 0,
// 禁止正则表达式字面量中出现多个空格
"no-regex-spaces": 2,
// 禁用稀疏数组
"no-sparse-arrays": 2,
// 禁止出现令人困惑的多行表达式
"no-unexpected-multiline": 2,
// 禁止在return、throw、continue 和 break语句之后出现不可达代码
"no-unreachable": 2,
// 要求使用 isNaN() 检查 NaN
"use-isnan": 2,
// 强制使用有效的 JSDoc 注释
"valid-jsdoc": 0,
// 强制 typeof 表达式与有效的字符串进行比较
// typeof foo === "undefimed" 错误
"valid-typeof": 2,
//////////////
// 最佳实践 //
//////////////
// 定义对象的set存取器属性时,强制定义get
"accessor-pairs": 2,
// 强制数组方法的回调函数中有 return 语句
"array-callback-return": 0,
// 强制把变量的使用限制在其定义的作用域范围内
"block-scoped-var": 0,
// 限制圈复杂度,也就是类似if else能连续接多少个
"complexity": [2, 20],
// 要求 return 语句要么总是指定返回的值,要么不指定
"consistent-return": 0,
// 强制所有控制语句使用一致的括号风格
"curly": [2, "all"],
// switch 语句强制 default 分支,也可添加 // no default 注释取消此次警告
"default-case": 2,
// 强制object.key 中 . 的位置,参数:
// property,'.'号应与属性在同一行
// object, '.' 号应与对象名在同一行
"dot-location": [2, "property"],
// 强制使用.号取属性
// 参数: allowKeywords:true 使用保留字做属性名时,只能使用.方式取属性
// false 使用保留字做属性名时, 只能使用[]方式取属性 e.g [2, {"allowKeywords": false}]
// allowPattern: 当属性名匹配提供的正则表达式时,允许使用[]方式取值,否则只能用.号取值 e.g [2, {"allowPattern": "^[a-z]+(_[a-z]+)+$"}]
"dot-notation": [2, {
"allowKeywords": false
}],
// 使用 === 替代 == allow-null允许null和undefined==
"eqeqeq": [0, "allow-null"],
// 要求 for-in 循环中有一个 if 语句
"guard-for-in": 2,
// 禁用 alert、confirm 和 prompt
"no-alert": 0,
// 禁用 arguments.caller 或 arguments.callee
"no-caller": 2,
// 不允许在 case 子句中使用词法声明
"no-case-declarations": 2,
// 禁止除法操作符显式的出现在正则表达式开始的位置
"no-div-regex": 2,
// 禁止 if 语句中有 return 之后有 else
"no-else-return": 0,
// 禁止出现空函数.如果一个函数包含了一条注释,它将不会被认为有问题。
"no-empty-function": 2,
// 禁止使用空解构模式no-empty-pattern
"no-empty-pattern": 2,
// 禁止在没有类型检查操作符的情况下与 null 进行比较
"no-eq-null": 1,
// 禁用 eval()
"no-eval": 2,
// 禁止扩展原生类型
"no-extend-native": 2,
// 禁止不必要的 .bind() 调用
"no-extra-bind": 2,
// 禁用不必要的标签
"no-extra-label:": 0,
// 禁止 case 语句落空
"no-fallthrough": 2,
// 禁止数字字面量中使用前导和末尾小数点
"no-floating-decimal": 2,
// 禁止使用短符号进行类型转换(!!fOO)
"no-implicit-coercion": 0,
// 禁止在全局范围内使用 var 和命名的 function 声明
"no-implicit-globals": 1,
// 禁止使用类似 eval() 的方法
"no-implied-eval": 2,
// 禁止 this 关键字出现在类和类对象之外
"no-invalid-this": 0,
// 禁用 __iterator__ 属性
"no-iterator": 2,
// 禁用标签语句
"no-labels": 2,
// 禁用不必要的嵌套块
"no-lone-blocks": 2,
// 禁止在循环中出现 function 声明和表达式
"no-loop-func": 1,
// 禁用魔术数字(3.14什么的用常量代替)
"no-magic-numbers": [1, {
"ignore": [0, -1, 1]
}],
// 禁止使用多个空格
"no-multi-spaces": 2,
// 禁止使用多行字符串,在 JavaScript 中,可以在新行之前使用斜线创建多行字符串
"no-multi-str": 2,
// 禁止对原生对象赋值
"no-native-reassign": 2,
// 禁止在非赋值或条件语句中使用 new 操作符
"no-new": 2,
// 禁止对 Function 对象使用 new 操作符
"no-new-func": 0,
// 禁止对 String,Number 和 Boolean 使用 new 操作符
"no-new-wrappers": 2,
// 禁用八进制字面量
"no-octal": 2,
// 禁止在字符串中使用八进制转义序列
"no-octal-escape": 2,
// 不允许对 function 的参数进行重新赋值
"no-param-reassign": 0,
// 禁用 __proto__ 属性
"no-proto": 2,
// 禁止使用 var 多次声明同一变量
"no-redeclare": 2,
// 禁用指定的通过 require 加载的模块
"no-return-assign": 0,
// 禁止使用 javascript: url
"no-script-url": 0,
// 禁止自我赋值
"no-self-assign": 2,
// 禁止自身比较
"no-self-compare": 2,
// 禁用逗号操作符
"no-sequences": 2,
// 禁止抛出非异常字面量
"no-throw-literal": 2,
// 禁用一成不变的循环条件
"no-unmodified-loop-condition": 2,
// 禁止出现未使用过的表达式
"no-unused-expressions": 0,
// 禁用未使用过的标签
"no-unused-labels": 2,
// 禁止不必要的 .call() 和 .apply()
"no-useless-call": 2,
// 禁止不必要的字符串字面量或模板字面量的连接
"no-useless-concat": 0,
// 禁用不必要的转义字符
"no-useless-escape": 0,
// 禁用 void 操作符
"no-void": 0,
// 禁止在注释中使用特定的警告术语
"no-warning-comments": 0,
// 禁用 with 语句
"no-with": 2,
// 强制在parseInt()使用基数参数
"radix": 2,
// 要求所有的 var 声明出现在它们所在的作用域顶部
"vars-on-top": 0,
// 要求 IIFE 使用括号括起来
"wrap-iife": [2, "any"],
// 要求或禁止 “Yoda” 条件
"yoda": [2, "never"],
// 要求或禁止使用严格模式指令
"strict": 0,
//////////////
// 变量声明 //
//////////////
// 要求或禁止 var 声明中的初始化(初值)
"init-declarations": 0,
// 不允许 catch 子句的参数与外层作用域中的变量同名
"no-catch-shadow": 0,
// 禁止删除变量
"no-delete-var": 2,
// 不允许标签与变量同名
"no-label-var": 2,
// 禁用特定的全局变量
"no-restricted-globals": 0,
// 禁止 var 声明 与外层作用域的变量同名
"no-shadow": 0,
// 禁止覆盖受限制的标识符
"no-shadow-restricted-names": 2,
// 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
"no-undef": 2,
// 禁止将变量初始化为 undefined
"no-undef-init": 2,
// 禁止将 undefined 作为标识符
"no-undefined": 0,
// 禁止出现未使用过的变量
"no-unused-vars": [2, {
"vars": "all",
"args": "none"
}],
// 不允许在变量定义之前使用它们
"no-use-before-define": 0,
//////////////////////////
// Node.js and CommonJS //
//////////////////////////
// require return statements after callbacks
"callback-return": 0,
// 要求 require() 出现在顶层模块作用域中
"global-require": 1,
// 要求回调函数中有容错处理
"handle-callback-err": [2, "^(err|error)$"],
// 禁止混合常规 var 声明和 require 调用
"no-mixed-requires": 0,
// 禁止调用 require 时使用 new 操作符
"no-new-require": 2,
// 禁止对 __dirname 和 __filename进行字符串连接
"no-path-concat": 0,
// 禁用 process.env
"no-process-env": 0,
// 禁用 process.exit()
"no-process-exit": 0,
// 禁用同步方法
"no-sync": 0,
//////////////
// 风格指南 //
//////////////
// 指定数组的元素之间要以空格隔开(, 后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格
"array-bracket-spacing": [2, "never"],
// 禁止或强制在单行代码块中使用空格(禁用)
"block-spacing": [1, "never"],
//强制使用一致的缩进 第二个参数为 "tab" 时,会使用tab,
// if while function 后面的{必须与if在同一行,java风格。
"brace-style": [2, "1tbs", {
"allowSingleLine": true
}],
// 双峰驼命名格式
"camelcase": 2,
// 控制逗号前后的空格
"comma-spacing": [2, {
"before": false,
"after": true
}],
// 控制逗号在行尾出现还是在行首出现 (默认行尾)
// http://eslint.org/docs/rules/comma-style
"comma-style": [2, "last"],
//"SwitchCase" (默认:0) 强制 switch 语句中的 case 子句的缩进水平
// 以方括号取对象属性时,[ 后面和 ] 前面是否需要空格, 可选参数 never, always
"computed-property-spacing": [2, "never"],
// 用于指统一在回调函数中指向this的变量名,箭头函数中的this已经可以指向外层调用者,应该没卵用了
// e.g [0,"that"] 指定只能 var that = this. that不能指向其他任何值,this也不能赋值给that以外的其他值
"consistent-this": [1, "that"],
// 强制使用命名的 function 表达式
"func-names": 0,
// 文件末尾强制换行
"eol-last": 2,
"indent": [2, 2, {
"SwitchCase": 1
}],
// 强制在对象字面量的属性中键和值之间使用一致的间距
"key-spacing": [2, {
"beforeColon": false,
"afterColon": true
}],
// 强制使用一致的换行风格
"linebreak-style": [1, "unix"],
// 要求在注释周围有空行 ( 要求在块级注释之前有一空行)
"lines-around-comment": [1, {
"beforeBlockComment": true
}],
// 强制一致地使用函数声明或函数表达式,方法定义风格,参数:
// declaration: 强制使用方法声明的方式,function f(){} e.g [2, "declaration"]
// expression:强制使用方法表达式的方式,var f = function() {} e.g [2, "expression"]
// allowArrowFunctions: declaration风格中允许箭头函数。 e.g [2, "declaration", { "allowArrowFunctions": true }]
"func-style": 0,
// 强制回调函数最大嵌套深度 5层
"max-nested-callbacks": [1, 5],
// 禁止使用指定的标识符
"id-blacklist": 0,
// 强制标识符的最新和最大长度
"id-length": 0,
// 要求标识符匹配一个指定的正则表达式
"id-match": 0,
// 强制在 JSX 属性中一致地使用双引号或单引号
"jsx-quotes": 0,
// 强制在关键字前后使用一致的空格 (前后腰需要)
"keyword-spacing": 2,
// 强制一行的最大长度
"max-len": [1, 200],
// 强制最大行数
"max-lines": 0,
// 强制 function 定义中最多允许的参数数量
"max-params": [1, 7],
// 强制 function 块最多允许的的语句数量
"max-statements": [1, 200],
// 强制每一行中所允许的最大语句数量
"max-statements-per-line": 0,
// 要求构造函数首字母大写 (要求调用 new 操作符时有首字母大小的函数,允许调用首字母大写的函数时没有 new 操作符。)
"new-cap": [2, {
"newIsCap": true,
"capIsNew": false
}],
// 要求调用无参构造函数时有圆括号
"new-parens": 2,
// 要求或禁止 var 声明语句后有一行空行
"newline-after-var": 0,
// 禁止使用 Array 构造函数
"no-array-constructor": 2,
// 禁用按位运算符
"no-bitwise": 0,
// 要求 return 语句之前有一空行
"newline-before-return": 0,
// 要求方法链中每个调用都有一个换行符
"newline-per-chained-call": 1,
// 禁用 continue 语句
"no-continue": 0,
// 禁止在代码行后使用内联注释
"no-inline-comments": 0,
// 禁止 if 作为唯一的语句出现在 else 语句中
"no-lonely-if": 0,
// 禁止混合使用不同的操作符
"no-mixed-operators": 0,
// 不允许空格和 tab 混合缩进
"no-mixed-spaces-and-tabs": 2,
// 不允许多个空行
"no-multiple-empty-lines": [2, {
"max": 2
}],
// 不允许否定的表达式
"no-negated-condition": 0,
// 不允许使用嵌套的三元表达式
"no-nested-ternary": 0,
// 禁止使用 Object 的构造函数
"no-new-object": 2,
// 禁止使用一元操作符 ++ 和 --
"no-plusplus": 0,
// 禁止使用特定的语法
"no-restricted-syntax": 0,
// 禁止 function 标识符和括号之间出现空格
"no-spaced-func": 2,
// 不允许使用三元操作符
"no-ternary": 0,
// 禁用行尾空格
"no-trailing-spaces": 2,
// 禁止标识符中有悬空下划线_bar
"no-underscore-dangle": 0,
// 禁止可以在有更简单的可替代的表达式时使用三元操作符
"no-unneeded-ternary": 2,
// 禁止属性前有空白
"no-whitespace-before-property": 0,
// 强制花括号内换行符的一致性
"object-curly-newline": 0,
// 强制在花括号中使用一致的空格
"object-curly-spacing": 0,
// 强制将对象的属性放在不同的行上
"object-property-newline": 0,
// 强制函数中的变量要么一起声明要么分开声明
"one-var": [2, {
"initialized": "never"
}],
// 要求或禁止在 var 声明周围换行
"one-var-declaration-per-line": 0,
// 要求或禁止在可能的情况下要求使用简化的赋值操作符
"operator-assignment": 0,
// 强制操作符使用一致的换行符
"operator-linebreak": [2, "after", {
"overrides": {
"?": "before",
":": "before"
}
}],
// 要求或禁止块内填充
"padded-blocks": 0,
// 要求对象字面量属性名称用引号括起来
"quote-props": 0,
// 强制使用一致的反勾号、双引号或单引号
// "quotes": [2, "single", "avoid-escape"],
// 要求使用 JSDoc 注释
"require-jsdoc": 0,
// 要求或禁止使用分号而不是 ASI(这个才是控制行尾部分号的,)
"semi": [0, "always"],
// 强制分号之前和之后使用一致的空格
"semi-spacing": 0,
// 要求同一个声明块中的变量按顺序排列
"sort-vars": 0,
// 强制在块之前使用一致的空格
"space-before-blocks": [2, "always"],
// 强制在 function的左括号之前使用一致的空格
"space-before-function-paren": [0, "always"],
// 强制在圆括号内使用一致的空格
"space-in-parens": [2, "never"],
// 要求操作符周围有空格
"space-infix-ops": 2,
// 强制在一元操作符前后使用一致的空格
"space-unary-ops": [2, {
"words": true,
"nonwords": false
}],
// 强制在注释中 // 或 /* 使用一致的空格
"spaced-comment": [2, "always", {
"markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"]
}],
// 要求或禁止 Unicode BOM
"unicode-bom": 0,
// 要求正则表达式被括号括起来
"wrap-regex": 0,
//////////////
// ES6.相关 //
//////////////
// 要求箭头函数体使用大括号
"arrow-body-style": 2,
// 要求箭头函数的参数使用圆括号
"arrow-parens": 0,
"arrow-spacing": [2, {
"before": true,
"after": true
}],
// 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示
"constructor-super": 0,
// 强制 generator 函数中 * 号周围使用一致的空格
"generator-star-spacing": [2, {
"before": true,
"after": true
}],
// 禁止修改类声明的变量
"no-class-assign": 2,
// 不允许箭头功能,在那里他们可以混淆的比较
"no-confusing-arrow": 0,
// 禁止修改 const 声明的变量
"no-const-assign": 2,
// 禁止类成员中出现重复的名称
"no-dupe-class-members": 2,
// 不允许复制模块的进口
"no-duplicate-imports": 0,
// 禁止 Symbol 的构造函数
"no-new-symbol": 2,
// 允许指定模块加载时的进口
"no-restricted-imports": 0,
// 禁止在构造函数中,在调用 super() 之前使用 this 或 super
"no-this-before-super": 2,
// 禁止不必要的计算性能键对象的文字
"no-useless-computed-key": 0,
// 要求使用 let 或 const 而不是 var
"no-var": 0,
// 要求或禁止对象字面量中方法和属性使用简写语法
"object-shorthand": 0,
// 要求使用箭头函数作为回调
"prefer-arrow-callback": 0,
// 要求使用 const 声明那些声明后不再被修改的变量
"prefer-const": 0,
// 要求在合适的地方使用 Reflect 方法
"prefer-reflect": 0,
// 要求使用扩展运算符而非 .apply()
"prefer-spread": 0,
// 要求使用模板字面量而非字符串连接
"prefer-template": 0,
// Suggest using the rest parameters instead of arguments
"prefer-rest-params": 0,
// 要求generator 函数内有 yield
"require-yield": 0,
// enforce spacing between rest and spread operators and their expressions
"rest-spread-spacing": 0,
// 强制模块内的 import 排序
"sort-imports": 0,
// 要求或禁止模板字符串中的嵌入表达式周围空格的使用
"template-curly-spacing": 1,
// 强制在 yield* 表达式中 * 周围使用空格
"yield-star-spacing": 2
}
}
# Editor directories and files
.DS_Store
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
.vscode
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# ///////////////////////////
#### mvvm协议标准中处理cml文件style部分与样式文件
\ No newline at end of file
const lessCompile = require('./lib/lessCompile');
const mediaCompile = require('./lib/mediaCompile');
const standardCompile = require('./lib/standardCompile');
const stylusCompile = require('./lib/stylusCompile');
exports.lessCompile = lessCompile;
exports.mediaCompile = mediaCompile;
exports.standardCompile = standardCompile;
exports.stylusCompile = stylusCompile;
const postcss = require('postcss');
module.exports = function({source, filePath, compiler}) {
let deps = [];
const assetsPlugin = postcss.plugin('postcss-assets-plugin', function(options) {
return (root, result) => {
root.walkDecls((decl, i) => {
if (~decl.value.indexOf('url')) {
decl.value = decl.value.replace(/url\s*\(\s*[\'\"]?(.+?)[\'\"]?\s*\)/g, function(all, $1) {
let realDependPath = compiler.resolve(filePath, $1);
deps.push(realDependPath);
let publicPath = compiler.getPublicPath(realDependPath);
return publicPath;
})
}
})
}
})
return {
source: postcss([assetsPlugin]).process(source).css,
deps
}
}
const less = require('less');
module.exports = function({source, filePath}) {
// todo 给less options 添加plugin addFileManager 参见less-loader createWebpackLessPlugin.js
return less.render(source, {
compress: false,
filename: filePath,
relativeUrls: true,
sourceMap: false
})
}
module.exports = function(source = '', cmlType) {
let reg = /@media\s*cml-type\s*\(([\w\s,]*)\)\s*/g;
if (!reg.test(source)) {
return source;
}
reg.lastIndex = 0;
while (true) { // eslint-disable-line
let result = reg.exec(source);
if (!result) {break;}
let cmlTypes = result[1] || '';
cmlTypes = cmlTypes.split(',').map(item => item.trim());
let isSave = ~cmlTypes.indexOf(cmlType);
let startIndex = result.index; // @media的开始
let currentIndex = source.indexOf('{', startIndex); // 从第一个@media开始
let signStartIndex = currentIndex; // 第一个{的位置
if (currentIndex == -1) {
throw new Error("@media cml-type format err");
}
let signStack = [];
signStack.push(0);
while (signStack.length > 0) {
let index1 = source.indexOf('{', currentIndex + 1);
let index2 = source.indexOf('}', currentIndex + 1);
let index;
// 都有的话 index为最前面的
if (index1 !== -1 && index2 !== -1) {
index = Math.min(index1, index2);
} else {
index = Math.max(index1, index2);
}
if (index === -1) {
throw new Error("@media cml-type format err");
}
let sign = source[index];
currentIndex = index;
if (sign === '{') {
signStack.push(signStack.length);
} else if (sign === '}') {
signStack.pop();
}
}
// 操作source
if (isSave) { // 保存的@media
var sourceArray = Array.from(source);
sourceArray.splice(startIndex, currentIndex - startIndex + 1, source.slice(signStartIndex + 1, currentIndex));
source = sourceArray.join('');
} else { // 删除的
source = source.slice(0, startIndex) + source.slice(currentIndex + 1);
}
reg.lastIndex = 0;
}
return source;
}
const mediaCompile = require('./mediaCompile.js');
const lessCompile = require('./lessCompile.js');
const stylusCompile = require('./stylusCompile.js');
const assetsCompile = require('./assetsCompile.js');
module.exports = async function({source, filePath, cmlType, lang = 'less', compiler}) {
let imports = [];
source = mediaCompile(source, cmlType);
if (lang === 'less') {
let lessResult = await lessCompile({source, filePath});
source = lessResult.css;
imports = lessResult.imports;
}
if (lang === 'stylus' || lang === 'styl') {
let stylusResult = await stylusCompile({source, filePath});
source = stylusResult.css;
imports = stylusResult.imports;
}
if (compiler) {
let {source: newSource, deps} = assetsCompile({source, filePath, compiler})
source = newSource;
imports = imports.concat(deps);
}
return {
output: source,
imports // 返回依赖文件的绝对路径
};
}
const stylus = require('stylus');
const path = require('path');
module.exports = function({source, filePath}) {
// todo 给less options 添加plugin addFileManager 参见less-loader createWebpackLessPlugin.js
return new Promise(function(resolve, reject) {
let styl = stylus(output);
styl.set('filename', filePath);
styl.set('paths', [path.dirname(filePath)]);
let imports = styl.deps();
stylus.render(function(err, css) {
if (err) {
reject(err);
}
resolve({
imports,
css
});
})
})
}
{
"name": "mvvm-style-parser",
"version": "0.3.0-alpha.2",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"chameleon-tool-utils": "0.3.0-alpha.2",
"less": "3.9.0",
"postcss": "^7.0.14",
"stylus": "0.54.5"
}
}
\ No newline at end of file
let assetsCompile = require('../lib/assetsCompile.js');
const source = `
.class1 {
background: url(./images/1.png?__inline) no-repeat;
}
@font-face{
font-family: 'YaHei Consolas Hybrid';
src : url('./fonts/test.ttf');
}
`
const mvvmpack = require('../../mvvm-pack/index.js');
const path = require('path');
let compiler = new mvvmpack({
config: {
check: {
enable: true, // 是否开启接口校验
enableTypes: [] // 接口校验支持的类型 可以开启["Object","Array","Nullable"]
},
output: {
publicPath: 'http://static.cml.com/static/'
}
},
logLevel: 3,
cmlType: 'web',
media: 'dev',
cmlRoot: path.resolve('./'),
projectRoot: path.resolve(__dirname, './')
})
let result = assetsCompile({source, filePath: path.join(__dirname, './assetsCompile.js'), compiler});
console.log(result)
@import './2.styl';
\ No newline at end of file
body
font: 12px Helvetica, Arial, sans-serif
a.button
-webkit-border-radius: 5px
-moz-border-radius: 5px
border-radius: 5px
\ No newline at end of file
var path = require('path');
var fs = require('fs');
var stylus = require('stylus')
let source = fs.readFileSync(path.join(__dirname, './1.styl'), {encoding: 'utf8'});
let filename = path.join(__dirname, './1.styl');
let demo = stylus(source)
demo.set('filename', filename)
demo.set('paths', [path.dirname(filename)]);
let deps = demo.deps();
debugger
console.log(deps)
demo.render(function(err, css) {
console.log(css)
})
let lessCompile = require('../../lib/lessCompile');
var path = require('path');
var fs = require('fs');
let filePath = path.join(__dirname, './less1.less')
let source = fs.readFileSync(filePath, {encoding: 'utf8'});
debugger
lessCompile({
source,
filePath
}).then(res => {
console.log(res)
})
@import './less2.less';
\ No newline at end of file
.name {
font-size: 2px;
}
\ No newline at end of file
let standard = require('../lib/standardCompile.js');
const source = `
.class1 {
background: url(./images/1.png) no-repeat;
}
@font-face{
font-family: 'YaHei Consolas Hybrid';
src : url('./fonts/test.ttf');
}
`
const mvvmpack = require('../../mvvm-pack/index.js');
const path = require('path');
let compiler = new mvvmpack({
config: {
check: {
enable: true, // 是否开启接口校验
enableTypes: [] // 接口校验支持的类型 可以开启["Object","Array","Nullable"]
},
output: {
publicPath: 'http://static.cml.com/static/'
}
},
logLevel: 3,
cmlType: 'web',
media: 'dev',
cmlRoot: path.resolve('./'),
projectRoot: path.resolve(__dirname, './')
})
let result = standard({ cmlType: 'web', lang: 'less', source, filePath: path.join(__dirname, './assetsCompile.js'), compiler});
console.log(result.output)
console.log(result.imports)
{
// 在配置文件里配置全局变量时,使用 globals 指出你要使用的全局变量。将变量设置为 true 将允许变量被重写,或 false 将不允许被重写
"globals": {
"cml": false
},
// 环境定义了预定义的全局变量。
"env": {
//环境定义了预定义的全局变量。更多在官网查看
"browser": true,
"node": true,
"commonjs": true,
"amd": true,
"es6": true,
"mocha": true
},
// JavaScript 语言选项
"parserOptions": {
// ECMAScript 版本
"ecmaVersion": 9,
"sourceType": "module", //设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)。
//想使用的额外的语言特性:
"ecmaFeatures": {
// 允许在全局作用域下使用 return 语句
"globalReturn": true,
// impliedStric
"impliedStrict": true,
// 启用 JSX
"jsx": true,
"modules": true
}
},
//-----让eslint支持 JSX start
"plugins": [
],
"extends": [
"eslint:recommended"
],
//-----让eslint支持 JSX end
/**
* "off" 或 0 - 关闭规则
* "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出),
* "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
*/
"rules": {
////////////////
// 可能的错误 //
////////////////
// 禁止条件表达式中出现赋值操作符
"no-cond-assign": 2,
// 禁用 console
"no-console": 0,
// 禁止在条件中使用常量表达式
// if (false) {
// doSomethingUnfinished();
// } //cuowu
"no-constant-condition": 2,
// 禁止在正则表达式中使用控制字符 :new RegExp("\x1f")
"no-control-regex": 2,
// 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,
// always-multiline:多行模式必须带逗号,单行模式不能带逗号
"comma-dangle": [1, "never"],
// 禁用 debugger
"no-debugger": 2,
// 禁止 function 定义中出现重名参数
"no-dupe-args": 2,
// 禁止对象字面量中出现重复的 key
"no-dupe-keys": 2,
// 禁止重复的 case 标签
"no-duplicate-case": 2,
// 禁止空语句块
"no-empty": 2,
// 禁止在正则表达式中使用空字符集 (/^abc[]/)
"no-empty-character-class": 2,
// 禁止对 catch 子句的参数重新赋值
"no-ex-assign": 2,
// 禁止不必要的布尔转换
"no-extra-boolean-cast": 2,
// 禁止不必要的括号 //(a * b) + c;//报错
"no-extra-parens": 0,
// 禁止不必要的分号
"no-extra-semi": 2,
// 禁止对 function 声明重新赋值
"no-func-assign": 2,
// 禁止在嵌套的块中出现 function 或 var 声明
"no-inner-declarations": [2, "functions"],
// 禁止 RegExp 构造函数中无效的正则表达式字符串
"no-invalid-regexp": 2,
// 禁止在字符串和注释之外不规则的空白
"no-irregular-whitespace": 2,
// 禁止在 in 表达式中出现否定的左操作数
"no-negated-in-lhs": 2,
// 禁止把全局对象 (Math 和 JSON) 作为函数调用 错误:var math = Math();
"no-obj-calls": 2,
// 禁止直接使用 Object.prototypes 的内置属性
"no-prototype-builtins": 0,
// 禁止正则表达式字面量中出现多个空格
"no-regex-spaces": 2,
// 禁用稀疏数组
"no-sparse-arrays": 2,
// 禁止出现令人困惑的多行表达式
"no-unexpected-multiline": 2,
// 禁止在return、throw、continue 和 break语句之后出现不可达代码
"no-unreachable": 2,
// 要求使用 isNaN() 检查 NaN
"use-isnan": 2,
// 强制使用有效的 JSDoc 注释
"valid-jsdoc": 0,
// 强制 typeof 表达式与有效的字符串进行比较
// typeof foo === "undefimed" 错误
"valid-typeof": 2,
//////////////
// 最佳实践 //
//////////////
// 定义对象的set存取器属性时,强制定义get
"accessor-pairs": 2,
// 强制数组方法的回调函数中有 return 语句
"array-callback-return": 0,
// 强制把变量的使用限制在其定义的作用域范围内
"block-scoped-var": 0,
// 限制圈复杂度,也就是类似if else能连续接多少个
"complexity": [2, 20],
// 要求 return 语句要么总是指定返回的值,要么不指定
"consistent-return": 0,
// 强制所有控制语句使用一致的括号风格
"curly": [2, "all"],
// switch 语句强制 default 分支,也可添加 // no default 注释取消此次警告
"default-case": 2,
// 强制object.key 中 . 的位置,参数:
// property,'.'号应与属性在同一行
// object, '.' 号应与对象名在同一行
"dot-location": [2, "property"],
// 强制使用.号取属性
// 参数: allowKeywords:true 使用保留字做属性名时,只能使用.方式取属性
// false 使用保留字做属性名时, 只能使用[]方式取属性 e.g [2, {"allowKeywords": false}]
// allowPattern: 当属性名匹配提供的正则表达式时,允许使用[]方式取值,否则只能用.号取值 e.g [2, {"allowPattern": "^[a-z]+(_[a-z]+)+$"}]
"dot-notation": [2, {
"allowKeywords": false
}],
// 使用 === 替代 == allow-null允许null和undefined==
"eqeqeq": [0, "allow-null"],
// 要求 for-in 循环中有一个 if 语句
"guard-for-in": 2,
// 禁用 alert、confirm 和 prompt
"no-alert": 0,
// 禁用 arguments.caller 或 arguments.callee
"no-caller": 2,
// 不允许在 case 子句中使用词法声明
"no-case-declarations": 2,
// 禁止除法操作符显式的出现在正则表达式开始的位置
"no-div-regex": 2,
// 禁止 if 语句中有 return 之后有 else
"no-else-return": 0,
// 禁止出现空函数.如果一个函数包含了一条注释,它将不会被认为有问题。
"no-empty-function": 2,
// 禁止使用空解构模式no-empty-pattern
"no-empty-pattern": 2,
// 禁止在没有类型检查操作符的情况下与 null 进行比较
"no-eq-null": 1,
// 禁用 eval()
"no-eval": 2,
// 禁止扩展原生类型
"no-extend-native": 2,
// 禁止不必要的 .bind() 调用
"no-extra-bind": 2,
// 禁用不必要的标签
"no-extra-label:": 0,
// 禁止 case 语句落空
"no-fallthrough": 2,
// 禁止数字字面量中使用前导和末尾小数点
"no-floating-decimal": 2,
// 禁止使用短符号进行类型转换(!!fOO)
"no-implicit-coercion": 0,
// 禁止在全局范围内使用 var 和命名的 function 声明
"no-implicit-globals": 1,
// 禁止使用类似 eval() 的方法
"no-implied-eval": 2,
// 禁止 this 关键字出现在类和类对象之外
"no-invalid-this": 0,
// 禁用 __iterator__ 属性
"no-iterator": 2,
// 禁用标签语句
"no-labels": 2,
// 禁用不必要的嵌套块
"no-lone-blocks": 2,
// 禁止在循环中出现 function 声明和表达式
"no-loop-func": 1,
// 禁用魔术数字(3.14什么的用常量代替)
"no-magic-numbers": [1, {
"ignore": [0, -1, 1]
}],
// 禁止使用多个空格
"no-multi-spaces": 2,
// 禁止使用多行字符串,在 JavaScript 中,可以在新行之前使用斜线创建多行字符串
"no-multi-str": 2,
// 禁止对原生对象赋值
"no-native-reassign": 2,
// 禁止在非赋值或条件语句中使用 new 操作符
"no-new": 2,
// 禁止对 Function 对象使用 new 操作符
"no-new-func": 0,
// 禁止对 String,Number 和 Boolean 使用 new 操作符
"no-new-wrappers": 2,
// 禁用八进制字面量
"no-octal": 2,
// 禁止在字符串中使用八进制转义序列
"no-octal-escape": 2,
// 不允许对 function 的参数进行重新赋值
"no-param-reassign": 0,
// 禁用 __proto__ 属性
"no-proto": 2,
// 禁止使用 var 多次声明同一变量
"no-redeclare": 2,
// 禁用指定的通过 require 加载的模块
"no-return-assign": 0,
// 禁止使用 javascript: url
"no-script-url": 0,
// 禁止自我赋值
"no-self-assign": 2,
// 禁止自身比较
"no-self-compare": 2,
// 禁用逗号操作符
"no-sequences": 2,
// 禁止抛出非异常字面量
"no-throw-literal": 2,
// 禁用一成不变的循环条件
"no-unmodified-loop-condition": 2,
// 禁止出现未使用过的表达式
"no-unused-expressions": 0,
// 禁用未使用过的标签
"no-unused-labels": 2,
// 禁止不必要的 .call() 和 .apply()
"no-useless-call": 2,
// 禁止不必要的字符串字面量或模板字面量的连接
"no-useless-concat": 0,
// 禁用不必要的转义字符
"no-useless-escape": 0,
// 禁用 void 操作符
"no-void": 0,
// 禁止在注释中使用特定的警告术语
"no-warning-comments": 0,
// 禁用 with 语句
"no-with": 2,
// 强制在parseInt()使用基数参数
"radix": 2,
// 要求所有的 var 声明出现在它们所在的作用域顶部
"vars-on-top": 0,
// 要求 IIFE 使用括号括起来
"wrap-iife": [2, "any"],
// 要求或禁止 “Yoda” 条件
"yoda": [2, "never"],
// 要求或禁止使用严格模式指令
"strict": 0,
//////////////
// 变量声明 //
//////////////
// 要求或禁止 var 声明中的初始化(初值)
"init-declarations": 0,
// 不允许 catch 子句的参数与外层作用域中的变量同名
"no-catch-shadow": 0,
// 禁止删除变量
"no-delete-var": 2,
// 不允许标签与变量同名
"no-label-var": 2,
// 禁用特定的全局变量
"no-restricted-globals": 0,
// 禁止 var 声明 与外层作用域的变量同名
"no-shadow": 0,
// 禁止覆盖受限制的标识符
"no-shadow-restricted-names": 2,
// 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
"no-undef": 2,
// 禁止将变量初始化为 undefined
"no-undef-init": 2,
// 禁止将 undefined 作为标识符
"no-undefined": 0,
// 禁止出现未使用过的变量
"no-unused-vars": [2, {
"vars": "all",
"args": "none"
}],
// 不允许在变量定义之前使用它们
"no-use-before-define": 0,
//////////////////////////
// Node.js and CommonJS //
//////////////////////////
// require return statements after callbacks
"callback-return": 0,
// 要求 require() 出现在顶层模块作用域中
"global-require": 1,
// 要求回调函数中有容错处理
"handle-callback-err": [2, "^(err|error)$"],
// 禁止混合常规 var 声明和 require 调用
"no-mixed-requires": 0,
// 禁止调用 require 时使用 new 操作符
"no-new-require": 2,
// 禁止对 __dirname 和 __filename进行字符串连接
"no-path-concat": 0,
// 禁用 process.env
"no-process-env": 0,
// 禁用 process.exit()
"no-process-exit": 0,
// 禁用同步方法
"no-sync": 0,
//////////////
// 风格指南 //
//////////////
// 指定数组的元素之间要以空格隔开(, 后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格
"array-bracket-spacing": [2, "never"],
// 禁止或强制在单行代码块中使用空格(禁用)
"block-spacing": [1, "never"],
//强制使用一致的缩进 第二个参数为 "tab" 时,会使用tab,
// if while function 后面的{必须与if在同一行,java风格。
"brace-style": [2, "1tbs", {
"allowSingleLine": true
}],
// 双峰驼命名格式
"camelcase": 2,
// 控制逗号前后的空格
"comma-spacing": [2, {
"before": false,
"after": true
}],
// 控制逗号在行尾出现还是在行首出现 (默认行尾)
// http://eslint.org/docs/rules/comma-style
"comma-style": [2, "last"],
//"SwitchCase" (默认:0) 强制 switch 语句中的 case 子句的缩进水平
// 以方括号取对象属性时,[ 后面和 ] 前面是否需要空格, 可选参数 never, always
"computed-property-spacing": [2, "never"],
// 用于指统一在回调函数中指向this的变量名,箭头函数中的this已经可以指向外层调用者,应该没卵用了
// e.g [0,"that"] 指定只能 var that = this. that不能指向其他任何值,this也不能赋值给that以外的其他值
"consistent-this": [1, "that"],
// 强制使用命名的 function 表达式
"func-names": 0,
// 文件末尾强制换行
"eol-last": 2,
"indent": [2, 2, {
"SwitchCase": 1
}],
// 强制在对象字面量的属性中键和值之间使用一致的间距
"key-spacing": [2, {
"beforeColon": false,
"afterColon": true
}],
// 强制使用一致的换行风格
"linebreak-style": [1, "unix"],
// 要求在注释周围有空行 ( 要求在块级注释之前有一空行)
"lines-around-comment": [1, {
"beforeBlockComment": true
}],
// 强制一致地使用函数声明或函数表达式,方法定义风格,参数:
// declaration: 强制使用方法声明的方式,function f(){} e.g [2, "declaration"]
// expression:强制使用方法表达式的方式,var f = function() {} e.g [2, "expression"]
// allowArrowFunctions: declaration风格中允许箭头函数。 e.g [2, "declaration", { "allowArrowFunctions": true }]
"func-style": 0,
// 强制回调函数最大嵌套深度 5层
"max-nested-callbacks": [1, 5],
// 禁止使用指定的标识符
"id-blacklist": 0,
// 强制标识符的最新和最大长度
"id-length": 0,
// 要求标识符匹配一个指定的正则表达式
"id-match": 0,
// 强制在 JSX 属性中一致地使用双引号或单引号
"jsx-quotes": 0,
// 强制在关键字前后使用一致的空格 (前后腰需要)
"keyword-spacing": 2,
// 强制一行的最大长度
"max-len": [1, 200],
// 强制最大行数
"max-lines": 0,
// 强制 function 定义中最多允许的参数数量
"max-params": [1, 7],
// 强制 function 块最多允许的的语句数量
"max-statements": [1, 200],
// 强制每一行中所允许的最大语句数量
"max-statements-per-line": 0,
// 要求构造函数首字母大写 (要求调用 new 操作符时有首字母大小的函数,允许调用首字母大写的函数时没有 new 操作符。)
"new-cap": [2, {
"newIsCap": true,
"capIsNew": false
}],
// 要求调用无参构造函数时有圆括号
"new-parens": 2,
// 要求或禁止 var 声明语句后有一行空行
"newline-after-var": 0,
// 禁止使用 Array 构造函数
"no-array-constructor": 2,
// 禁用按位运算符
"no-bitwise": 0,
// 要求 return 语句之前有一空行
"newline-before-return": 0,
// 要求方法链中每个调用都有一个换行符
"newline-per-chained-call": 1,
// 禁用 continue 语句
"no-continue": 0,
// 禁止在代码行后使用内联注释
"no-inline-comments": 0,
// 禁止 if 作为唯一的语句出现在 else 语句中
"no-lonely-if": 0,
// 禁止混合使用不同的操作符
"no-mixed-operators": 0,
// 不允许空格和 tab 混合缩进
"no-mixed-spaces-and-tabs": 2,
// 不允许多个空行
"no-multiple-empty-lines": [2, {
"max": 2
}],
// 不允许否定的表达式
"no-negated-condition": 0,
// 不允许使用嵌套的三元表达式
"no-nested-ternary": 0,
// 禁止使用 Object 的构造函数
"no-new-object": 2,
// 禁止使用一元操作符 ++ 和 --
"no-plusplus": 0,
// 禁止使用特定的语法
"no-restricted-syntax": 0,
// 禁止 function 标识符和括号之间出现空格
"no-spaced-func": 2,
// 不允许使用三元操作符
"no-ternary": 0,
// 禁用行尾空格
"no-trailing-spaces": 2,
// 禁止标识符中有悬空下划线_bar
"no-underscore-dangle": 0,
// 禁止可以在有更简单的可替代的表达式时使用三元操作符
"no-unneeded-ternary": 2,
// 禁止属性前有空白
"no-whitespace-before-property": 0,
// 强制花括号内换行符的一致性
"object-curly-newline": 0,
// 强制在花括号中使用一致的空格
"object-curly-spacing": 0,
// 强制将对象的属性放在不同的行上
"object-property-newline": 0,
// 强制函数中的变量要么一起声明要么分开声明
"one-var": [2, {
"initialized": "never"
}],
// 要求或禁止在 var 声明周围换行
"one-var-declaration-per-line": 0,
// 要求或禁止在可能的情况下要求使用简化的赋值操作符
"operator-assignment": 0,
// 强制操作符使用一致的换行符
"operator-linebreak": [2, "after", {
"overrides": {
"?": "before",
":": "before"
}
}],
// 要求或禁止块内填充
"padded-blocks": 0,
// 要求对象字面量属性名称用引号括起来
"quote-props": 0,
// 强制使用一致的反勾号、双引号或单引号
// "quotes": [2, "single", "avoid-escape"],
// 要求使用 JSDoc 注释
"require-jsdoc": 0,
// 要求或禁止使用分号而不是 ASI(这个才是控制行尾部分号的,)
"semi": [0, "always"],
// 强制分号之前和之后使用一致的空格
"semi-spacing": 0,
// 要求同一个声明块中的变量按顺序排列
"sort-vars": 0,
// 强制在块之前使用一致的空格
"space-before-blocks": [2, "always"],
// 强制在 function的左括号之前使用一致的空格
"space-before-function-paren": [0, "always"],
// 强制在圆括号内使用一致的空格
"space-in-parens": [2, "never"],
// 要求操作符周围有空格
"space-infix-ops": 2,
// 强制在一元操作符前后使用一致的空格
"space-unary-ops": [2, {
"words": true,
"nonwords": false
}],
// 强制在注释中 // 或 /* 使用一致的空格
"spaced-comment": [2, "always", {
"markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"]
}],
// 要求或禁止 Unicode BOM
"unicode-bom": 0,
// 要求正则表达式被括号括起来
"wrap-regex": 0,
//////////////
// ES6.相关 //
//////////////
// 要求箭头函数体使用大括号
"arrow-body-style": 2,
// 要求箭头函数的参数使用圆括号
"arrow-parens": 0,
"arrow-spacing": [2, {
"before": true,
"after": true
}],
// 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示
"constructor-super": 0,
// 强制 generator 函数中 * 号周围使用一致的空格
"generator-star-spacing": [2, {
"before": true,
"after": true
}],
// 禁止修改类声明的变量
"no-class-assign": 2,
// 不允许箭头功能,在那里他们可以混淆的比较
"no-confusing-arrow": 0,
// 禁止修改 const 声明的变量
"no-const-assign": 2,
// 禁止类成员中出现重复的名称
"no-dupe-class-members": 2,
// 不允许复制模块的进口
"no-duplicate-imports": 0,
// 禁止 Symbol 的构造函数
"no-new-symbol": 2,
// 允许指定模块加载时的进口
"no-restricted-imports": 0,
// 禁止在构造函数中,在调用 super() 之前使用 this 或 super
"no-this-before-super": 2,
// 禁止不必要的计算性能键对象的文字
"no-useless-computed-key": 0,
// 要求使用 let 或 const 而不是 var
"no-var": 0,
// 要求或禁止对象字面量中方法和属性使用简写语法
"object-shorthand": 0,
// 要求使用箭头函数作为回调
"prefer-arrow-callback": 0,
// 要求使用 const 声明那些声明后不再被修改的变量
"prefer-const": 0,
// 要求在合适的地方使用 Reflect 方法
"prefer-reflect": 0,
// 要求使用扩展运算符而非 .apply()
"prefer-spread": 0,
// 要求使用模板字面量而非字符串连接
"prefer-template": 0,
// Suggest using the rest parameters instead of arguments
"prefer-rest-params": 0,
// 要求generator 函数内有 yield
"require-yield": 0,
// enforce spacing between rest and spread operators and their expressions
"rest-spread-spacing": 0,
// 强制模块内的 import 排序
"sort-imports": 0,
// 要求或禁止模板字符串中的嵌入表达式周围空格的使用
"template-curly-spacing": 1,
// 强制在 yield* 表达式中 * 周围使用空格
"yield-star-spacing": 2
}
}
module.exports = require('./lib/MVVMPack.js');
const fs = require('fs');
class CMLNode {
constructor(options = {}) {
this.ext;
this.realPath; // 文件物理地址
this.nodeType; // App/Page/Component/Module // 节点类型 CML文件分为App/Page/Component 其他的为Module CML文件中的每一个部分也是一个Node节点
this.moduleType; // template/style/script/json/asset CML为CML文件
this.dependencies = []; // 该节点的直接依赖编译及诶点 app.cml依赖pages.cml pages.cml依赖components.cml js依赖js cmss依赖cmss
this.devDependencies = []; // 该节点的编译依赖的文件 该文件改动会触发重新编译 但是这个文件本身是不需要单独编译
this.childrens = []; // 子模块 CML才有子模块
this.parent; // 父模块 CML文件中的子模块才有
this.source; // 模块源代码
this.convert; // AST JSON
this.output; // 模块输出 各种过程操作该字段
this.attrs; // template/style/script/json模块上的属性
this.compiled; // 是否经过编译
this.extra; // 用户可以额外添加的信息
this.mtime; // 文件修改时间
this.identifier; // 节点唯一标识 由 nodeType moduleType realPath组成
this.modId; // script 与asset模块的id 用于amd包装
Object.keys(options).forEach(key => {
this[key] = options[key];
})
}
// 文件的修改时间map todo
notChange(fileTimestamps) {
let depNodes = this.getDependenciesNode();
let result = depNodes.every(node => {
let result = fs.statSync(node.realPath.split('?')[0]).mtime.getTime() === node.mtime;
return result;
})
return result;
}
getDependenciesNode(depList = []) {
if (!~depList.indexOf(this)) {
depList.push(this);
let newDepList = [];
newDepList = newDepList.concat(this.dependencies, this.devDependencies, this.childrens);
newDepList = [...new Set(newDepList)];
newDepList.forEach(item => {
item.getDependenciesNode(depList);
})
}
return depList;
}
getDependenciesFilePaths() {
let depNodes = this.getDependenciesNode();
let result = depNodes.map(node => {
return node.realPath.split('?')[0];
})
return result;
}
}
module.exports = CMLNode;
const Event = require('./Event');
const ResolveFactory = require('./ResolveFactory');
const NodeEnvironmentPlugin = require('./FileSystem/NodeEnvironmentPlugin.js');
const CMLNode = require('./CMLNode.js');
const path = require('path');
const cmlUtils = require('chameleon-tool-utils');
const CMLParser = require('mvvm-template-parser');
const CMSSParser = require('mvvm-style-parser');
const JSParser = require('mvvm-script-parser');
const fs = require('fs');
const Watching = require('./Watching');
const Log = require('./Log');
const {AMDWrapper} = require('./Mod/index.js');
const mime = require('mime');
class Compile {
constructor(options) {
this.options = options; // cmlType, media, projectRoot, cmlRoot, config
this.graphNodeMap = {}; // 创建graph的时候就要注意 同一个文件只能创建一个node 所以要记录有了哪些node key 为filePath + moduleType value为Node对象
this.projectGraph; // 编译图
this.oneLoopCompiledNode = []; // 一次编译过程编译到的节点,利用这个队列去触发用户的编译,实现了用户编译的缓存。
this.event = new Event();
this._resolve = ResolveFactory(options);
this.fileDependencies = new Set(); // 整个编译过程依赖的文件 编译完成后watch需要
new NodeEnvironmentPlugin().apply(this); // 文件系统
this.stringExt = /\.(cml|interface|js|json|css|less|sass|scss|stylus|styl)(\?.*)?$/;// 转成utf-8编码的文件后缀
this.nodeType = {
App: 'App',
Page: 'Page',
Component: 'Component',
Module: 'Module'
}
this.moduleType = {
template: "template",
style: "style",
script: "script",
json: "json",
asset: "asset",
other: "other"
}
this.compileQueue = []; // 待编译节点列表
this.log = new Log({
level: options.logLevel || 2
})
this.assetsPath = 'static/assets/${filename}_${hash}.${ext}'; // 资源的发布路径 配合publicPath
this.moduleRule = [ // 文件后缀对应module信息
{
test: /\.css|\.less$/,
moduleType: this.moduleType.style,
attrs: {
lang: 'less'
}
},
{
test: /\.stylus|\.styls$/,
moduleType: this.moduleType.style,
attrs: {
lang: 'stylus'
}
},
{
test: /\.js|\.interface$/,
moduleType: this.moduleType.script
},
{
test: /\.json$/,
moduleType: this.moduleType.json
},
{
test: /\.(png|jpe?g|gif|svg|mp4|webm|ogg|mp3|wav|flac|aac|woff|woff2?|eot|ttf|otf)(\?.*)?$/,
moduleType: this.moduleType.asset
}
]
this.resolve = this.resolve.bind(this);
this.outputFileList = {}; // 输出对象
}
// path 是源文件路径 request是要解析的路径
resolve(start, request, context = {}) {
start = path.dirname(start);
return this._resolve.resolveSync(context, start, request)
}
watch(watchOptions, handler) {
this.fileTimestamps = {};
this.contextTimestamps = {};
const watching = new Watching(this, watchOptions, handler);
return watching;
}
async run() {
this.log.debug('start run!');
this.emit('start-run', Date.now());
// 每次编译要清空 编译图 重新计算 this.graphNodeMap做缓存
this.projectGraph = null;
this.fileDependencies = new Set();
this.oneLoopCompiledNode = [];
await this.createProjectGraph();
await this.customCompile();
this.emit('end-run', (Date.now()));
}
hook(eventName, func) {
this.event.on(eventName, func);
}
emit(eventName, ...params) {
this.log.debug('emit log:' + eventName + 'params:' + params)
this.event.emit(eventName, ...params);
}
// 触发事件 带通用参数
commonEmit(eventName, currentNode) {
let params = {
currentNode,
compile: this
}
this.event.emit(eventName, params);
}
// 创建依赖图
async createProjectGraph() {
this.createAppAndPage();
// 层级编译
while (this.compileQueue.length) {
let node = this.compileQueue.shift();
await this.compileNode(node);
}
this.log.debug('standard compile end!');
}
// 创建App和Page节点
createAppAndPage() {
let {projectRoot} = this.options;
let root = this.projectGraph = this.createNode({
realPath: path.join(this.options.projectRoot, 'src/app/app.cml'),
nodeType: this.nodeType.App
})
this.compileQueue.push(root);
let {hasError, routerConfig} = this.getRouterConfig();
if (!hasError) {
let routes = routerConfig.routes;
routes.forEach(route => {
let cmlFilePath = path.join(projectRoot, 'src', route.path + '.cml');
if (cmlUtils.isFile(cmlFilePath)) {
let pageNode = this.createNode({
realPath: cmlFilePath,
nodeType: this.nodeType.Page
})
root.dependencies.push(pageNode)
}
})
}
}
// 路由变化何时要触发编译
getRouterConfig() {
let {projectRoot} = this.options;
// 有配置路由文件,给app.json添加pages
let routerConfigPath = path.join(projectRoot, 'src/router.config.json');
let routerConfig = {};
let hasError = false;
try {
let content = this.readFileSync(routerConfigPath);
content = this.utf8BufferToString(content);
routerConfig = JSON.parse(content);
} catch (e) {
hasError = true;
}
return {
hasError,
routerConfig
};
}
async compileNode(currentNode) {
if (currentNode.compiled) {
return;
}
this.oneLoopCompiledNode.push(currentNode);
this.log.debug('standard compiled node: ' + currentNode.identifier)
switch (currentNode.nodeType) {
case this.nodeType.App:
await this.compileCMLFile(currentNode)
break;
case this.nodeType.Page:
await this.compileCMLFile(currentNode)
break;
case this.nodeType.Component:
await this.compileCMLFile(currentNode)
break;
case this.nodeType.Module:
await this.compileModule(currentNode);
break;
default:
throw new Error('not find nodeType '+ currentNode.nodeType);
}
// 实现层级编译
// 子模块的编译
if (currentNode.childrens && currentNode.childrens.length > 0) {
for (let i = 0; i < currentNode.childrens.length; i++) {
this.compileQueue.push(currentNode.childrens[i]);
}
}
// 依赖节点的编译
if (currentNode.dependencies && currentNode.dependencies.length > 0) {
for (let i = 0; i < currentNode.dependencies.length; i++) {
this.compileQueue.push(currentNode.dependencies[i]);
}
}
currentNode.compiled = true;
}
readNodeSource(currentNode) {
let buf = this.readFileSync(cmlUtils.delQueryPath(currentNode.realPath));
currentNode.ext = path.extname(currentNode.realPath);
if (this.stringExt.test(currentNode.ext)) {
buf = this.utf8BufferToString(buf);
}
currentNode.source = buf;
}
readFileSync(...args) {
return this.inputFileSystem.readFileSync.apply(this.inputFileSystem, args);
}
compileCMLFile(currentNode) {
let realPath = currentNode.realPath;
let content = currentNode.source;
let parts = cmlUtils.splitParts({content});
if (parts.template && parts.template[0]) {
let item = parts.template[0];
let newNode = this.createNode({
realPath,
nodeType: this.nodeType.Module,
moduleType: this.moduleType.Template,
source: item.content
})
newNode.attrs = item.attrs;
newNode.parent = currentNode;
currentNode.childrens.push(newNode);
}
if (parts.script && parts.script.length > 0) {
parts.script.forEach(item => {
let moduleType = item.cmlType === 'json' ? this.moduleType.json : this.moduleType.script;
let newNode = this.createNode({
realPath,
nodeType: this.nodeType.Module,
moduleType,
source: item.content
})
newNode.attrs = item.attrs;
newNode.parent = currentNode;
currentNode.childrens.push(newNode);
})
}
if (parts.style && parts.style[0]) {
let item = parts.style[0];
let newNode = this.createNode({
realPath,
nodeType: this.nodeType.Module,
moduleType: this.moduleType.style,
source: item.content
})
newNode.attrs = item.attrs;
newNode.parent = currentNode;
currentNode.childrens.push(newNode);
}
}
async compileModule(currentNode) {
switch (currentNode.moduleType) {
case this.moduleType.Template:
await this.compileTemplate(currentNode);
break;
case this.moduleType.style:
await this.compileStyle(currentNode);
break;
case this.moduleType.script:
await this.compileScript(currentNode);
break;
case this.moduleType.json:
await this.compileJson(currentNode);
break;
case this.moduleType.assets:
await this.compileAsset(currentNode);
break;
case this.moduleType.other:
// await this.compileOther(currentNode);
break;
default:
throw new Error('not find compile Module Type ' + currentNode.moduleType)
}
}
async compileTemplate(currentNode) {
let {convert, output} = await CMLParser.standardParser({
source: currentNode.source,
lang: currentNode.attrs.lang
});
currentNode.convert = convert;
currentNode.output = output;
}
async compileStyle(currentNode) {
let {output, imports} = await CMSSParser.standardCompile({
source: currentNode.source,
filePath: currentNode.realPath,
cmlType: this.options.cmlType,
lang: currentNode.attrs.lang,
compiler: this
});
currentNode.output = output;
imports.forEach(item => {
let newNode = this.createNode({
realPath: item,
nodeType: this.nodeType.Module,
moduleType: this.moduleType.style
})
currentNode.devDependencies.push(newNode);
})
}
async compileScript(currentNode) {
let self = this;
let { cmlType, media, config} = this.options;
let {source, devDeps} = await JSParser.standardParser({
cmlType,
media,
source: currentNode.source,
filePath: currentNode.realPath,
check: config.check,
resolve: this.resolve
});
for (let i = 0; i < devDeps.length; i++) {
let dependPath = devDeps[i];
let dependNode = self.createNode({
realPath: dependPath,
nodeType: self.nodeType.Module
})
currentNode.devDependencies.push(dependNode);
}
let result = await JSParser.JSCompile({source, filePath: currentNode.realPath, compiler: this});
currentNode.convert = result.ast;
for (let i = 0;i < result.dependencies.length;i++) {
let dependPath = result.dependencies[i];
let dependNode = self.createNode({
realPath: dependPath,
nodeType: self.nodeType.Module
})
currentNode.dependencies.push(dependNode);
}
}
async compileJson(currentNode) {
let {cmlType, projectRoot} = this.options;
let jsonObject;
try {
jsonObject = JSON.parse(currentNode.source);
} catch (e) {
this.log.warn(`The .json file corresponding to :${currentNode.realPath} is not correct`);
}
jsonObject = jsonObject || {};
if (currentNode.ext === '.cml') {
let targetObject = jsonObject[cmlType] || {};
if (jsonObject.base) {
targetObject = cmlUtils.merge(jsonObject.base, targetObject)
}
currentNode.convert = targetObject;
targetObject.usingComponents = targetObject.usingComponents || {};
Object.keys(targetObject.usingComponents).forEach(key => {
let comPath = targetObject.usingComponents[key];
let { filePath } = cmlUtils.handleComponentUrl(projectRoot, cmlUtils.delQueryPath(currentNode.realPath), comPath, cmlType);
if (cmlUtils.isFile(filePath)) {
let nodeType = this.nodeType.Module;
if (path.extname(filePath) === '.cml') {
nodeType = this.nodeType.Component;
}
let subNode = this.createNode({
realPath: filePath,
nodeType
})
currentNode.parent.dependencies.push(subNode);
this.compileQueue.push(subNode);
} else {
this.log.error(`can't find component:${comPath} in ${currentNode.realPath} `);
}
})
} else if (currentNode.ext == '.json') {
currentNode.convert = jsonObject;
}
}
async compileAsset(currentNode) {
let realPath = currentNode.realPath;
if (cmlUtils.isInline(realPath)) {
currentNode.output = `module.exports = ${JSON.stringify(this.getPublicPath(realPath)
)}`
}
}
// 用户想要添加文件依赖触发watch重新编译 需要给node添加依赖createNode创建节点
createNode({realPath, source, nodeType, moduleType}) {
this.fileDependencies.add(cmlUtils.delQueryPath(realPath));
let attrs;
if (nodeType === this.nodeType.Module) {
if (!moduleType) {
this.moduleRule.forEach(rule => {
if (rule.test.test(realPath)) {
moduleType = rule.moduleType;
attrs = rule.attrs;
}
})
moduleType = moduleType || this.moduleType.other;
}
} else {
moduleType = null;
}
let key = moduleType === null ? `${nodeType}_${realPath}` : `${nodeType}_${moduleType}_${realPath}`;
/*
缓存判断 1 同一个文件节点不重复创建 compileNode时 compiled为true
有文件 并且mtime 都相同 证明依赖的文件都没有改动 否则删除缓存
*/
if (this.graphNodeMap[key]) {
// 如果是cml文件的children则判断父节点是否有变化, 因为json节点的编译会给父节点添加dependencies,所以父节点变化了子节点也要重新编译
let targetNode = this.graphNodeMap[key].parent ? this.graphNodeMap[key].parent : this.graphNodeMap[key];
if (targetNode.notChange(this.fileTimestamps)) {
let fileDeps = targetNode.getDependenciesFilePaths();
fileDeps.forEach(item => this.fileDependencies.add(item));
return this.graphNodeMap[key];
}
}
let newNode = new CMLNode({
realPath,
nodeType,
moduleType,
attrs,
identifier: key
})
// js模块的模块类型
if (~[this.moduleType.script, this.moduleType.asset].indexOf(moduleType)) {
let modId = this.createModId(realPath);
newNode.modId = modId;
}
let noQueryPath = cmlUtils.delQueryPath(realPath);
newNode.mtime = fs.statSync(noQueryPath).mtime.getTime();
newNode.ext = path.extname(noQueryPath);
if (source) {
newNode.source = source;
} else {
this.readNodeSource(newNode);
}
this.graphNodeMap[key] = newNode;
return newNode;
}
createModId(realPath) {
let modId = realPath;
if (~realPath.indexOf(this.options.projectRoot)) {
modId = path.relative(this.options.projectRoot, realPath);
} else if (~realPath.indexOf(this.options.cmlRoot)) {
modId = path.relative(this.options.cmlRoot, realPath);
}
return modId;
}
// 根据资源路径 返回base64或者publicPath
getPublicPath(filePath) {
let publicPath = this.options.config.output.publicPath;
let mimetype = mime.getType(filePath);
let buf = this.readFileSync(cmlUtils.delQueryPath(filePath));
let result = '';
if (cmlUtils.isInline(filePath)) {
result = `data:${mimetype || ''};base64,${buf.toString('base64')}`
} else {
if (typeof publicPath === 'function') {
return publicPath(filePath);
} else {
// let modId = this.createModId(filePath);
let hash = cmlUtils.createMd5(buf);
if (publicPath[publicPath.length - 1] !== '/') {
publicPath = publicPath + '/';
}
let assetsPath = this.assetsPath;
if (assetsPath[0] === '/') {
assetsPath = assetsPath.slice(1);
}
let splitName = cmlUtils.splitFileName(filePath);
result = publicPath + assetsPath;
let replaceMap = {
filename: splitName[0],
ext: splitName[1],
hash
}
result = result.replace(/\$\{(.*?)\}/g, function(all, $1) {
return replaceMap[$1];
})
return result;
}
}
}
// 开启用户自定义编译
async customCompile() {
// 队列串行编译
// while (this.oneLoopCompiledNode.length) {
// let currentNode = this.oneLoopCompiledNode.shift();
// let key = currentNode.moduleType === null ? `compile-${currentNode.nodeType}` : `compile-${currentNode.nodeType}-${currentNode.moduleType}`;
// this.emit(key, currentNode);
// // AMD模块包装
// if (~[this.moduleType.script, this.moduleType.asset].indexOf(currentNode.moduleType) && currentNode.jsType === 'AMD') {
// AMDWrapper({compiler: this, currentNode})
// }
// }
// 递归编译
this.customCompileNode(this.projectGraph);
}
customCompileNode(currentNode) {
// 存在这个节点
let index = this.oneLoopCompiledNode.indexOf(currentNode);
if (index !== -1) {
// console.log('custom compile' + currentNode.moduleType + currentNode.realPath)
// 先删除 保证只编译一次
this.oneLoopCompiledNode.splice(index, 1);
if (~[this.nodeType.App, this.nodeType.Page, this.nodeType.Component].indexOf(currentNode.nodeType)) {
this.log.debug('custom compile preCML:' + currentNode.nodeType + '_' + currentNode.realPath);
this.emit(`compile-preCML`, currentNode, currentNode.nodeType);
} else {
// Template Script Style Json
this.log.debug('custom compile ' + currentNode.moduleType + ':' + currentNode.realPath);
let parent = currentNode.parent || {};
this.emit(`compile-${currentNode.moduleType}`, currentNode, parent.nodeType);
// AMD模块包装
// if (~[this.moduleType.script, this.moduleType.asset].indexOf(currentNode.moduleType) && currentNode.jsType === 'AMD') {
// AMDWrapper({compiler: this, currentNode})
// }
}
currentNode.childrens.forEach(item => {
this.customCompileNode(item);
})
currentNode.dependencies.forEach(item => {
this.customCompileNode(item);
})
if (~[this.nodeType.App, this.nodeType.Page, this.nodeType.Component].indexOf(currentNode.nodeType)) {
this.log.debug('custom compile postCML:' + currentNode.nodeType + '_' + currentNode.realPath);
this.emit(`compile-postCML`, currentNode, currentNode.nodeType);
}
}
}
utf8BufferToString(buf) {
var str = buf.toString("utf-8");
if (str.charCodeAt(0) === 0xFEFF) {
return str.substr(1);
} else {
return str;
}
}
}
module.exports = Compile;
exports.getAllCML = function({projectRoot}) {
let projectPath = path.resolve(root, 'src');
entry.app = path.join(projectPath, 'app/app.cml');
}
const EventEmitter = require('events');
module.exports = EventEmitter;
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NodeWatchFileSystem = require("./NodeWatchFileSystem");
const NodeOutputFileSystem = require("./NodeOutputFileSystem");
const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem");
const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem");
class NodeEnvironmentPlugin {
apply(compiler) {
compiler.inputFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 60000);
const inputFileSystem = compiler.inputFileSystem;
compiler.outputFileSystem = new NodeOutputFileSystem();
compiler.watchFileSystem = new NodeWatchFileSystem(compiler.inputFileSystem);
compiler.hook("before-run", () => {
if (compiler.inputFileSystem === inputFileSystem) {inputFileSystem.purge();}
callback();
});
}
}
module.exports = NodeEnvironmentPlugin;
const fs = require("fs");
const path = require("path");
const mkdirp = require("mkdirp");
class NodeOutputFileSystem {
constructor() {
this.mkdirp = mkdirp;
this.mkdir = fs.mkdir.bind(fs);
this.rmdir = fs.rmdir.bind(fs);
this.unlink = fs.unlink.bind(fs);
this.writeFile = fs.writeFile.bind(fs);
this.join = path.join.bind(path);
}
}
module.exports = NodeOutputFileSystem;
// fileSystem.utf8BufferToString = function (buf) {
// var str = buf.toString("utf-8");
// if (str.charCodeAt(0) === 0xFEFF) {
// return str.substr(1);
// } else {
// return str;
// }
// }
// fileSystem.convertArgs = function(args, raw) {
// if (!raw && Buffer.isBuffer(args[0])) {args[0] = utf8BufferToString(args[0]);} else if (raw && typeof args[0] === "string")
// {args[0] = new Buffer(args[0], "utf-8");} // eslint-disable-line
// }
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Watchpack = require("watchpack");
class NodeWatchFileSystem {
constructor(inputFileSystem) {
this.inputFileSystem = inputFileSystem;
this.watcherOptions = {
aggregateTimeout: 0
};
this.watcher = new Watchpack(this.watcherOptions);
}
watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) {
if (!Array.isArray(files)) {throw new Error("Invalid arguments: 'files'");}
if (!Array.isArray(dirs)) {throw new Error("Invalid arguments: 'dirs'");}
if (!Array.isArray(missing)) {throw new Error("Invalid arguments: 'missing'");}
if (typeof callback !== "function") {throw new Error("Invalid arguments: 'callback'");}
if (typeof startTime !== "number" && startTime) {throw new Error("Invalid arguments: 'startTime'");}
if (typeof options !== "object") {throw new Error("Invalid arguments: 'options'");}
if (typeof callbackUndelayed !== "function" && callbackUndelayed) {throw new Error("Invalid arguments: 'callbackUndelayed'");}
const oldWatcher = this.watcher;
this.watcher = new Watchpack(options);
if (callbackUndelayed) {this.watcher.once("change", callbackUndelayed);}
this.watcher.once("aggregated", (changes, removals) => {
changes = changes.concat(removals);
if (this.inputFileSystem && this.inputFileSystem.purge) {
this.inputFileSystem.purge(changes);
}
const times = this.watcher.getTimes();
callback(null,
changes.filter(file => files.indexOf(file) >= 0).sort(),
changes.filter(file => dirs.indexOf(file) >= 0).sort(),
changes.filter(file => missing.indexOf(file) >= 0).sort(), times, times);
});
this.watcher.watch(files.concat(missing), dirs.concat(missing), startTime);
if (oldWatcher) {
oldWatcher.close();
}
return {
close: () => {
if (this.watcher) {
this.watcher.close();
this.watcher = null;
}
},
pause: () => {
if (this.watcher) {
this.watcher.pause();
}
}
};
}
}
module.exports = NodeWatchFileSystem;
const chalk = require('chalk');
class Log {
constructor(options = {}) {
this.level = options.level || 2;
}
debug (msg) {
if (this.level >= 3) {
process.stdout.write('\n' + chalk.gray('[DEBUG]') + ' ' + msg + '\n');
}
}
notice (msg) {
if (this.level >= 2) {
process.stdout.write('\n' + chalk.cyan('[INFO]') + ' ' + msg + '\n');
}
}
warn (msg) {
if (this.level >= 1) {
process.stdout.write('\n' + chalk.yellow('[WARNI]') + ' ' + msg + '\n');
}
}
error(msg) {
if (this.level >= 0) {
process.stdout.write('\n' + chalk.red('[ERROR]') + ' ' + msg + '\n');
}
}
}
module.exports = Log;
const Compile = require('./Compile');
/**
* @param {options} 构建参数
* @return {Compile} 编译对象
*/
function MVVMPack(options) {
let compile = new Compile(options);
return compile;
}
module.exports = MVVMPack;
module.exports = function({compiler, currentNode}) {
currentNode.output = `define('${currentNode.modId}', function(require, exports, module){${currentNode.output}\r\n});`
}
let AMDWrapper = require('./AMDWrapper');
module.exports = {
AMDWrapper
}
const { ResolverFactory, NodeJsInputFileSystem, CachedInputFileSystem} = require('enhanced-resolve');
const path = require('path');
module.exports = function(options) {
let defaultOptions = {
extensions: ['.cml', '.interface', '.vue', '.js', '.json'],
alias: {
'$CMLPROJECT': path.join(options.cmlRoot),
'$PROJECT': path.join(options.projectRoot)
},
modules: [
'node_modules',
path.join(options.cmlRoot, '/node_modules')
],
"unsafeCache": true,
"mainFiles": ["index"],
"aliasFields": ["browser"],
"mainFields": ["browser", "module", "main"],
"cacheWithContext": false}
options.config = options.config || {}
options.config.resolve = options.config.resolve || {};
return ResolverFactory.createResolver(Object.assign(
{
useSyncFileSystemCalls: true,
fileSystem: new CachedInputFileSystem(new NodeJsInputFileSystem(), 4000)
},
defaultOptions,
options.config.resolve
))
}
class Watching {
constructor(compiler, watchOptions, handler) {
this.startTime = null;
this.invalid = false;
this.handler = handler;
this.callbacks = [];
this.closed = false;
if (typeof watchOptions === "number") {
this.watchOptions = {
aggregateTimeout: watchOptions
};
} else if (watchOptions && typeof watchOptions === "object") {
this.watchOptions = Object.assign({}, watchOptions);
} else {
this.watchOptions = {};
}
this.watchOptions.aggregateTimeout = this.watchOptions.aggregateTimeout || 200;
this.compiler = compiler;
this.running = true;
this._go();
}
async _go() {
// 记录上一次编译开始的时间 下次watch从这时候开始
this.startTime = Date.now();
this.running = true;
this.invalid = false;
await this.compiler.run();
this._done();
}
_getStats(compilation) {
const stats = new Stats(compilation);
stats.startTime = this.startTime;
stats.endTime = Date.now();
return stats;
}
_done(err, compilation) {
this.running = false;
if (this.invalid) {return this._go();}
this.handler(null, this.compiler);
let contextDependencies = [];
let missingDependencies = [];
if (!this.closed) {
this.watch([...this.compiler.fileDependencies], contextDependencies, missingDependencies);
}
}
watch(files, dirs, missing) {
this.pausedWatcher = null;
this.watcher = this.compiler.watchFileSystem.watch(files, dirs, missing, this.startTime, this.watchOptions, (err, filesModified, contextModified, missingModified, fileTimestamps, contextTimestamps) => {
this.pausedWatcher = this.watcher;
this.watcher = null;
if (err) {return this.handler(err);}
this.compiler.fileTimestamps = fileTimestamps;
this.compiler.contextTimestamps = contextTimestamps;
this.invalidate();
}, (fileName, changeTime) => {
this.compiler.emit("invalid", fileName, changeTime);
});
}
invalidate(callback) {
if (callback) {
this.callbacks.push(callback);
}
if (this.watcher) {
this.pausedWatcher = this.watcher;
this.watcher.pause();
this.watcher = null;
}
if (this.running) {
this.invalid = true;
return false;
} else {
this._go();
}
}
close(callback) {
if (callback === undefined) {callback = function() {};}
this.closed = true;
if (this.watcher) {
this.watcher.close();
this.watcher = null;
}
if (this.pausedWatcher) {
this.pausedWatcher.close();
this.pausedWatcher = null;
}
if (this.running) {
this.invalid = true;
this._done = () => {
this.compiler.emit("watch-close");
callback();
};
} else {
this.compiler.emit("watch-close");
callback();
}
}
}
module.exports = Watching;
{
"name": "old-mvvm-pack",
"version": "0.3.0-alpha.2",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"chai": "^4.2.0",
"chalk": "^2.4.2",
"chameleon-tool-utils": "0.3.0-alpha.2",
"enhanced-resolve": "^4.1.0",
"mime": "^2.4.0",
"mvvm-interface-parser": "0.3.0-alpha.2",
"mvvm-script-parser": "0.3.0-alpha.2",
"mvvm-style-parser": "0.3.0-alpha.2",
"mvvm-template-parser": "0.3.0-alpha.2",
"watchpack": "^1.6.0"
}
}
\ No newline at end of file
const filePath = path.resolve('./ResolveFactory.test.js')
const result = compile.inputFileSystem.readFileSync(filePath);
const Compile = require('../lib/Compile.js');
const path = require('path');
let compile = new Compile({
config: {},
cmlRoot: path.resolve('./'),
projectRoot: path.resolve('./')
})
const filePath = path.resolve('./ResolveFactory.test.js')
const result = compile.readFileSync(filePath);
const path = require('path')
const ResolveFactory = require('../lib/ResolveFactory.js')
let resolve = ResolveFactory({
config: {},
cmlRoot: path.resolve('../'),
projectRoot: path.join('../')
});
resolve.resolve({}, '/Users/didi/Documents/newcml/open/mvvm-sets/test_project/src/app/', '../router.config.json?__inline', {}, function(err, result) {
if (err) {
throw err;
}
console.log(path.extname(result))
// expect(result).to.equal(path.join(__dirname,'../src/Event.js'))
})
const ResolveFactory = require('../lib/ResolveFactory.js')
let expect = require('chai').expect;
const path = require('path');
describe('ResolveFactory', function() {
it('getResolveObject', function() {
let result = ResolveFactory({
config: {},
cmlRoot: path.resolve('../'),
projectRoot: path.join('../')
});
expect(typeof result).to.equal('object')
})
it('resolve Relative Path', function() {
let resolve = ResolveFactory({
config: {},
cmlRoot: path.resolve('../'),
projectRoot: path.join('../')
});
resolve.resolve({}, path.join(__dirname), '../src/Event', {}, function(err, result) {
if (err) {
throw err;
}
console.log(result)
expect(result).to.equal(path.join(__dirname, '../src/Event.js'))
})
})
})
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册