Last active
February 24, 2020 09:16
-
-
Save Cheny-chen/a35e3d50b898513a0230fa8e19e8ed40 to your computer and use it in GitHub Desktop.
Revisions
-
Cheny-chen revised this gist
Feb 24, 2020 . 1 changed file with 38 additions and 27 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -20,7 +20,7 @@ const _env_conf = {source_dirs: [], skipped_paths:[], tmpl: null, output: null}; const working_root = process.cwd(); let line_sum=0; // Read incoming arguments { const [, , basic_dir, tmpl_path, ...exec_args] = process.argv; @@ -182,8 +182,7 @@ await ParseFile(file, named_map, unnamed_pool); } } console.error(`\nRendering...`); // Output generated script base on template script @@ -253,10 +252,11 @@ } function WriteToStream(stream, data){ return new Promise((resolve, reject)=>{ stream.write(data, ()=>resolve(true)); // if( !should_wait ){ // reject(false); // } }); } function CloseStream(stream){ @@ -284,18 +284,21 @@ return arrayFiles; } function GenerateLineReader(filePath) { return new Promise((resolve)=>{ let lineNumer=0; const output = new stream.PassThrough({objectMode:true, highWaterMark:1000}); const readInterface = readline.createInterface({ input: fs.createReadStream(filePath), }); readInterface.on("line", line => { output.write(line); lineNumer++; }); readInterface.on("close", () => { output.push(null); resolve( {readInterface:output, lineNumer:lineNumer} ); }); }); } async function ParseFile(filePath, named, unnamed){ let idx1, idx2; @@ -305,12 +308,17 @@ let line_count=0; let line_queue=[]; const { readInterface, lineNumer} = await GenerateLineReader(filePath); for await(const new_line of readInterface) { line_sum++; line_queue.push(new_line); ProcessLineQueue(); if(lineNumer===line_sum) { line_sum=0; return; } } // Do remaining cleanup on boundary conditions @@ -328,7 +336,7 @@ async function ProcessLineQueue() { while(line_queue.length > 0) { let line = line_queue.shift(); line_count++; @@ -343,6 +351,7 @@ if ( line[idx1+START_SIG_LEN] === '=' ) { name_key = line.substring(idx1+START_SIG_LEN+1).trim(); // Purge key identifiers if (name_key[0] === '!' || name_key[0] === '@' || name_key === '?') { name_key = name_key.substring(1); @@ -358,13 +367,14 @@ // Search for paired //@endexport const has_terminator = ((idx1 = line.indexOf(END_SIG)) >= 0); const has_starter = ((idx2 = line.indexOf(START_SIG)) >= 0); if ( !has_starter && !has_terminator ) { collect_buffer += line + "\n"; continue; } if ( has_starter ) { // console.log('has_starter', line_queue); if ( !has_terminator || idx2 < idx1 ) { console.error(` ${line_count}:\n A paired //@endexport token must be presented before //@export token!`); process.exit(1); @@ -375,7 +385,7 @@ line_queue.push(line.substring(idx1+END_SIG_LEN)); line_count--; } collect_buffer += line.substring(0, idx1); if ( name_key !== null ) { @@ -391,6 +401,7 @@ collect_mode = false; collect_buffer = ''; } } } })() -
Cheny-chen revised this gist
Feb 24, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -358,7 +358,7 @@ // Search for paired //@endexport const has_terminator = ((idx1 = line.indexOf(END_SIG)) >= 0); const has_starter = ((idx2 = line.indexOf(START_SIG)) >= 0); if ( !has_starter || !has_terminator ) { collect_buffer += line + "\n"; continue; } -
Cheny-chen revised this gist
Feb 24, 2020 . 1 changed file with 5 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -262,9 +262,9 @@ function CloseStream(stream){ return new Promise((resolve, reject)=>stream.end(resolve)); } function ReadMainFolder(folder, arrayFiles = [], arrayFolder = []) { fs.readdirSync(folder, {withFileTypes: true}).forEach(filename=>{ if( filename.isDirectory() && filename.name.indexOf('.')!==0 ){ arrayFolder.push(path.join(folder, filename.name)); return; } @@ -281,7 +281,6 @@ arrayFiles.concat(temp); } } return arrayFiles; } function GenerateLineReader(filePath) { @@ -308,6 +307,8 @@ const readInterface = GenerateLineReader(filePath); for await(const new_line of readInterface) { console.log(new_line); line_queue.push(new_line); ProcessLineQueue(); } -
Cheny-chen revised this gist
Feb 11, 2020 . 1 changed file with 91 additions and 45 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,7 +17,7 @@ const readline = require('readline'); const _env_conf = {source_dirs: [], skipped_paths:[], tmpl: null, output: null}; const working_root = process.cwd(); @@ -58,6 +58,15 @@ break; } case '--skip': { const tpath = exec_args.pop() || ''; if ( tpath ) { _env_conf.skipped_paths.push(path.resolve(working_root, tpath)); } break; } case "--output": case "-o":{ const fpath = exec_args.pop() || ''; @@ -80,7 +89,7 @@ // Expose collected arguments const {tmpl, source_dirs, output, skipped_paths} = _env_conf; // Fetch template @@ -163,46 +172,62 @@ // Collect and parse all js script of the target folders const named_map = {}, unnamed_pool = []; for ( const dir_path of source_dirs ){ const arrayFiles = ReadMainFolder(dir_path); for ( const file of arrayFiles ) { if ( skipped_paths.indexOf(file) >= 0 ) continue; console.error(`Parsing ${file}...`); await ParseFile(file, named_map, unnamed_pool); } } console.error(`\nRendering...`); // Output generated script base on template script { const {statics, dynamics} = template; await WriteToStream(write_stream, statics[0]); for( let i = 1; i < statics.length; i++ ){ const dynamic_content = dynamics[i - 1]; if( typeof dynamic_content !== "string" ) { await WriteToStream(write_stream, '' + dynamic_content); await WriteToStream(write_stream, statics[i]); continue; } if ( dynamic_content === "@unnamed" ) { for( const code_segment of unnamed_pool ){ await WriteToStream(write_stream, code_segment); } await WriteToStream(write_stream, statics[i]); continue; } const important = dynamic_content[0] === '!'; const optional = dynamic_content[0] === '?'; const key = (important || optional) ? dynamic_content.substring(1) : dynamic_content; const seg_pool = named_map[key]; if( seg_pool !== undefined ){ for( const code_segment of seg_pool ) { await WriteToStream(write_stream, code_segment); } } else if( important ){ console.error(` Missing required named block \`${ key }\``); process.exit(1); } else{ if( !optional ){ console.error(` Miss matching named block \`${ key }\``); } await WriteToStream(write_stream, ''); @@ -211,10 +236,6 @@ await WriteToStream(write_stream, statics[i]); } await CloseStream(write_stream); @@ -241,53 +262,72 @@ function CloseStream(stream){ return new Promise((resolve, reject)=>stream.end(resolve)); } function ReadMainFolder(folder, arrayFiles = [], arrayFolder = []) { fs.readdirSync(folder, {withFileTypes: true}).forEach(filename=>{ if( filename.isDirectory() ){ arrayFolder.push(path.join(folder, filename.name)); return; } if ( filename.name.indexOf('.js') > 0 ) { arrayFiles.push(path.join(folder, filename.name)); } }); if( arrayFolder.length > 0 ){ for (const foldername of arrayFolder) { if ( skipped_paths.indexOf(foldername) >= 0 ) continue; const temp = ReadMainFolder(foldername, arrayFiles); arrayFiles.concat(temp); } } return arrayFiles; } function GenerateLineReader(filePath) { const output = new stream.PassThrough({objectMode:true}); const readInterface = readline.createInterface({ input: fs.createReadStream(filePath), }); readInterface.on("line", line => { output.write(line); }); readInterface.on("close", () => { output.push(null); }); return output; } async function ParseFile(filePath, named, unnamed){ let idx1, idx2; let name_key=null; let collect_mode=false; let collect_buffer=''; let line_count=0; let line_queue=[]; const readInterface = GenerateLineReader(filePath); for await(const new_line of readInterface) { line_queue.push(new_line); ProcessLineQueue(); } // Do remaining cleanup on boundary conditions if ( collect_mode && collect_buffer !== '' ) { console.error(` Unterminated region detected!`); if ( name_key !== null ) { named[name_key] = named[name_key] || []; named[name_key].push(collect_buffer); } else { unnamed.push(collect_buffer); } } function ProcessLineQueue() { while(line_queue.length > 0) { let line = line_queue.shift(); line_count++; @@ -301,6 +341,11 @@ collect_mode = true; if ( line[idx1+START_SIG_LEN] === '=' ) { name_key = line.substring(idx1+START_SIG_LEN+1).trim(); // Purge key identifiers if (name_key[0] === '!' || name_key[0] === '@' || name_key === '?') { name_key = name_key.substring(1); } } // Ignore the whole line since that contents before //@export is defined to be discarded @@ -320,7 +365,7 @@ if ( has_starter ) { if ( !has_terminator || idx2 < idx1 ) { console.error(` ${line_count}:\n A paired //@endexport token must be presented before //@export token!`); process.exit(1); return; } @@ -333,7 +378,8 @@ collect_buffer += line.substring(0, idx1); if ( name_key !== null ) { named[name_key] = named[name_key] || []; named[name_key].push(collect_buffer); } else { unnamed.push(collect_buffer); -
Cheny-chen revised this gist
Jan 29, 2020 . No changes.There are no files selected for viewing
-
Cheny-chen revised this gist
Jan 29, 2020 . 1 changed file with 6 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -281,6 +281,7 @@ const readInterface = await ReadLines(filePath); let idx1, idx2, name_key=null, collect_mode=false, collect_buffer='', line_count=0, line_queue=[]; for await(const new_line of readInterface) { line_queue.push(new_line); @@ -331,13 +332,17 @@ collect_buffer += line.substring(0, idx1); if ( name_key !== null ) { named[name_key] = collect_buffer; } else { unnamed.push(collect_buffer); } // Clear state collect_mode = false; collect_buffer = ''; } } } -
Cheny-chen revised this gist
Jan 29, 2020 . 1 changed file with 61 additions and 39 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,6 +5,12 @@ (async()=>{ "use strict"; const START_SIG = "//@export"; const START_SIG_LEN = START_SIG.length; const END_SIG = "//@endexport"; const END_SIG_LEN = END_SIG.length; const fs = require('fs'); const path = require('path'); const stream = require('stream'); @@ -155,7 +161,6 @@ // Collect and parse all js script of the target folders const named_map = {}, unnamed_pool = []; for await( const dir_path of source_dirs ){ @@ -166,9 +171,7 @@ } } // Output generated script base on template script { @@ -219,9 +222,6 @@ function TemplateResolver(strings, ...dynamics) { if ( !(this instanceof TemplateResolver) ) { return new TemplateResolver(strings, ...dynamics); @@ -278,46 +278,68 @@ }) } async function ParseFile(filePath, named, unnamed){ const readInterface = await ReadLines(filePath); let idx1, idx2, name_key=null, collect_mode=false, collect_buffer='', line_count=0, line_queue=[]; for await(const new_line of readInterface) { line_queue.push(new_line); while(line_queue.length > 0) { let line = line_queue.shift(); line_count++; // Search for //@export if ( !collect_mode ) { if ( (idx1 = line.indexOf(START_SIG)) < 0 ) continue; // Parse //@export=[key] collect_mode = true; if ( line[idx1+START_SIG_LEN] === '=' ) { name_key = line.substring(idx1+START_SIG_LEN+1).trim(); } // Ignore the whole line since that contents before //@export is defined to be discarded continue; } // Search for paired //@endexport const has_terminator = ((idx1 = line.indexOf(END_SIG)) >= 0); const has_starter = ((idx2 = line.indexOf(START_SIG)) >= 0); if ( !has_terminator || !has_terminator ) { collect_buffer += line + "\n"; continue; } if ( has_starter ) { if ( !has_terminator || idx2 < idx1 ) { console.error(`${filePath}:${line_count}:\n A paired //@endexport token must be presented before //@export token!`); process.exit(1); return; } // The token //@endexport is presented at right position! line_queue.push(line.substring(idx1+END_SIG_LEN)); line_count--; } collect_buffer += line.substring(0, idx1); collect_mode = false; if ( name_key !== null ) { named[name_key] = collect_buffer; } else { unnamed.push(collect_buffer); } } } } })() .catch((e)=>setTimeout(()=>{throw e;})); -
Cheny-chen revised this gist
Jan 29, 2020 . 1 changed file with 307 additions and 112 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,128 +1,323 @@ /** * Author: ChenyChen, JCloudYu * Create: 2020/01/29 **/ (async()=>{ "use strict"; const fs = require('fs'); const path = require('path'); const stream = require('stream'); const readline = require('readline'); const _env_conf = {source_dirs: [], tmpl: null, output: null}; const working_root = process.cwd(); // Read incoming arguments { const [, , basic_dir, tmpl_path, ...exec_args] = process.argv; exec_args.reverse(); if( !basic_dir ){ console.error("Source directory is not assigned!"); process.exit(1); return; } _env_conf.source_dirs.push(path.resolve(working_root, basic_dir)); if( !tmpl_path ){ console.error("Template script is not assigned!"); process.exit(1); return; } _env_conf.tmpl = path.resolve(working_root, tmpl_path); while( exec_args.length > 0 ){ const opt = exec_args.pop(); switch( opt ){ case "--dir": case "-d":{ const dpath = exec_args.pop() || ''; if( dpath ){ _env_conf.source_dirs.push(path.resolve(working_root, dpath)); } break; } case "--output": case "-o":{ const fpath = exec_args.pop() || ''; if( fpath ){ _env_conf.output = path.resolve(working_root, fpath); } break; } default:{ console.error(`Unknown option \`${ opt }\``); process.exit(1); return; } } } } // Expose collected arguments const {tmpl, source_dirs, output} = _env_conf; // Fetch template global.BuildTemplate = TemplateResolver; const template = (()=>{ try{ const script = require(tmpl); if( !(script instanceof TemplateResolver) ){ console.error("Given tmpl is not a valid template descriptor!"); process.exit(1); return null; } return script; } catch(e){ if( e.code === 'ENOENT' ){ console.error(`Template path \`${ tmpl }\` doesn't exist!`); process.exit(1); return null; } throw e; } })(); // Check source directories { for( const dir_path of source_dirs ){ try{ const dir_stat = fs.statSync(dir_path); if( !dir_stat.isDirectory() ){ console.error(`Source path \`${ dir_path }\` is not a directory!`); process.exit(1); return; } } catch(e){ if( e.code === "ENOENT" ){ console.error(`Source path \`${ dir_path }\` is not a directory!`); process.exit(1); return; } throw e; } try{ fs.accessSync(dir_path, fs.constants.R_OK | fs.constants.X_OK); } catch(e){ console.error(`Current user has no privilege to access directory \`${ dir_path }\`!`); process.exit(1); return; } } } // Create output stream const write_stream = (()=>{ if( !output ) return process.stdout; try{ return fs.createWriteStream(output, {mode: 0o644, flags: 'w'}); } catch(e){ return null; } })(); if( !write_stream ){ console.error(`Cannot create output stream to file \`${ output }\`!`); process.exit(1); return; } // Collect and parse all js script of the target folders const named_map = {}, unnamed_pool = []; for await( const dir_path of source_dirs ){ const arrayFiles = await ReadMainFolder(dir_path); for await ( const file of arrayFiles ){ await ParseFile(file, named_map, unnamed_pool); } } console.log(named_map, unnamed_pool); // Output generated script base on template script { const {statics, dynamics} = template; await WriteToStream(write_stream, statics[0]); for( let i = 1; i < statics.length; i++ ){ const dynamic_content = dynamics[i - 1]; if( typeof dynamic_content !== "string" ){ await WriteToStream(write_stream, '' + dynamic_content); await WriteToStream(write_stream, statics[i]); continue; } const important = dynamic_content[0] === '!'; const optional = dynamic_content[0] === '?'; const key = (important || optional) ? dynamic_content.substring(1) : dynamic_content; const code_segment = named_map[key]; if( code_segment !== undefined ){ await WriteToStream(write_stream, code_segment); } else if( important ){ console.error(`Missing required named block \`${ key }\``); process.exit(1); } else{ if( !optional ){ console.error(`Missm matching named block \`${ key }\``); } await WriteToStream(write_stream, ''); } await WriteToStream(write_stream, statics[i]); } for( const code_segment of unnamed_pool ){ await WriteToStream(write_stream, code_segment); } await CloseStream(write_stream); } function TemplateResolver(strings, ...dynamics) { if ( !(this instanceof TemplateResolver) ) { return new TemplateResolver(strings, ...dynamics); } this.statics = strings; this.dynamics = dynamics; } function WriteToStream(stream, data){ return new Promise((resolve, reject)=>{ const should_wait = stream.write(data, ()=>resolve(true)); if( !should_wait ){ reject(false); } }); } function CloseStream(stream){ return new Promise((resolve, reject)=>stream.end(resolve)); } async function ReadMainFolder(folder, arrayFiles = [], arrayFolder = []){ fs.readdirSync(folder, {withFileTypes: true}).forEach(filename=>{ if( filename.isDirectory() && !/^\..*|test*/.test(filename.name) ){ arrayFolder.push(path.join(folder, filename.name)); } if( !filename.isDirectory() && filename.name.indexOf('.js') > 0 ){ arrayFiles.push(path.join(folder, filename.name)); } }); if( arrayFolder.length > 0 ){ for await(const foldername of arrayFolder) { const temp = await ReadMainFolder(foldername, arrayFiles); arrayFiles.concat(temp); } } return arrayFiles } async function ReadLines(filePath) { return new Promise( async(resolve, reject) => { const output = new stream.PassThrough({ objectMode: true }); const readInterface = readline.createInterface({ input: fs.createReadStream(filePath), }); readInterface.on("line", line => { output.write(line); }); readInterface.on("close", () => { output.push(null); }); resolve(output); }) } async function ParseFile(filePath, named, unnamed){ return new Promise( async(resolve, reject) => { const readInterface = await ReadLines(filePath); let flag = false, splitByEqualsSign = [], temp_unamed = '', index=0; for await(let line of readInterface) { if( line.indexOf('//@export') > -1 ) { splitByEqualsSign = line.split('='); line = '\n'; flag = true; } else if( line.indexOf('//@endexport') > -1 ){ line = line.replace('//@endexport', ''); flag = false; if( temp_unamed ){ unnamed.push(temp_unamed); temp_unamed = ''; } } if( flag ){ line = line + '\n'; if( splitByEqualsSign[1] && !named.hasOwnProperty(splitByEqualsSign[1]) ){ named[splitByEqualsSign[1]] = ''; } else if( splitByEqualsSign.length > 1 && splitByEqualsSign[1] ){ named[splitByEqualsSign[1]] += line; } else if( line !== '\n' ){ temp_unamed += line; } } } resolve(true); }) } })() .catch((e)=>setTimeout(()=>{throw e;})); -
Cheny-chen revised this gist
Jan 29, 2020 . 1 changed file with 112 additions and 308 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,324 +1,128 @@ (()=>{ // NOTE: Helper functions const writable=true, configurable=true, enumerable=false; const [ExtES, IsNodeJS, Padding, UTF8Encode, UTF8Decode] = (()=>{ const IsNodeJS = (typeof Buffer !== "undefined" && ArrayBuffer.isView(Buffer)); const UTF8_DECODE_CHUNK_SIZE = 100; const GLOBAL = IsNodeJS ? global : window; const ExtES = GLOBAL.ExtES = Object.create(null); return [ ExtES, IsNodeJS, function Padding(val, length=2, stuffing='0'){ val = `${val}`; let remain = length - val.length; while( remain-- > 0 ) { val = stuffing + val; } return val; }, function UTF8Encode(js_str) { if ( typeof js_str !== "string" ) { throw new TypeError( "Given input argument must be a js string!" ); } let codePoints = []; let i=0; while( i < js_str.length ) { let codePoint = js_str.codePointAt(i); // 1-byte sequence if( (codePoint & 0xffffff80) === 0 ) { codePoints.push(codePoint); } // 2-byte sequence else if( (codePoint & 0xfffff800) === 0 ) { codePoints.push( 0xc0 | (0x1f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } // 3-byte sequence else if( (codePoint & 0xffff0000) === 0 ) { codePoints.push( 0xe0 | (0x0f & (codePoint >> 12)), 0x80 | (0x3f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } // 4-byte sequence else if( (codePoint & 0xffe00000) === 0 ) { codePoints.push( 0xf0 | (0x07 & (codePoint >> 18)), 0x80 | (0x3f & (codePoint >> 12)), 0x80 | (0x3f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } i += (codePoint>0xFFFF) ? 2 : 1; } return new Uint8Array(codePoints); }, function UTF8Decode(raw_bytes) { if ( raw_bytes instanceof ArrayBuffer ) { raw_bytes = new Uint8Array(raw_bytes); } if ( !(raw_bytes instanceof Uint8Array) ) { throw new TypeError( "Given input must be an Uint8Array contains UTF8 encoded value!" ); } let uint8 = raw_bytes; let codePoints = []; let i = 0; while( i < uint8.length ) { let codePoint = uint8[i] & 0xff; // 1-byte sequence (0 ~ 127) if( (codePoint & 0x80) === 0 ){ codePoints.push(codePoint); i += 1; } // 2-byte sequence (192 ~ 223) else if( (codePoint & 0xE0) === 0xC0 ){ codePoint = ((0x1f & uint8[i]) << 6) | (0x3f & uint8[i + 1]); codePoints.push(codePoint); i += 2; } // 3-byte sequence (224 ~ 239) else if( (codePoint & 0xf0) === 0xe0 ){ codePoint = ((0x0f & uint8[i]) << 12) | ((0x3f & uint8[i + 1]) << 6) | (0x3f & uint8[i + 2]); codePoints.push(codePoint); i += 3; } // 4-byte sequence (249 ~ ) else if( (codePoint & 0xF8) === 0xF0 ){ codePoint = ((0x07 & uint8[i]) << 18) | ((0x3f & uint8[i + 1]) << 12) | ((0x3f & uint8[i + 2]) << 6) | (0x3f & uint8[i + 3]); codePoints.push(codePoint); i += 4; } else { i += 1; } } let result_string = ""; while(codePoints.length > 0) { const chunk = codePoints.splice(0, UTF8_DECODE_CHUNK_SIZE); result_string += String.fromCodePoint(...chunk); } return result_string; } ] })(); })(); console.log('ABC-DEF-GGG'.camelCase); -
Cheny-chen revised this gist
Jan 29, 2020 . 1 changed file with 272 additions and 123 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,112 +1,247 @@ /** * Author: ChenyChen, JCloudYu * Create: 2020/01/29 **/ (async()=>{ "use strict"; const os = require('os'); const fs = require('fs'); const path = require('path'); const stream = require('stream'); const readline = require('readline'); const _env_conf = {source_dirs: [], tmpl: null, output: null}; const working_root = process.cwd(); // Read incoming arguments { const [, , basic_dir, tmpl_path, ...exec_args] = process.argv; exec_args.reverse(); if( !basic_dir ){ console.error("Source directory is not assigned!"); process.exit(1); return; } _env_conf.source_dirs.push(path.resolve(working_root, basic_dir)); if( !tmpl_path ){ console.error("Template script is not assigned!"); process.exit(1); return; } _env_conf.tmpl = path.resolve(working_root, tmpl_path); while( exec_args.length > 0 ){ const opt = exec_args.pop(); switch( opt ){ case "--dir": case "-d":{ const dpath = exec_args.pop() || ''; if( dpath ){ _env_conf.source_dirs.push(path.resolve(working_root, dpath)); } break; } case "--output": case "-o":{ const fpath = exec_args.pop() || ''; if( fpath ){ _env_conf.output = path.resolve(working_root, fpath); } break; } default:{ console.error(`Unknown option \`${ opt }\``); process.exit(1); return; } } } } // Expose collected arguments const {tmpl, source_dirs, output} = _env_conf; // Fetch template global.BuildTemplate = TemplateResolver; const template = (()=>{ try{ const script = require(tmpl); if( !(script instanceof TemplateResolver) ){ console.error("Given tmpl is not a valid template descriptor!"); process.exit(1); return null; } return script; } catch(e){ if( e.code === 'ENOENT' ){ console.error(`Template path \`${ tmpl }\` doesn't exist!`); process.exit(1); return null; } throw e; } })(); // Check source directories { for( const dir_path of source_dirs ){ try{ const dir_stat = fs.statSync(dir_path); if( !dir_stat.isDirectory() ){ console.error(`Source path \`${ dir_path }\` is not a directory!`); process.exit(1); return; } } catch(e){ if( e.code === "ENOENT" ){ console.error(`Source path \`${ dir_path }\` is not a directory!`); process.exit(1); return; } throw e; } try{ fs.accessSync(dir_path, fs.constants.R_OK | fs.constants.X_OK); } catch(e){ console.error(`Current user has no privilege to access directory \`${ dir_path }\`!`); process.exit(1); return; } } } // Create output stream const write_stream = (()=>{ if( !output ) return process.stdout; try{ return fs.createWriteStream(output, {mode: 0o644, flags: 'w'}); } catch(e){ return null; } })(); if( !write_stream ){ console.error(`Cannot create output stream to file \`${ output }\`!`); process.exit(1); return; } // Collect and parse all js script of the target folders const named_map = {}, unnamed_pool = []; for await( const dir_path of source_dirs ){ const arrayFiles = await ReadMainFolder(dir_path); for await ( const file of arrayFiles ){ await ParseFile(file, named_map, unnamed_pool); } } console.log(named_map, unnamed_pool); // Output generated script base on template script { const {statics, dynamics} = template; await WriteToStream(write_stream, statics[0]); for( let i = 1; i < statics.length; i++ ){ const dynamic_content = dynamics[i - 1]; if( typeof dynamic_content !== "string" ){ await WriteToStream(write_stream, '' + dynamic_content); await WriteToStream(write_stream, statics[i]); continue; } const important = dynamic_content[0] === '!'; const optional = dynamic_content[0] === '?'; const key = (important || optional) ? dynamic_content.substring(1) : dynamic_content; const code_segment = named_map[key]; if( code_segment !== undefined ){ await WriteToStream(write_stream, code_segment); } else if( important ){ console.error(`Missing required named block \`${ key }\``); process.exit(1); } else{ if( !optional ){ console.error(`Missm matching named block \`${ key }\``); } await WriteToStream(write_stream, ''); } await WriteToStream(write_stream, statics[i]); } for( const code_segment of unnamed_pool ){ await WriteToStream(write_stream, code_segment); } await CloseStream(write_stream); } function TemplateResolver(strings, ...dynamics) { if ( !(this instanceof TemplateResolver) ) { return new TemplateResolver(strings, ...dynamics); } this.statics = strings; this.dynamics = dynamics; } function WriteToStream(stream, data){ return new Promise((resolve, reject)=>{ const should_wait = stream.write(data, ()=>resolve(true)); if( !should_wait ){ reject(false); } }); } function CloseStream(stream){ return new Promise((resolve, reject)=>stream.end(resolve)); } async function ReadMainFolder(folder, arrayFiles = [], arrayFolder = []){ fs.readdirSync(folder, {withFileTypes: true}).forEach(filename=>{ @@ -120,56 +255,70 @@ const readline = require('readline'); }); if( arrayFolder.length > 0 ){ for await(const foldername of arrayFolder) { const temp = await ReadMainFolder(foldername, arrayFiles); arrayFiles.concat(temp); } } return arrayFiles } async function ReadLines(filePath) { return new Promise( async(resolve, reject) => { const output = new stream.PassThrough({ objectMode: true }); const readInterface = readline.createInterface({ input: fs.createReadStream(filePath), }); readInterface.on("line", line => { output.write(line); }); readInterface.on("close", () => { output.push(null); }); resolve(output); }) } async function ParseFile(filePath, named, unnamed){ return new Promise( async(resolve, reject) => { const readInterface = await ReadLines(filePath); let flag = false, splitByEqualsSign = [], temp_unamed = '', index=0; for await(let line of readInterface) { if( line.indexOf('//@export') > -1 ) { splitByEqualsSign = line.split('='); line = os.EOL; flag = true; } else if( line.indexOf('//@endexport') > -1 ){ line = line.replace('//@endexport', ''); flag = false; if( temp_unamed ){ unnamed.push(temp_unamed); temp_unamed = ''; } } if( flag ){ line = line + os.EOL; if( splitByEqualsSign[1] && !named.hasOwnProperty(splitByEqualsSign[1]) ){ named[splitByEqualsSign[1]] = ''; } else if( splitByEqualsSign.length > 1 && splitByEqualsSign[1] ){ named[splitByEqualsSign[1]] += line; } else if( line !== os.EOL ){ temp_unamed += line; } } } resolve(true); }) } })() .catch((e)=>setTimeout(()=>{throw e;})); -
Cheny-chen revised this gist
Jan 29, 2020 . 1 changed file with 166 additions and 62 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,71 +1,175 @@ /** * Author: ChenyChen, JCloudYu * Create: 2020/01/29 **/ const os = require('os'); const fs = require('fs'); const path = require('path'); const readline = require('readline'); (async()=>{ 'use strict'; if( process.argv.length < 3 ){ return console.error('** Missing Directory and Destination Filename!'); } const named_map = {}, unnamed_pool = []; const arrayFiles = await ReadMainFolder(process.argv[2]); for( const file of arrayFiles ){ ParseFile(file, named_map, unnamed_pool); } const output_map = [ { template:"./tmpl1.js", output:"./output.js" } ]; const TemplateResolver = global.BuildTemplate = function(strings, ...dynamics) { if ( this instanceof TemplateResolver) { this.statics = strings; this.dynamics = dynamics; return; } return new TemplateResolver(strings, ...dynamics); }; for(const {template:_tmpl_name, output:_out_name} of output_map) { try { const out_file = path.resolve(__dirname, _out_name); const write_stream = fs.createWriteStream(out_file, {flags: 'w'}); const tmpl_name = path.resolve(__dirname, _tmpl_name); const tmpl = require(tmpl_name); if ( tmpl instanceof TemplateResolver ) { const {statics, dynamics} = tmpl; await WriteToStream(write_stream, statics[0]); for ( let i=1; i<statics.length; i++ ) { const dynamic_content = dynamics[i-1]; if ( typeof dynamic_content !== "string" ) { await WriteToStream(write_stream, ''+dynamic_content); await WriteToStream(write_stream, statics[i]); continue; } const important = dynamic_content[0]==='!'; const optional = dynamic_content[0]==='?'; const key = (important||optional) ? dynamic_content.substring(1) : dynamic_content; const code_segment = named_map[key]; if ( code_segment !== undefined ) { await WriteToStream(write_stream, code_segment); } else if ( important ) { throw new Error(`Missing required named block \`${key}\``); } else { if ( !optional ) { console.error(`Mismatched named block \`${key}\``); } await WriteToStream(write_stream, ''); } await WriteToStream(write_stream, statics[i]); } } for ( const code_segment of unnamed_pool ) { await WriteToStream(write_stream, code_segment); } await CloseStream(write_stream); } catch(e) { console.error(e); } } function WriteToStream(stream, data) { return new Promise((resolve, reject)=>{ const should_wait = stream.write(data, ()=>resolve(true)); if ( !should_wait ) { reject(false); } }); } function CloseStream(stream) { return new Promise((resolve, reject)=>stream.end(resolve)); } async function ReadMainFolder(folder, arrayFiles = [], arrayFolder = []){ fs.readdirSync(folder, {withFileTypes: true}).forEach(filename=>{ if( filename.isDirectory() && !/^\..*|test*/.test(filename.name) ){ arrayFolder.push(path.join(folder, filename.name)); } if( !filename.isDirectory() && filename.name.indexOf('.js') > 0 ){ arrayFiles.push(path.join(folder, filename.name)); } }); if( arrayFolder.length > 0 ){ const temp = await ReadMainFolder(arrayFolder[0], arrayFiles); arrayFiles.concat(temp); } console.log('** The List of Files'); console.log(arrayFiles); return arrayFiles } function ParseFile(filePath, named, unnamed){ const readInterface = readline.createInterface({ input: fs.createReadStream(filePath), }); readInterface.on('line', generateContain); let flag = false, splitByEqualsSign = [], temp_unamed = ''; function generateContain(line){ if( line.indexOf('//@export') > -1 ){ splitByEqualsSign = line.split('='); line = os.EOL; flag = true; } else if( line.indexOf('//@endexport') > -1 ){ line = line.replace('//@endexport', ''); flag = false; if(temp_unamed){ unnamed.push(temp_unamed); temp_unamed = ''; } } if( flag ){ line = line.trim() + os.EOL; if( splitByEqualsSign[1] && !named.hasOwnProperty(splitByEqualsSign[1]) ){ named[splitByEqualsSign[1]] = ''; } else if( splitByEqualsSign.length > 1 && splitByEqualsSign[1] ){ named[splitByEqualsSign[1]] += line; } else if( line != os.EOL ){ temp_unamed += line; } } } } })(); -
Cheny-chen revised this gist
Jan 28, 2020 . 1 changed file with 2 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,14 +3,13 @@ const os = require('os'); const fs = require('fs'); const path = require('path'); const readline = require('readline'); if (process.argv.length < 3) { return console.error('** Missing Director and Destination Filename!'); } else if (process.argv.length < 4) { return console.error('** Missing Destination Filename!'); } const writeFile = fs.createWriteStream( process.argv[3], {flags: 'a'} ); -
Cheny-chen created this gist
Jan 28, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,72 @@ (async () => { 'use stric'; const os = require('os'); const fs = require('fs'); const path = require('path'); const colors = require('colors'); const readline = require('readline'); if (process.argv.length < 3) { return console.error('** Missing Director and Destination Filename!'.red); } else if (process.argv.length < 4) { return console.error('** Missing Destination Filename!'.red); } const writeFile = fs.createWriteStream( process.argv[3], {flags: 'a'} ); async function ReadMainFoler(folder, arrayFiles = [], arrayFolder = []) { fs.readdirSync(folder, { withFileTypes: true }).forEach(filename => { if ( filename.isDirectory() && ! /^\..*|test*/.test(filename.name) ) { arrayFolder.push( path.join(folder, filename.name) ); } if( !filename.isDirectory() && filename.name.indexOf('.js')>0 ) { arrayFiles.push( path.join(folder, filename.name) ); } }); if (arrayFolder.length > 0) { const temp = await ReadMainFoler(arrayFolder[0], arrayFiles); arrayFiles.concat(temp); } console.log('** The List of Files'.blue); console.log(arrayFiles); return arrayFiles } function AppendFiles(filePath) { const readInterface = readline.createInterface({ input: fs.createReadStream(filePath), }); readInterface.on('line', replaceWords); let flag = false; function replaceWords(line) { if (line.indexOf('//@export=') > -1) { flag = true; line = os.EOL; } else if (line.indexOf('//@endexport') > -1) { line = line.replace('//@endexport',''); writeFile.write(line + os.EOL); flag = false; } if(flag) { writeFile.write(line + os.EOL); } } } const arrayFiles = await ReadMainFoler( process.argv[2] ); for (const file of arrayFiles) { AppendFiles(file) } })()