@@ -4,65 +4,70 @@ const glob = require('glob')
44const { marked} = require ( 'marked' )
55const MagicString = require ( 'magic-string' )
66const md5 = require ( 'md5' )
7+ const axios = require ( 'axios' )
8+ const FormData = require ( 'form-data' ) ;
9+ const cliProgress = require ( 'cli-progress' ) ;
710
8- const flattenToken = ( token ) => {
9- const { type, tokens, text, href } = token
10- switch ( type ) {
11- case 'list' :
12- const items = token . items . map ( item => flattenToken ( item ) )
13- return { type, items }
14- case 'list_item' :
15- if ( tokens . length == 1 && tokens [ 0 ] . tokens . length == 1 ) {
16- const final = tokens [ 0 ] . tokens [ 0 ] ;
17- return final . type == 'text' ? text : flattenToken ( final ) ;
18- }
19- if ( tokens . length == 1 ) {
20- return flattenToken ( tokens [ 0 ] )
21- }
22- // console.log(token);
23- return tokens . map ( item => flattenToken ( item ) )
24- case 'row' :
25- return { type, row : token . rows }
26- case 'text' :
27- case 'paragraph' :
28- if ( ! tokens ) return text
29- if ( tokens . length == 1 ) {
30- return tokens [ 0 ] . type == 'text' ? text : flattenToken ( tokens [ 0 ] )
31- }
32- return tokens . map ( item => flattenToken ( item ) )
33- case 'strong' :
34- case 'codespan' :
35- case 'em' :
36- return { type, text }
37- case 'html' :
38- const ans = / < i m g .+ s r c = " ( [ \w \. \/ - ] + ) " / . exec ( text )
39- if ( ans ) {
40- return { type : 'image' , href : ans [ 1 ] , text : '图片' }
41- }
42- return ''
43- case 'image' :
44- // todo upload image
45- // token.href
46- return { type, text, href }
47- case 'link' :
48- return { type, text, href }
49- case 'space' :
50- return ''
51- case 'blockquote' :
52- return text
53- default :
54- console . log ( token )
11+ const config = require ( '../config' )
12+
13+ const bar = new cliProgress . SingleBar ( { } , cliProgress . Presets . shades_classic ) ;
14+
15+ let accessToken = ''
16+ const getAccessToken = async ( ) => {
17+ if ( accessToken ) return accessToken
18+
19+ const { data } = await axios . get ( 'https://api.weixin.qq.com/cgi-bin/token' , {
20+ params : {
21+ grant_type : 'client_credential' ,
22+ appid : config . appid ,
23+ secret : config . secret
24+ }
25+ } )
26+ if ( data . access_token ) {
27+ accessToken = data . access_token
28+ return accessToken
5529 }
56- return token
30+ throw new TypeError ( data )
5731}
5832
59- glob ( path . resolve ( __dirname , '../HowToCook/dishes/**/*.md' ) , { } , ( err , files ) => {
33+
34+ const uploadImage = async ( filePath ) => {
35+ const cloudPath = 'cookbook'
36+ const token = await getAccessToken ( )
37+ const url = 'https://api.weixin.qq.com/tcb/uploadfile?access_token=' + token
38+ const { data } = await axios . post ( url , {
39+ env : config . cloudEnvId ,
40+ path : cloudPath
41+ } )
42+ if ( data . errcode == 0 ) {
43+ const { url, token, authorization, file_id, cos_file_id} = data ;
44+ const form = new FormData ( )
45+
46+ form . append ( 'key' , authorization ) ;
47+ form . append ( 'Signature' , authorization ) ;
48+ form . append ( 'x-cos-security-token' , token ) ;
49+ form . append ( 'x-cos-meta-fileid' , cos_file_id ) ;
50+ form . append ( 'file' , fs . createReadStream ( filePath ) ) ;
51+
52+ return new Promise ( ( resolve , reject ) => {
53+ form . submit ( url , ( err ) => {
54+ if ( err ) reject ( err )
55+ resolve ( file_id . replace ( cloudPath , '' ) + authorization )
56+ } )
57+ } )
58+ } else {
59+ throw new TypeError ( data . errmsg )
60+ }
61+ }
62+
63+ glob ( path . resolve ( __dirname , '../HowToCook/dishes/**/*.md' ) , { } , async ( err , files ) => {
6064 if ( err ) {
6165 console . log ( err )
6266 }
6367 const dishes = [ ]
6468 let no = 0
6569
70+ bar . start ( files . length , 0 ) ;
6671 for ( let p of files ) {
6772 const { name, dir } = path . parse ( p )
6873 const [ , category ] = / d i s h e s \/ ( [ \w - ] + ) \/ / g. exec ( p )
@@ -75,14 +80,68 @@ glob(path.resolve(__dirname, '../HowToCook/dishes/**/*.md'), {}, (err, files) =>
7580 detail : [ ] ,
7681 desc : [ ]
7782 }
83+ const flattenToken = async ( token ) => {
84+ const { type, tokens, text, href } = token
85+ switch ( type ) {
86+ case 'list' :
87+ const items = await Promise . all ( token . items . map ( async item => await flattenToken ( item ) ) )
88+ return { type, items }
89+ case 'list_item' :
90+ if ( tokens . length == 1 && tokens [ 0 ] . tokens . length == 1 ) {
91+ const final = tokens [ 0 ] . tokens [ 0 ] ;
92+ return final . type == 'text' ? text : await flattenToken ( final ) ;
93+ }
94+ if ( tokens . length == 1 ) {
95+ return await flattenToken ( tokens [ 0 ] )
96+ }
97+ // console.log(token);
98+ return await Promise . all ( tokens . map ( async item => await flattenToken ( item ) ) )
99+ case 'row' :
100+ return { type, row : token . rows }
101+ case 'text' :
102+ case 'paragraph' :
103+ if ( ! tokens ) return text
104+ if ( tokens . length == 1 ) {
105+ return tokens [ 0 ] . type == 'text' ? text : await flattenToken ( tokens [ 0 ] )
106+ }
107+ return await await Promise . all ( tokens . map ( async item => await flattenToken ( item ) ) )
108+ case 'strong' :
109+ case 'codespan' :
110+ case 'em' :
111+ return { type, text }
112+ case 'html' :
113+ const ans = / < i m g .+ s r c = " ( [ \w \. \/ - ] + ) " / . exec ( text )
114+ if ( ans ) {
115+ const data = await uploadImage ( path . resolve ( dir , ans [ 1 ] ) )
116+ return { type : 'image' , href : data , text : '图片' }
117+ }
118+ return ''
119+ case 'image' :
120+ // todo upload image
121+ // token.href
122+ const data = await uploadImage ( path . resolve ( dir , href ) )
123+ return { type, text, href : data }
124+ case 'link' :
125+ return { type, text, href }
126+ case 'space' :
127+ return ''
128+ case 'blockquote' :
129+ return text
130+ default :
131+ console . log ( token )
132+ }
133+ return token
134+ }
78135
79136 no ++ ;
80137 target = null ;
81138
82- marked . lexer ( content , {
139+ const tokens = marked . lexer ( content , {
83140 baseUrl : dir ,
84141 xhtml : true
85- } ) . forEach ( ( token ) => {
142+ } ) ;
143+
144+ for ( let token of tokens ) {
86145 const { text, type, depth } = token ;
87146
88147 if ( type == 'heading' ) {
@@ -105,15 +164,18 @@ glob(path.resolve(__dirname, '../HowToCook/dishes/**/*.md'), {}, (err, files) =>
105164 }
106165 } else if ( type !== 'space' ) {
107166 if ( target == null ) {
108- menu . desc . push ( flattenToken ( token ) )
167+ menu . desc . push ( await flattenToken ( token ) )
109168 } else {
110- const tmp = flattenToken ( token )
169+ const tmp = await flattenToken ( token )
111170 target . push ( tmp )
112171 }
113172 }
114- } )
173+ }
174+ bar . update ( no )
115175 dishes . push ( menu )
116176 }
177+
178+ bar . stop ( )
117179
118180 const jsonData = new MagicString ( '' ) ;
119181 const s = new MagicString ( JSON . stringify ( dishes , null , 2 ) )
0 commit comments