add ttf node module auto build

This commit is contained in:
kekee000
2015-01-27 18:15:30 +08:00
parent bafa263a73
commit b9b14522e3
9 changed files with 405 additions and 1 deletions

6
build-node.sh Normal file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
# ttf 模块node端组件导出程序
edp build --config ./edp-build-config-node.js --force
echo "asset path../fonteditor-ttf/lib"

73
edp-build-config-node.js Normal file
View File

@@ -0,0 +1,73 @@
var path = require( 'path' );
var amd2module = require('./node/amd2module');
exports.input = path.resolve(__dirname, './src');;
exports.output = path.resolve(__dirname, '../fonteditor-ttf/lib');
exports.getProcessors = function () {
var NodeModuleProcessor = {
name: 'NodeModuleProcessor',
files: [
'common/lang.js',
'common/string.js',
'common/observable.js',
'common/DomParser.js',
'math/**/*.js',
'graphics/**/*.js',
'ttf/**/*.js'
],
process: function(file, processContext, callback) {
var depth = new Array(file.path.split('/').length).join('../');
if (file.data.indexOf('define') >= 0) {
file.setData(amd2module(file.data, depth));
}
callback();
}
}
return [
NodeModuleProcessor,
// 清除冗余文件,比如`less`
new OutputCleaner({
files: [
'common/ajaxFile.js',
'common/DataStore.js',
'common/observable.js',
'common/promise.js',
'editor/**',
'fonteditor/**',
'render/**',
'template/**'
]
})
];
};
exports.exclude = [
".svn",
"*.conf",
"*.sh",
"*.bat",
"*.md",
"demo",
"agent/*",
"mock",
"test/*",
"edp-*",
"output",
".DS_Store",
".gitignore",
"package.json",
"node"
];
exports.injectProcessor = function ( processors ) {
for ( var key in processors ) {
global[ key ] = processors[ key ];
}
};

186
node/amd2module.js Normal file
View File

@@ -0,0 +1,186 @@
/**
* @file amd 模块转换为commonjs模块
* @author mengke01(kekee000@gmail.com)
*/
var esprima = require('esprima');
var estraverse = require( 'estraverse' );
var escodegen = require('escodegen');
var SYNTAX = estraverse.Syntax;
// 顶级模块,用来生成相对位置
var REG_TOP_MODULE = /^(:?common|math|graphics|ttf)/;
var EXPORT_SEGMENT = {
"expression": {
"left": {
"computed": false,
"object": {
"name": "module",
"type": "Identifier"
},
"property": {
"name": "exports",
"type": "Identifier"
},
"type": "MemberExpression"
},
"operator": "=",
"right": null,
"type": "AssignmentExpression"
},
"type": "ExpressionStatement"
};
/**
* 获取导出声明
*
* @return {Object}
*/
function getExportStatement() {
return JSON.parse(JSON.stringify(EXPORT_SEGMENT));
}
/**
* 获取ast树
* @param {string} code 代码片段
* @return {Object} ast树
*/
function getAst(code) {
var ast = null;
try {
ast = esprima.parse(code, {
});
} catch (ex) {
throw 'can\'t parse amd code';
}
return ast;
}
/**
* 获取define的factory
*
* @return {astNode}
*/
function getDefineFactory(defineExpr) {
var args = defineExpr['arguments'];
var factoryAst;
// 解析参数
for (var i = 0, l = args.length; i < l; i++) {
var argument = args[i];
if (argument.type === SYNTAX.FunctionExpression || argument.type === SYNTAX.ObjectExpression) {
factoryAst = argument;
break;
}
}
return factoryAst;
}
/**
* 替换define的return为 module.exports
*
* @param {Object} ast ast
* @return {Object} ast
*/
function replaceDefine(ast) {
estraverse.replace(ast, {
enter: function (node, parent) {
if ( node.type == SYNTAX.ExpressionStatement
&& node.expression.type == SYNTAX.CallExpression
&& node.expression.callee.name == 'define'
) {
var factory = getDefineFactory(node.expression);
// define('xxx', {})
if (factory.type === SYNTAX.ObjectExpression) {
var exportStatment = getExportStatement();
exportStatment.expression.right = factory;
return exportStatment;
}
// define(function() {})
else if (factory.type === SYNTAX.FunctionExpression){
var body = factory.body.body;
// 替换return
for (var i = body.length - 1; i >=0; i--) {
if (body[i].type == SYNTAX.ReturnStatement) {
var exportStatment = getExportStatement();
exportStatment.expression.right = body[i].argument;
body.splice(i, 1, exportStatment);
break;
}
}
var index = parent.body.indexOf(node);
Array.prototype.splice.apply(parent.body, [index, 1].concat(body));
return body[0];
}
}
return node;
}
} );
return ast;
}
/**
* 替换require的绝对路径为相对路径
*
* @param {Object} ast ast
* @param {Object} codeDepth 当前模块位置
* @return {Object} ast
*/
function replaceRequire(ast, codeDepth) {
estraverse.replace(ast, {
enter: function (node, parent) {
if ( node.type == SYNTAX.CallExpression
&& node.callee.name == 'require'
&& node.arguments.length
&& node.arguments[0].type == 'Literal'
) {
var argument = node.arguments[0];
if (REG_TOP_MODULE.test(argument.value)) {
argument.value = codeDepth + argument.value;
}
}
return node;
}
} );
return ast;
}
/**
* 生成commonjs代码
* @param {Object} ast ast树
* @return {string} 生成后的代码
*/
function genCommonJS(ast) {
return escodegen.generate(ast);
}
module.exports = function (code, codeDepth) {
if (codeDepth && codeDepth[codeDepth.length - 1] !== '/') {
codeDepth += '/';
}
var ast = getAst(code);
var replacedAst = replaceRequire(ast, codeDepth);
replacedAst = replaceDefine(replacedAst);
return genCommonJS(replacedAst);
};

35
node/generated.js Normal file
View File

@@ -0,0 +1,35 @@
var string = require('../common/string');
var error = {
10001: '\u8D85\u51FA\u8BFB\u53D6\u8303\u56F4\uFF1A${0}, ${1}',
10002: '\u8D85\u51FA\u5199\u5165\u8303\u56F4\uFF1A${0}, ${1}',
10003: '\u672A\u77E5\u6570\u636E\u7C7B\u578B\uFF1A${0}, ${1}',
10004: '\u4E0D\u652F\u6301svg\u89E3\u6790',
10101: '\u9519\u8BEF\u7684ttf\u6587\u4EF6',
10102: '\u9519\u8BEF\u7684woff\u6587\u4EF6',
10103: '\u9519\u8BEF\u7684svg\u6587\u4EF6',
10104: '\u8BFB\u53D6ttf\u6587\u4EF6\u9519\u8BEF',
10105: '\u8BFB\u53D6woff\u6587\u4EF6\u9519\u8BEF',
10106: '\u8BFB\u53D6svg\u6587\u4EF6\u9519\u8BEF',
10107: '\u5199\u5165ttf\u6587\u4EF6\u9519\u8BEF',
10108: '\u5199\u5165woff\u6587\u4EF6\u9519\u8BEF',
10109: '\u5199\u5165svg\u6587\u4EF6\u9519\u8BEF',
10110: '\u8BFB\u53D6eot\u6587\u4EF6\u9519\u8BEF',
10111: '\u8BFB\u53D6eot\u5B57\u4F53\u9519\u8BEF',
10200: '\u91CD\u590D\u7684unicode\u4EE3\u7801\u70B9\uFF0C\u5B57\u5F62\u5E8F\u53F7\uFF1A${0}',
10201: '\u5B57\u5F62\u8F6E\u5ED3\u6570\u636E\u4E3A\u7A7A',
10202: '\u4E0D\u652F\u6301\u6807\u5FD7\u4F4D\uFF1AARGS_ARE_XY_VALUES',
10203: '\u672A\u627E\u5230\u8868\uFF1A${0}',
10204: '\u8BFB\u53D6\u8868\u9519\u8BEF',
10205: '\u672A\u627E\u5230\u89E3\u538B\u51FD\u6570'
};
error.raise = function (number) {
var message = error[number];
if (arguments.length > 1) {
var args = typeof arguments[1] === 'object' ? arguments[1] : Array.prototype.slice.call(arguments, 1);
message = string.format(message, args);
}
var e = new Error(message);
e.number = number;
throw e;
};
module.exports = error;

13
node/test.js Normal file
View File

@@ -0,0 +1,13 @@
/**
* @file 测试模块转换
* @author mengke01(kekee000@gmail.com)
*/
var fs = require('fs');
var amd2module = require('./amd2module');
function main() {
var code = fs.readFileSync('../src/ttf/error.js');
fs.writeFileSync('./generated.js', amd2module(code, '../'));
}
main();

View File

@@ -20,5 +20,7 @@
"author": "",
"license": "MIT",
"devDependencies": {
"esprima": "~1.1.1",
"estraverse": "~1.5.0",
}
}

15
src/common/DOMParser.js Normal file
View File

@@ -0,0 +1,15 @@
/**
* @file DOM解析器兼容node端和浏览器端
* @author mengke01(kekee000@gmail.com)
*/
if (typeof exports !== 'undefined') {
module.exports = exports = require('xmldom').DOMParser;
}
else {
define(
function (require) {
return window.DOMParser;
}
);
}

View File

@@ -10,6 +10,7 @@
define(
function (require) {
var string = require('common/string');
var DOMParser = require('common/DOMParser');
var path2contours = require('./svg/path2contours');
var svgnode2contours = require('./svg/svgnode2contours');
var contoursTransform = require('./svg/contoursTransform');
@@ -24,7 +25,7 @@ define(
* @return {XMLDocument}
*/
function loadXML(xml) {
if (document.implementation && document.implementation.createDocument) {
if (DOMParser) {
try {
var domParser = new DOMParser();
var xmlDoc = domParser.parseFromString(xml, 'text/xml');

73
test/china.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 103 KiB