1+ var exec = require ( 'child_process' ) . exec ;
2+ var fs = require ( 'fs' ) ;
3+ var ejs = require ( 'ejs' ) ;
4+ var path = require ( 'path' ) ;
5+ var marked = require ( 'marked' ) ;
6+ var watch = require ( 'watch' ) ;
7+ var stylus = require ( 'stylus' )
8+ var highlight = require ( 'highlight.js' )
9+ var renderer = new marked . Renderer ( ) ;
10+ var color = require ( 'colors-cli/safe' ) ;
11+ var error = color . red . bold ;
12+ var warn = color . yellow ;
13+ var notice = color . blue ;
14+ var success = color . green ;
15+
16+ // console.log("该行代码所在的目录::",__dirname);
17+ // console.log("当前运行的的根目录::",path.dirname(__dirname));
18+ // console.log("当前目录名字::",path.basename(process.cwd()));
19+ // console.log("当前目录::",process.cwd());
20+
21+ renderer . heading = function ( text , level ) {
22+ if ( / [ \u4E00 - \u9FA5 ] / i. test ( text ) ) {
23+ return '<h' + level + ' id="' + text . toLowerCase ( ) + '">' + text + '</h' + level + '>' ;
24+ } else {
25+ var escapedText = text . toLowerCase ( ) . replace ( / [ ^ \w ] + / g, '-' ) ;
26+ return '<h' + level + ' id="' + escapedText + '">' + text + '</h' + level + '>' ;
27+ }
28+ }
29+
30+ marked . setOptions ( {
31+ renderer : renderer ,
32+ gfm : true ,
33+ tables : true ,
34+ breaks : true ,
35+ pedantic : false ,
36+ sanitize : false ,
37+ smartLists : true ,
38+ smartypants : false ,
39+ highlight : function ( code , lang , callback ) {
40+ if ( lang ) {
41+ return callback ( '' , highlight . highlight ( lang , code ) . value ) ;
42+ } else {
43+ return callback ( '' , highlight . highlightAuto ( code ) . value ) ;
44+ }
45+ }
46+ } ) ;
47+
48+ var path_root = path . dirname ( __dirname ) ;
49+
50+
51+ // .deploy
52+ // 当前项目根目录
53+ // 生成 项目所需的文件
54+ CreateDatajs ( './.deploy/js/dt.js' , function ( dt_path , arr ) {
55+
56+ cp ( path . join ( path_root , '/template/js/index.js' ) ,
57+ path . join ( path_root , '/.deploy/js/index.js' ) , function ( err , r ) {
58+ if ( err ) return console . log ( error ( " → error:" ) , err . errno ) ;
59+ console . log ( success ( " → " ) + '/template/js/index.js' ) ;
60+ } )
61+
62+ CreateStyl ( '/template/styl/index.styl' , '/.deploy/css/index.css' )
63+ // 首页生成
64+ ReadTmpToHTML ( '/template/index.ejs' , '/.deploy/index.html' ) ;
65+ ReadTmpToHTML ( '/template/list.ejs' , '/.deploy/list.html' ) ;
66+ // 文章批量生成
67+ arr . forEach ( function ( itm , idx ) {
68+ var ejstpm = path . join ( '/template/' , itm . p ) ;
69+ var md_path = path . join ( '/command' , itm . p ) ;
70+ var dep = path . join ( '/.deploy/command' , itm . p ) ;
71+ ReadTmpToHTML ( '/template/details.ejs' , dep + '.html' , md_path + '.md' )
72+ } ) ;
73+
74+ } )
75+
76+ // 监听实时编译
77+ watch . watchTree ( path . join ( path . dirname ( __dirname ) , '/' ) , function ( f , curr , prev ) {
78+ if ( typeof f == "object" && prev === null && curr === null ) {
79+ console . log ( success ( " → :watching " ) + '/template/' ) ;
80+ // Finished walking the tree
81+ } else if ( prev === null ) {
82+
83+ // f is a new file
84+ } else if ( curr . nlink === 0 ) {
85+ // f was removed
86+ } else {
87+
88+ if ( / \. s t y l $ / . test ( f ) ) {
89+ CreateStyl ( '/template/styl/index.styl' , '/.deploy/css/index.css' )
90+ } else if ( / \. j s $ / . test ( f ) ) {
91+
92+ cp ( path . join ( path_root , '/template/js/index.js' ) ,
93+ path . join ( path_root , '/.deploy/js/index.js' ) , function ( err , r ) {
94+ if ( err ) return console . log ( error ( " → error:" ) , err . errno ) ;
95+ console . log ( success ( " → " ) + '/template/js/index.js' ) ;
96+ } )
97+
98+ } else if ( / \. e j s $ / . test ( f ) ) {
99+ // 首页生成
100+ ReadTmpToHTML ( '/template/index.ejs' , '/.deploy/index.html' ) ;
101+ ReadTmpToHTML ( '/template/list.ejs' , '/.deploy/list.html' ) ;
102+
103+ } else if ( / \. m d $ / . test ( f ) ) {
104+ var mdp = f . replace ( path_root , '' ) ;
105+ var dep = path . join ( '/.deploy/' , mdp ) ;
106+ ReadTmpToHTML ( '/template/details.ejs' , dep . replace ( '.md' , '.html' ) , mdp ) ;
107+ }
108+ }
109+ } )
110+
111+
112+ /**
113+ * [ReadTmpToHTML ejs 模板转换成HTML]
114+ * @param {[type] } from_path [模版来源地址]
115+ * @param {[type] } to_path [生成到指定的位置]
116+ * @param {[type] } md_path [Markdown的位置]
117+ */
118+ function ReadTmpToHTML ( from_path , to_path , md_path ) {
119+ var tmp_path = path . join ( path . dirname ( __dirname ) , from_path ) ;
120+ if ( ! exists ( tmp_path ) ) return console . log ( "\n → error: 模板文件 " + tmp_path + " 不存在" )
121+ var tmp_str = fs . readFileSync ( tmp_path ) ;
122+ tmp_str = tmp_str . toString ( ) ;
123+
124+ var relative_path = '' ;
125+ if ( md_path ) {
126+ relative_path = path . relative ( md_path . toString ( ) , '/' ) ;
127+ relative_path = relative_path . replace ( / \. \. $ / , '' ) ;
128+ }
129+ // 生成 HTML
130+ var html = ejs . render ( tmp_str , {
131+ filename : tmp_path ,
132+ relative_path :relative_path
133+ } ) ;
134+ // 生成到指定目录
135+ var new_to_path = path . join ( path . dirname ( __dirname ) , to_path ) ;
136+ // 循环创建目录
137+ mkdirsSync ( path . dirname ( new_to_path ) ) ;
138+ if ( md_path ) {
139+ var new_md_path = path . join ( path . dirname ( __dirname ) , md_path ) ;
140+ var README_str = fs . readFileSync ( new_md_path ) ;
141+ marked ( README_str . toString ( ) , function ( err , md_html ) {
142+ if ( err ) return console . log ( error ( ' → ' + md_path + " 转换成HTML失败!" ) ) ;
143+
144+ html = html . replace ( '{{content}}' , md_html ) ;
145+ html = html . replace ( '<!--[编辑]-->' , '<a class="edit_btn" href="' + path . join ( 'https://github.com/jaywcjlove/linux-command/edit/master/' , md_path ) + '">编辑</a>' )
146+ fs . writeFileSync ( new_to_path , html ) ;
147+ console . log ( success ( " → " ) + to_path + '' ) ;
148+
149+ } )
150+ } else {
151+
152+ html = html . toString ( ) ;
153+ fs . writeFileSync ( new_to_path , html . replace ( / \n / g, '' ) ) ;
154+ console . log ( success ( " → " ) + to_path + '' ) ;
155+ }
156+ }
157+
158+
159+
160+
161+ /**
162+ * [CreateStyl 生成CSS]
163+ * @param {[type] } styl_path [description]
164+ * @param {[type] } css_path [description]
165+ */
166+ function CreateStyl ( styl_path , css_path ) {
167+ var new_css_path = path . join ( path . dirname ( __dirname ) , css_path ) ;
168+ styl_path = path . dirname ( __dirname ) + styl_path ;
169+ // var paths = [
170+ // path.dirname(__dirname) , path.dirname(__dirname) + '/'
171+ // ];
172+ var styl_str = fs . readFileSync ( styl_path , 'utf8' ) ;
173+ stylus ( styl_str . toString ( ) )
174+ . set ( 'filename' , styl_path )
175+ . set ( 'compress' , true )
176+ . render ( function ( err , css ) {
177+ if ( err ) throw err ;
178+ // 循环创建目录
179+ mkdirsSync ( path . dirname ( new_css_path ) ) ;
180+ fs . writeFileSync ( new_css_path , css ) ;
181+ // console.log(err,css);
182+ console . log ( success ( " → " ) + styl_path + '' ) ;
183+ } ) ;
184+ }
185+
186+ // 生成数据索引JS
187+ function CreateDatajs ( dt_path , callback ) {
188+ // 获取 markdown文件所在的目录
189+ var path_md = path . join ( path . dirname ( __dirname ) , 'command' ) ;
190+ if ( ! exists ( path_md ) ) return console . log ( "\n → error: 文件夹 " + path_md + " 不存在 \n " )
191+ // 获取 markdown 目录的集合
192+ var path_arr = readMDSync ( path_md ) ;
193+ var indexes = [ ]
194+ path_arr . forEach ( function ( md_path , i ) {
195+ var json = { }
196+ var con = fs . readFileSync ( md_path ) ;
197+ var str = con . toString ( ) ;
198+ var title = str . match ( / [ ^ = = = ] + (? = [ = = = ] ) / g) ;
199+ // 命令名称
200+ json [ "n" ] = title [ 0 ] ?title [ 0 ] . replace ( / \n / g, '' ) :title [ 0 ] ;
201+ // 命令路径
202+ json [ "p" ] = md_path . replace ( / \. m d $ / , '' ) . replace ( path_md , '' ) ;
203+ // 命令描述
204+ var des = str . match ( / \n = = = { 1 , } ( [ \s \S ] * ?) # # / i) ;
205+ json [ "d" ] = des [ 1 ] ?des [ 1 ] . replace ( / \n / g, '' ) :des [ 1 ] ;
206+ indexes . push ( json )
207+ } )
208+ mkdirsSync ( path . dirname ( dt_path ) ) ;
209+ //生成数据文件
210+ fs . writeFile ( dt_path , 'var linux_commands=' + JSON . stringify ( indexes ) , 'utf8' , function ( err ) {
211+ console . log ( success ( "\n → " ) + "生成数据成功!" + dt_path + " \n " ) ;
212+ callback && callback ( dt_path , indexes ) ;
213+ } ) ;
214+ }
215+
216+
217+ // 同步循环创建所有目录 resolvePath
218+ function mkdirsSync ( dirpath , mode , callback ) {
219+ if ( fs . existsSync ( dirpath ) ) {
220+ callback && callback ( dirpath ) ;
221+ return true ;
222+ } else {
223+ if ( mkdirsSync ( path . dirname ( dirpath ) , mode ) ) {
224+ fs . mkdirSync ( dirpath , mode , callback ) ;
225+ callback && callback ( dirpath ) ;
226+ return true ;
227+ } else {
228+ callback && callback ( dirpath ) ;
229+ }
230+ }
231+ } ;
232+
233+ var fixture = path . join . bind ( path , __dirname , 'template' ) ;
234+
235+ function cp ( src , dest , cb ) {
236+ // yield support
237+ if ( 'function' != typeof cb ) return thunk ;
238+
239+ var complete = false ;
240+ var read = fs . createReadStream ( src ) ;
241+ var write = fs . createWriteStream ( dest ) ;
242+
243+ write . on ( 'error' , done ) ;
244+ write . on ( 'close' , done ) ;
245+ read . on ( 'error' , done ) ;
246+ read . pipe ( write ) ;
247+
248+ // done callback
249+ function done ( err ) {
250+ if ( ! complete ) {
251+ complete = true ;
252+ read . destroy ( ) ;
253+ write . destroy ( ) ;
254+ cb ( err ) ;
255+ }
256+ }
257+
258+ // thunk-ified
259+ function thunk ( done ) {
260+ cp ( src , dest , done ) ;
261+ }
262+ }
263+
264+ //返回 MD 所有路径的 Array
265+ function readMDSync ( filepath ) {
266+ if ( ! exists ( filepath ) ) return [ ] ;
267+ var str = '' , files = fs . readdirSync ( filepath ) ;
268+ for ( var i = 0 ; i < files . length ; i ++ ) {
269+ var path_c = path . join ( filepath , files [ i ] ) ;
270+ if ( isDir ( path_c ) ) {
271+ str += readMDSync ( path_c ) + ',' ;
272+ }
273+ else if ( / \. ( m d ) $ / . test ( files [ i ] ) ) str += path_c + ',' ;
274+ } ;
275+ str = str . replace ( / ^ \* | \, * $ / g, '' ) ;
276+ return str . split ( ',' ) ;
277+ }
278+ //写文件
279+ function writeSync ( filepath , content , callback ) {
280+ mkdirsSync ( path . dirname ( filepath ) ) ;
281+ return fs . writeFileSync ( filepath , content , callback ) ;
282+ } ;
283+
284+ //写文件
285+ function write ( filepath , content ) {
286+ return fs . writeFile ( filepath , content ) ;
287+ } ;
288+
289+ //判断是不是目录
290+ function isDir ( _path ) { return exists ( _path ) && fs . statSync ( _path ) . isDirectory ( ) ; }
291+
292+ //检查指定路径的文件或者目录,是否存在
293+ function exists ( _path ) { return fs . existsSync ( _path ) ; }
0 commit comments