@@ -6,6 +6,7 @@ const markdownpdf = require('markdown-pdf')
66const shortId = require ( 'shortid' )
77const querystring = require ( 'querystring' )
88const moment = require ( 'moment' )
9+ const { Pandoc } = require ( '@hackmd/pandoc.js' )
910
1011const config = require ( '../config' )
1112const logger = require ( '../logger' )
@@ -99,6 +100,63 @@ function actionPDF (req, res, note) {
99100 } )
100101}
101102
103+ const outputFormats = {
104+ asciidoc : 'text/plain' ,
105+ context : 'application/x-latex' ,
106+ epub : 'application/epub+zip' ,
107+ epub3 : 'application/epub+zip' ,
108+ latex : 'application/x-latex' ,
109+ odt : 'application/vnd.oasis.opendocument.text' ,
110+ pdf : 'application/pdf' ,
111+ rst : 'text/plain' ,
112+ rtf : 'application/rtf' ,
113+ textile : 'text/plain' ,
114+ docx : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
115+ }
116+
117+ async function actionPandoc ( req , res , note ) {
118+ var url = config . serverURL || 'http://' + req . get ( 'host' )
119+ var body = note . content
120+ var extracted = Note . extractMeta ( body )
121+ var content = extracted . markdown
122+ var title = Note . decodeTitle ( note . title )
123+
124+ if ( ! fs . existsSync ( config . tmpPath ) ) {
125+ fs . mkdirSync ( config . tmpPath )
126+ }
127+ const pandoc = new Pandoc ( )
128+
129+ var path = config . tmpPath + '/' + Date . now ( )
130+ content = content . replace ( / \] \( \/ / g, '](' + url + '/' )
131+
132+ // TODO: check export type
133+ const { exportType } = req . query
134+
135+ try {
136+ // TODO: timeout rejection
137+
138+ await pandoc . convertToFile ( content , 'markdown' , exportType , path , [
139+ '--metadata' , `title=${ title } `
140+ ] )
141+
142+ var stream = fs . createReadStream ( path )
143+ var filename = title
144+ // Be careful of special characters
145+ filename = encodeURIComponent ( filename )
146+ // Ideally this should strip them
147+ res . setHeader ( 'Content-disposition' , `attachment; filename="${ filename } .${ exportType } "` )
148+ res . setHeader ( 'Cache-Control' , 'private' )
149+ res . setHeader ( 'Content-Type' , `${ outputFormats [ exportType ] } ; charset=UTF-8` )
150+ res . setHeader ( 'X-Robots-Tag' , 'noindex, nofollow' ) // prevent crawling
151+ stream . pipe ( res )
152+ } catch ( err ) {
153+ // TODO: handle error
154+ res . json ( {
155+ message : err . message
156+ } )
157+ }
158+ }
159+
102160function actionGist ( req , res , note ) {
103161 const data = {
104162 client_id : config . github . clientID ,
@@ -161,4 +219,5 @@ exports.actionDownload = actionDownload
161219exports . actionInfo = actionInfo
162220exports . actionPDF = actionPDF
163221exports . actionGist = actionGist
222+ exports . actionPandoc = actionPandoc
164223exports . actionRevision = actionRevision
0 commit comments