-
-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from shd101wyy/0.1.2
0.1.2
- Loading branch information
Showing
20 changed files
with
1,863 additions
and
679 deletions.
There are no files selected for viewing
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import * as path from "path" | ||
import * as fs from "fs" | ||
import {spawn} from "child_process" | ||
|
||
import * as utility from "./utility" | ||
|
||
export async function run(content:string, fileDirectoryPath:string, options:object):Promise<string> { | ||
const cmd = options['cmd'] | ||
let args = options['args'] || [] | ||
if (typeof(args) === 'string') { | ||
args = [args] | ||
} | ||
|
||
const savePath = path.resolve(fileDirectoryPath, Math.random().toString(36).substr(2, 9) + '_code_chunk') | ||
content = content.replace(/\u00A0/g, ' ') | ||
|
||
|
||
if (cmd.match(/python/) && (options['matplotlib'] || options['mpl'])) { | ||
content = ` | ||
# -*- coding: utf-8 -*- | ||
# modify default matplotlib pyplot show function | ||
try: | ||
import matplotlib | ||
matplotlib.use('Agg') # use Agg backend | ||
import matplotlib.pyplot as plt | ||
import sys | ||
def new_plt_show(): | ||
plt.savefig(sys.stdout, format="svg") | ||
plt.show = new_plt_show # override old one | ||
except Exception: | ||
pass | ||
# modify default mpld3 behavior | ||
try: | ||
import matplotlib.pyplot as plt, mpld3 | ||
import sys | ||
def new_mpld3_show(): | ||
fig = plt.gcf() # get current figure | ||
sys.stdout.write(mpld3.fig_to_html(fig)) | ||
mpld3.show = new_mpld3_show # override old one | ||
mpld3.display = new_mpld3_show | ||
except Exception: | ||
pass | ||
` + content | ||
options['output'] = 'html' // change to html so that svg can be rendered | ||
} | ||
|
||
await utility.writeFile(savePath, content) | ||
|
||
// check macros | ||
let findInputFileMacro = false | ||
args = args.map((arg)=> { | ||
if (arg === '{input_file}') { | ||
findInputFileMacro = true | ||
return savePath | ||
} else { | ||
return arg | ||
} | ||
}) | ||
|
||
if (!findInputFileMacro && !options['stdin']) { | ||
args.push(savePath) | ||
} | ||
|
||
return await new Promise<string>((resolve, reject)=> { | ||
const task = spawn(cmd, args, {cwd: fileDirectoryPath}) | ||
if (options['stdin']) // pass content as stdin | ||
task.stdin.write(content) | ||
task.stdin.end() | ||
|
||
const chunks = [] | ||
task.stdout.on('data', (chunk)=> { | ||
chunks.push(chunk) | ||
}) | ||
|
||
task.stderr.on('data', (chunk)=> { | ||
chunks.push(chunk) | ||
}) | ||
|
||
task.on('error', (error)=> { | ||
chunks.push(Buffer.from(error.toString(), 'utf-8')) | ||
}) | ||
|
||
task.on('close', ()=> { | ||
fs.unlink(savePath, ()=>{}) | ||
|
||
const data = Buffer.concat(chunks).toString() | ||
return resolve(data) | ||
}) | ||
}) | ||
} |
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
import * as path from "path" | ||
import {execFile} from "child_process" | ||
import * as mkdirp from "mkdirp" | ||
// ebook-convert is requied (calibre), which can be got from https://calibre-ebook.com/download | ||
// xpath http://www.w3schools.com/xsl/xpath_syntax.asp | ||
|
||
function processMetadata(config={}, args) { | ||
const title = config['title'] || 'No Title' | ||
args.push('--title', title) | ||
|
||
if (config['authors']) | ||
args.push('--authors', config['authors']) | ||
|
||
if (config['cover']) | ||
args.push('--cover', config['cover']) | ||
|
||
if (config['comment']) | ||
args.push('--comments', config['comments']) | ||
|
||
if (config['publisher']) | ||
args.push('--publisher', config['publisher']) | ||
|
||
if (config['book-producer']) | ||
args.push('--book-producer', config['book-producer']) | ||
|
||
if (config['pubdate']) | ||
args.push('--pubdate', config['pubdate']) | ||
|
||
if (config['language']) | ||
args.push('--language', config['language']) | ||
|
||
if (config['isbn']) | ||
args.push('--isbn', config['isbn']) | ||
|
||
if (config['tags']) | ||
args.push('--tags', config['tags']) | ||
|
||
if (config['series']) | ||
args.push('--series', config['series']) | ||
|
||
if (config['rating']) | ||
args.push('--rating', config['rating']) | ||
} | ||
|
||
function processAppearance(config={}, args) { | ||
if (config['asciiize']) | ||
args.push('--asciiize') | ||
|
||
if (config['base-font-size']) | ||
args.push('--base-font-size='+config['base-font-size']) | ||
|
||
if (config['disable-font-rescaling']) | ||
args.push('--disable-font-rescaling') | ||
|
||
if (config['line-height']) | ||
args.push('--line-height='+config['line-height']) | ||
|
||
let marginTop = 72, | ||
marginRight = 72, | ||
marginBottom = 72, | ||
marginLeft = 72 | ||
if (config['margin']) { | ||
const margin:Array<number>|number = config['margin'] | ||
if (margin instanceof Array) { | ||
if (margin.length === 1) { | ||
marginTop = margin[0] | ||
marginBottom = margin[0] | ||
marginLeft = margin[0] | ||
marginRight = margin[0] | ||
} else if (margin.length === 2) { | ||
marginTop = margin[0] | ||
marginBottom = margin[0] | ||
marginLeft = margin[1] | ||
marginRight = margin[1] | ||
} else if (margin.length == 4) { | ||
marginTop = margin[0] | ||
marginRight = margin[1] | ||
marginBottom = margin[2] | ||
marginLeft = margin[3] | ||
} | ||
} else if (typeof(margin) == 'number') { | ||
marginTop = margin | ||
marginBottom = margin | ||
marginLeft = margin | ||
marginRight = margin | ||
} | ||
} else { | ||
if (config['margin-top']) | ||
marginTop = config['margin-top'] | ||
if (config['margin-right']) | ||
marginRight = config['margin-right'] | ||
if (config['margin-bottom']) | ||
marginBottom = config['margin-bottom'] | ||
if (config['margin-left']) | ||
marginLeft = config['margin-left'] | ||
} | ||
|
||
args.push('--margin-top='+marginTop) | ||
args.push('--margin-bottom='+marginBottom) | ||
args.push('--margin-left='+marginLeft) | ||
args.push('--margin-right='+marginRight) | ||
} | ||
|
||
function processEPub(config={}, args) { | ||
if (config['no-default-epub-cover']) | ||
args.push('--no-default-epub-cover') | ||
if (config['no-svg-cover']) | ||
args.push('--no-svg-cover') | ||
if (config['pretty-print']) | ||
args.push('--pretty-print') | ||
} | ||
|
||
function processPDF(config={}, args) { | ||
if (config['paper-size']) | ||
args.push('--paper-size', config['paper-size']) | ||
|
||
if (config['default-font-size']) | ||
args.push('--pdf-default-font-size='+config['default-font-size']) | ||
|
||
if (config['header-template']) | ||
args.push('--pdf-header-template', config['header-template']) | ||
|
||
if (config['footer-template']) | ||
args.push('--pdf-footer-template', config['footer-template']) | ||
|
||
if (config['page-numbers']) | ||
args.push('--pdf-page-numbers') | ||
|
||
if (config['pretty-print']) | ||
args.push('--pretty-print') | ||
} | ||
|
||
/** | ||
* @param src: link to .html file | ||
* @param dest: output path | ||
*/ | ||
export function ebookConvert(src, dest, config={}) { | ||
return new Promise((resolve, reject)=> { | ||
// config | ||
const title = config['title'] || 'No Title' | ||
const authors = config['authors'] || null | ||
const publisher = config['publisher'] || null | ||
const bookProducer = config['book-producer'] || null | ||
const pubdate = config['pubdate'] || null | ||
const isbn = config['isbn'] || null | ||
const cover = config['cover'] || null | ||
const epubTOCAtEnd = config['epub-toc-at-end'] || false | ||
|
||
const args = [ src, | ||
dest, | ||
'--level1-toc', '//*[@ebook-toc-level-1]/@heading', | ||
'--level2-toc', '//*[@ebook-toc-level-2]/@heading', | ||
'--level3-toc', '//*[@ebook-toc-level-3]/@heading', | ||
'--no-chapters-in-toc' | ||
] | ||
|
||
processMetadata(config, args) | ||
processAppearance(config, args) | ||
|
||
// output formats | ||
const format = path.extname(dest).slice(1) | ||
if (format == 'epub') | ||
processEPub(config['epub'], args) | ||
else if (format == 'pdf') | ||
processPDF(config['pdf'], args) | ||
|
||
// arguments | ||
const ebookArgs = config['args'] || [] | ||
ebookArgs.forEach((arg)=> { | ||
args.push(arg) | ||
}) | ||
|
||
// ebook-convert will cause error if directory doesn't exist, | ||
// therefore I will create directory first. | ||
mkdirp(path.dirname(dest), (error, made)=> { | ||
execFile('ebook-convert', args, (error)=> { | ||
if (error) return reject(error.toString()) | ||
else return resolve() | ||
}) | ||
}) | ||
}) | ||
} | ||
|
||
/* | ||
# Example | ||
ebookConvert('test.html', 'test.epub', {title: 'hehe', authors: 'shd101wyy'}) | ||
.then(()=> {...}) | ||
.catch((error)=> {...}) | ||
### | ||
*/ |
Oops, something went wrong.