UNPKG

7.67 kBJavaScriptView Raw
1var prj = require('./project.js');
2var fs = require('fs');
3var path = require('path');
4var walk = require('./util/walk.js');
5var _ = require('underscore');
6var J = require("juicer");
7var conf = require('./config.js');
8var debug = require('debug')('clam:mod');
9var templateCenter = require('./template.js');
10var mkdirp = require('mkdirp');
11var iconv = require('iconv-lite');
12
13var config = {
14 metaDir: '.clam',
15 metaFile : 'mod.json',
16 suffix : ['vm', 'php', 'html'],
17 templateDir : "../resource/mod/",
18 assetsDir : "assets",
19 coreName : "core",
20 coreTemplate:"../resource/mod/core",
21 headTemplate:"../resource/mod/head"
22};
23var appDir = path.resolve(__dirname);
24
25J.set("strip", false);
26/**
27 * 返回modsDir中所有的模块,递归的,返回所有子目录的模块。
28 * 模块以config.suffix中所标识的扩展名结束
29 * 如果,目录结构如下:
30 * mods/a/a.vm
31 * mods/a/b/b.vm
32 *
33 * 应该解析2个模块,分别叫做a/a.vm 和 a/b/b.vm 每一个.vm都是一个模块
34 * 每个.vm应对应一个同名.css及.js文件,不强制要求有css和js文件。
35 * 限定模块的css和js文件必须小余一定规模,比如500行。这么做的目的是为了鼓励拆分模块中复杂逻辑到widget中。
36 *
37 * 返回的模块名在.clam/mods.json中有额外信息记录。比如description。
38 */
39exports.list = function() {
40 var prjInfo = prj();
41
42 var modsDir = path.join(conf.root(), prjInfo.modsDir);
43 var metaFile = path.join(conf.root(), config.metaDir, config.metaFile);
44 var modsFiles = walk.walkSync(modsDir);
45 modsFiles = _.filter(modsFiles, function(file) {
46 return _.any(config.suffix, function(value) {
47 // 改为直接用后缀名判断,防止.vm.swp 这类文件混入
48 var fileSuffix = file.match(/.*\/.*\.(\w+)$/)[1];
49 return fileSuffix == value;
50 });
51 });
52 //console.log(modsFiles);
53 //conf.root() + prjInfo.dir
54 var metaInfo = conf.get('mod');
55
56 var info = _.map(modsFiles, function(file) {
57 var fileName = file.slice(modsDir.length+1, file.length);
58 var modName = file.slice(modsDir.length+1, file.lastIndexOf('.'));
59 var description = '';
60 if(metaInfo){
61 description = metaInfo[modName] ? metaInfo[modName].description : '';
62 }
63
64 return {
65 name : modName,
66 file : fileName,
67 description : description
68 };
69 });
70 return {succeed:true,
71 msg:'获取模块信息',
72 data:info
73 };
74}
75
76/**
77 * 创建模块,就是创建一个文件夹,及模块下对应的文件。
78 * 1、模块一定存在于一个包中,不能直接放置到mods目录下
79 * 2、默认情况下,模块被创建一个同名目录中。
80 * 3、可以创建子模块。
81 *
82 * 创建的模块如果有额外信息,需要记录到.clam/mods.json中
83 * 创建的模块,需要有额外注释,描述模块名。
84 *
85 * 未来,创建模块时,可以选择基于某模板创建,比如活动页面的模块。
86 */
87var addMod = exports.add = function(modName, description, template) {
88 var prjInfo = prj();
89 var actions = [];
90
91 //只支持几种扩展名,并且默认一个模块必须在子目录中
92 var modFileName = computeExt(modName);
93 if(modFileName.split('/').length === 1){
94 var modNameSet = modFileName.replace(/\..*$/, '');
95 modFileName = modNameSet + '/' + modFileName;
96 }
97 debug(modFileName);
98 //如果存在相同模块报错
99 var modFilePath = path.join(conf.root(), prjInfo.modsDir, modFileName);
100 if (fs.existsSync(modFilePath)) {
101 return {
102 succeed: false,
103 msg: '已存在相同的模块,创建模块失败。',
104 data: modFilePath
105 };;
106 }
107
108 //创建模块HTML文件目录
109 var modDir = path.join(modFilePath, '..');
110 mkdirp.sync(modDir);
111
112 //修改目录权限为775
113 var modDepsdirs = modFileName.split('/');
114 var dir = '', j = 0;
115 for(var i = 0; i < modDepsdirs.length-1; i++){
116 dir = path.join(conf.root(), prjInfo.modsDir);
117 j = 0;
118 while(j <= i ){
119 dir = path.join(dir, modDepsdirs[j]);
120 j++;
121 }
122 debug('修改目录权限%s', dir);
123 fs.chmodSync(dir,'775');
124 }
125
126 //取得模板路径
127 if(!template){
128 template = 'default';
129 }
130 var userHome = process.env.HOME || process.env.HOMEPATH;//兼容windows
131 var templateDir = path.join(userHome, '.clamconfig/templates', template,'mod');
132 if(!fs.existsSync(templateDir)){
133 return {
134 succeed: false,
135 msg: '模板'+template+'不存在',
136 data: ''
137 };
138 }
139
140 //转换模板
141 var bn = modDepsdirs[modDepsdirs.length-1];
142 var baseModName = path.basename(bn, path.extname(bn));
143 var modInfo = {
144 name: baseModName,
145 description: description
146 };
147 var param = {project: prjInfo, mod: modInfo};
148 templateCenter.convert(templateDir, modDir, param, baseModName);
149
150 //记录模块元信息
151 var metaInfo = conf.get('mod');
152 if(!metaInfo){
153 metaInfo = {};
154 }
155
156 metaInfo[modFileName.replace(/\.(html)$/,'')] = modInfo;
157 conf.set('mod', metaInfo);
158 actions.push({action:'更新模块元信息', content: '.clam/mod.json'});
159
160 //完成创建后执行回调
161 return {
162 succeed: true,
163 msg: '模块创建',
164 data: actions
165 };
166}
167
168/**
169 * 删除模块
170 */
171exports.del = function (data) {
172 var prjInfo = prj();
173 var dirName = path.dirname(data.name);
174 var fileName = path.basename(data.name);
175 var modDir = path.join(conf.root(), prjInfo.modsDir, dirName);
176 var modPath = path.join(conf.root(), prjInfo.modsDir, dirName, fileName+'.'+prjInfo.pageext[0]);
177 var actions = [];
178 if(!fs.existsSync(modPath)){
179 return {
180 succeed:false,
181 msg:modPath+"文件不存在"
182 }
183 }
184 //删除页面文件
185 fs.unlinkSync(modPath);
186 actions.push({action:'删除文件', content: modPath});
187 //检查该文件夹下是否还有文件,如果没有的话就删掉
188 var list = fs.readdirSync(modDir);
189 list = _.filter(list,function(file){
190 return _.any(config.suffix, function(value) {
191 return file.lastIndexOf(value) !== -1;
192 });
193 });
194 if(list.length==0){
195 walk.rmrfSync(modDir);
196 actions.push({action:'删除文件目录', content: modDir});
197 }
198 return {succeed:true,
199 msg:'删除页面',
200 data:actions
201 };
202
203}
204
205/**
206 * 创建core模块
207 */
208exports.addCore = function(){
209 var prjInfo = prj();
210 var name = config.coreName;
211 //添加核心模块
212 addMod({
213 name:name,
214 description:"项目核心模块,包含一些不依赖任何库的JS方法和页头页尾等通用模块",
215 addjs:true,
216 addcss:true,
217 jsns:prjInfo.jsns
218 },{
219 templateDir : config.coreTemplate
220 });
221 //添加头<head>内容模块
222 addMod({
223 name:name+"/head",
224 description:"项目页面head标签部分内容",
225 addjs:false,
226 addcss:false
227 },{
228 templateDir : config.headTemplate
229 });
230}
231
232//设置模块文件的扩展名,如果不是以下列表的,就改为.vm
233function computeExt(str) {
234 var prjInfo = prj();
235 if ((/\.(vm|php|html|htm)$/).test(str)) {
236 return str;
237 }
238 return str.replace(/\..*$/, "") + '.' + prjInfo.pageext[0];
239}
240/*
241function writeFile(path,str){
242 var prjInfo = prj();
243 var c = iconv.encode(str,prjInfo.charset[0]);
244 fs.writeFileSync(path, c);
245 fs.chmodSync(path, "777");
246}*/