From 87e8eb0085e548152a9d96ec891494182a458dac Mon Sep 17 00:00:00 2001 From: purocean Date: Tue, 12 Jun 2018 11:24:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0docx=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++-- backend/convert.js | 30 +++++++++++++++++++++ backend/main.js | 45 +++++++++++++++++++++++--------- backend/run.js | 2 +- frontend/src/components/View.vue | 33 +++++++++++++++++++++-- frontend/src/pages/Home.vue | 5 +++- 6 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 backend/convert.js diff --git a/README.md b/README.md index a2287fb7..5e160494 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,9 @@ + 自动保存(加密文档不自动保存) + 列表自动补全 + 粘贴剪切板里面的图片 -+ 运行PHP,nodejs,Python 代码,代码块第一行需要包含以 `--run--` 字符串,示例见下面截图,当然需要安装相关环境 -+ 开启了HTML解析,可以直接在文档里面使用 HTML 代码 ++ 运行 PHP,nodejs,Python 代码,代码块第一行需要包含以 `--run--` 字符串,示例见下面截图,当然需要安装相关环境 ++ 开启了 HTML 解析,可以直接在文档里面使用 HTML 代码 ++ docx 格式导出,需要安装 [pandoc](https://pandoc.org/) + markdown 编辑器 [monaco-editor](https://github.com/Microsoft/monaco-editor) + markdown 解析 [markdown-it](https://github.com/markdown-it/markdown-it) + GitHub 风格样式和特性 [GitHub Flavored Markdown Spec](https://github.github.com/gfm/) diff --git a/backend/convert.js b/backend/convert.js new file mode 100644 index 00000000..575ae253 --- /dev/null +++ b/backend/convert.js @@ -0,0 +1,30 @@ +const os = require('os') +const fs = require('fs') +const spawn = require("child_process").spawn + +const convert = async (html, type) => { + try { + const path = os.tmpdir() + `/yn_convert_${new Date().getTime()}.${type}` + + return new Promise((resolve, reject) => { + const process = spawn('pandoc', ['-f', 'html', '-o', path]) + + process.on('close', (code) => { + try { + const data = fs.readFileSync(path) + fs.unlinkSync(path) + resolve(data) + } catch (error) { + reject(error) + } + }) + + process.stdin.write(html) + process.stdin.end() + }) + } catch (e) { + return e.message + } +} + +module.exports = convert diff --git a/backend/main.js b/backend/main.js index 98a29793..00b373d7 100644 --- a/backend/main.js +++ b/backend/main.js @@ -7,12 +7,13 @@ const plantuml = require('node-plantuml') const file = require('./file') const run = require('./run') +const convert = require('./convert') const result = (status = 'ok', message = '操作成功', data = null) => { return { status, message, data } } -const fileContent = (ctx, next) => { +const fileContent = async (ctx, next) => { if (ctx.path === '/api/file') { if (ctx.method === 'GET') { ctx.body = result('ok', '获取成功', file.read(ctx.query.path).toString()) @@ -29,11 +30,11 @@ const fileContent = (ctx, next) => { } else if (ctx.path === '/api/tree') { ctx.body = result('ok', '获取成功', file.tree()) } else { - next() + await next() } } -const attachment = (ctx, next) => { +const attachment = async (ctx, next) => { if (ctx.path.startsWith('/api/attachment')) { if (ctx.method === 'POST') { const path = ctx.request.body.fields.path @@ -44,11 +45,11 @@ const attachment = (ctx, next) => { ctx.body = file.read(ctx.query.path) } } else { - next() + await next() } } -const plantumlGen = (ctx, next) => { +const plantumlGen = async (ctx, next) => { if (ctx.path.startsWith('/api/plantuml/svg')) { const gen = plantuml.generate(ctx.query.data, {format: 'svg'}); @@ -60,16 +61,28 @@ const plantumlGen = (ctx, next) => { ctx.type = 'image/png' ctx.body = gen.out } else { - next() + await next() } } -const runCode = (ctx, next) => { +const runCode = async (ctx, next) => { if (ctx.path.startsWith('/api/run')) { const rst = run.runCode(ctx.request.body.language, ctx.request.body.code) ctx.body = result('ok', '运行成功', rst) } else { - next() + await next() + } +} + +const convertFile = async (ctx, next) => { + if (ctx.path.startsWith('/api/convert/')) { + const html = ctx.request.body.html + const type = ctx.request.body.type + + ctx.type = mime.getType(`file.${type}`) + ctx.body = await convert(html, type) + } else { + await next() } } @@ -79,11 +92,17 @@ app.use(static( path.join(__dirname, '../static') )) -app.use(bodyParser({multipart: true})) -app.use(async (ctx, next) => fileContent(ctx, next)) -app.use(async (ctx, next) => attachment(ctx, next)) -app.use(async (ctx, next) => plantumlGen(ctx, next)) -app.use(async (ctx, next) => runCode(ctx, next)) +app.use(bodyParser({ + multipart: true, + formLimit: '20mb', + jsonLimit: '20mb', + textLimit: '20mb' +})) +app.use(async (ctx, next) => await fileContent(ctx, next)) +app.use(async (ctx, next) => await attachment(ctx, next)) +app.use(async (ctx, next) => await plantumlGen(ctx, next)) +app.use(async (ctx, next) => await runCode(ctx, next)) +app.use(async (ctx, next) => await convertFile(ctx, next)) const port = 3000 app.listen(port) diff --git a/backend/run.js b/backend/run.js index 9e5e6d5a..8cbd9c9a 100644 --- a/backend/run.js +++ b/backend/run.js @@ -1,4 +1,4 @@ -const execFileSync = require("child_process").execFileSync; +const execFileSync = require("child_process").execFileSync const runCode = (language, code) => { try { diff --git a/frontend/src/components/View.vue b/frontend/src/components/View.vue index 684c4864..62cc7cff 100644 --- a/frontend/src/components/View.vue +++ b/frontend/src/components/View.vue @@ -1,5 +1,13 @@ @@ -133,6 +133,9 @@ export default { computed: { unsaved () { return this.value !== this.lastSaveContent + }, + fileName () { + return this.file ? this.file.name : null } } }