218 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| #!/usr/bin/env node
 | |
| 
 | |
| /**
 | |
|  * Marked CLI
 | |
|  * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)
 | |
|  */
 | |
| 
 | |
| import { promises } from 'fs';
 | |
| import { marked } from '../lib/marked.esm.js';
 | |
| 
 | |
| const { readFile, writeFile } = promises;
 | |
| 
 | |
| /**
 | |
|  * Man Page
 | |
|  */
 | |
| 
 | |
| async function help() {
 | |
|   const { spawn } = await import('child_process');
 | |
| 
 | |
|   const options = {
 | |
|     cwd: process.cwd(),
 | |
|     env: process.env,
 | |
|     setsid: false,
 | |
|     stdio: 'inherit'
 | |
|   };
 | |
| 
 | |
|   const { dirname, resolve } = await import('path');
 | |
|   const { fileURLToPath } = await import('url');
 | |
|   const __dirname = dirname(fileURLToPath(import.meta.url));
 | |
|   const helpText = await readFile(resolve(__dirname, '../man/marked.1.txt'), 'utf8');
 | |
| 
 | |
|   // eslint-disable-next-line promise/param-names
 | |
|   await new Promise(res => {
 | |
|     spawn('man', [resolve(__dirname, '../man/marked.1')], options)
 | |
|       .on('error', () => {
 | |
|         console.log(helpText);
 | |
|       })
 | |
|       .on('close', res);
 | |
|   });
 | |
| }
 | |
| 
 | |
| async function version() {
 | |
|   const { createRequire } = await import('module');
 | |
|   const require = createRequire(import.meta.url);
 | |
|   const pkg = require('../package.json');
 | |
|   console.log(pkg.version);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Main
 | |
|  */
 | |
| 
 | |
| async function main(argv) {
 | |
|   const files = [];
 | |
|   const options = {};
 | |
|   let input;
 | |
|   let output;
 | |
|   let string;
 | |
|   let arg;
 | |
|   let tokens;
 | |
|   let opt;
 | |
| 
 | |
|   function getarg() {
 | |
|     let arg = argv.shift();
 | |
| 
 | |
|     if (arg.indexOf('--') === 0) {
 | |
|       // e.g. --opt
 | |
|       arg = arg.split('=');
 | |
|       if (arg.length > 1) {
 | |
|         // e.g. --opt=val
 | |
|         argv.unshift(arg.slice(1).join('='));
 | |
|       }
 | |
|       arg = arg[0];
 | |
|     } else if (arg[0] === '-') {
 | |
|       if (arg.length > 2) {
 | |
|         // e.g. -abc
 | |
|         argv = arg.substring(1).split('').map(function(ch) {
 | |
|           return '-' + ch;
 | |
|         }).concat(argv);
 | |
|         arg = argv.shift();
 | |
|       } else {
 | |
|         // e.g. -a
 | |
|       }
 | |
|     } else {
 | |
|       // e.g. foo
 | |
|     }
 | |
| 
 | |
|     return arg;
 | |
|   }
 | |
| 
 | |
|   while (argv.length) {
 | |
|     arg = getarg();
 | |
|     switch (arg) {
 | |
|       case '-o':
 | |
|       case '--output':
 | |
|         output = argv.shift();
 | |
|         break;
 | |
|       case '-i':
 | |
|       case '--input':
 | |
|         input = argv.shift();
 | |
|         break;
 | |
|       case '-s':
 | |
|       case '--string':
 | |
|         string = argv.shift();
 | |
|         break;
 | |
|       case '-t':
 | |
|       case '--tokens':
 | |
|         tokens = true;
 | |
|         break;
 | |
|       case '-h':
 | |
|       case '--help':
 | |
|         return await help();
 | |
|       case '-v':
 | |
|       case '--version':
 | |
|         return await version();
 | |
|       default:
 | |
|         if (arg.indexOf('--') === 0) {
 | |
|           opt = camelize(arg.replace(/^--(no-)?/, ''));
 | |
|           if (!marked.defaults.hasOwnProperty(opt)) {
 | |
|             continue;
 | |
|           }
 | |
|           if (arg.indexOf('--no-') === 0) {
 | |
|             options[opt] = typeof marked.defaults[opt] !== 'boolean'
 | |
|               ? null
 | |
|               : false;
 | |
|           } else {
 | |
|             options[opt] = typeof marked.defaults[opt] !== 'boolean'
 | |
|               ? argv.shift()
 | |
|               : true;
 | |
|           }
 | |
|         } else {
 | |
|           files.push(arg);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   async function getData() {
 | |
|     if (!input) {
 | |
|       if (files.length <= 2) {
 | |
|         if (string) {
 | |
|           return string;
 | |
|         }
 | |
|         return await getStdin();
 | |
|       }
 | |
|       input = files.pop();
 | |
|     }
 | |
|     return await readFile(input, 'utf8');
 | |
|   }
 | |
| 
 | |
|   const data = await getData();
 | |
| 
 | |
|   const html = tokens
 | |
|     ? JSON.stringify(marked.lexer(data, options), null, 2)
 | |
|     : marked(data, options);
 | |
| 
 | |
|   if (output) {
 | |
|     return await writeFile(output, html);
 | |
|   }
 | |
| 
 | |
|   process.stdout.write(html + '\n');
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Helpers
 | |
|  */
 | |
| 
 | |
| function getStdin() {
 | |
|   return new Promise((resolve, reject) => {
 | |
|     const stdin = process.stdin;
 | |
|     let buff = '';
 | |
| 
 | |
|     stdin.setEncoding('utf8');
 | |
| 
 | |
|     stdin.on('data', function(data) {
 | |
|       buff += data;
 | |
|     });
 | |
| 
 | |
|     stdin.on('error', function(err) {
 | |
|       reject(err);
 | |
|     });
 | |
| 
 | |
|     stdin.on('end', function() {
 | |
|       resolve(buff);
 | |
|     });
 | |
| 
 | |
|     stdin.resume();
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @param {string} text
 | |
|  */
 | |
| function camelize(text) {
 | |
|   return text.replace(/(\w)-(\w)/g, function(_, a, b) {
 | |
|     return a + b.toUpperCase();
 | |
|   });
 | |
| }
 | |
| 
 | |
| function handleError(err) {
 | |
|   if (err.code === 'ENOENT') {
 | |
|     console.error('marked: output to ' + err.path + ': No such directory');
 | |
|     return process.exit(1);
 | |
|   }
 | |
|   throw err;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Expose / Entry Point
 | |
|  */
 | |
| 
 | |
| process.title = 'marked';
 | |
| main(process.argv.slice()).then(code => {
 | |
|   process.exit(code || 0);
 | |
| }).catch(err => {
 | |
|   handleError(err);
 | |
| });
 |