Inject [draft] option to documentclass if draft option is passed

This commit is contained in:
James Allen
2016-02-02 14:26:14 +00:00
parent 03b75b12cf
commit d96605d5e8
6 changed files with 151 additions and 37 deletions

View File

@@ -11,6 +11,7 @@ module.exports = CompileController =
RequestParser.parse req.body, (error, request) -> RequestParser.parse req.body, (error, request) ->
return next(error) if error? return next(error) if error?
request.project_id = req.params.project_id request.project_id = req.params.project_id
logger.log {request}, "got request"
ProjectPersistenceManager.markProjectAsJustAccessed request.project_id, (error) -> ProjectPersistenceManager.markProjectAsJustAccessed request.project_id, (error) ->
return next(error) if error? return next(error) if error?
CompileManager.doCompile request, (error, outputFiles = []) -> CompileManager.doCompile request, (error, outputFiles = []) ->

View File

@@ -8,6 +8,7 @@ logger = require "logger-sharelatex"
Metrics = require "./Metrics" Metrics = require "./Metrics"
child_process = require "child_process" child_process = require "child_process"
CommandRunner = require(Settings.clsi?.commandRunner or "./CommandRunner") CommandRunner = require(Settings.clsi?.commandRunner or "./CommandRunner")
DraftModeManager = require "./DraftModeManager"
fs = require("fs") fs = require("fs")
module.exports = CompileManager = module.exports = CompileManager =
@@ -20,24 +21,32 @@ module.exports = CompileManager =
return callback(error) if error? return callback(error) if error?
logger.log project_id: request.project_id, time_taken: Date.now() - timer.start, "written files to disk" logger.log project_id: request.project_id, time_taken: Date.now() - timer.start, "written files to disk"
timer.done() timer.done()
timer = new Metrics.Timer("run-compile") injectDraftModeIfRequired = (callback) ->
Metrics.inc("compiles") if request.draft
LatexRunner.runLatex request.project_id, { DraftModeManager.injectDraftMode Path.join(compileDir, request.rootResourcePath), callback
directory: compileDir else
mainFile: request.rootResourcePath callback()
compiler: request.compiler
timeout: request.timeout injectDraftModeIfRequired (error) ->
image: request.imageName
}, (error) ->
return callback(error) if error? return callback(error) if error?
logger.log project_id: request.project_id, time_taken: Date.now() - timer.start, "done compile" timer = new Metrics.Timer("run-compile")
timer.done() Metrics.inc("compiles")
LatexRunner.runLatex request.project_id, {
OutputFileFinder.findOutputFiles request.resources, compileDir, (error, outputFiles) -> directory: compileDir
mainFile: request.rootResourcePath
compiler: request.compiler
timeout: request.timeout
image: request.imageName
}, (error) ->
return callback(error) if error? return callback(error) if error?
OutputCacheManager.saveOutputFiles outputFiles, compileDir, (error, newOutputFiles) -> logger.log project_id: request.project_id, time_taken: Date.now() - timer.start, "done compile"
callback null, newOutputFiles timer.done()
OutputFileFinder.findOutputFiles request.resources, compileDir, (error, outputFiles) ->
return callback(error) if error?
OutputCacheManager.saveOutputFiles outputFiles, compileDir, (error, newOutputFiles) ->
callback null, newOutputFiles
clearProject: (project_id, _callback = (error) ->) -> clearProject: (project_id, _callback = (error) ->) ->
callback = (error) -> callback = (error) ->

View File

@@ -0,0 +1,21 @@
fs = require "fs"
logger = require "logger-sharelatex"
module.exports = DraftModeManager =
injectDraftMode: (filename, callback = (error) ->) ->
fs.readFile filename, "utf8", (error, content) ->
return callback(error) if error?
modified_content = DraftModeManager._injectDraftOption content
logger.log {
content: content.slice(0,1024), # \documentclass is normally v near the top
modified_content: modified_content.slice(0,1024),
filename
}, "injected draft class"
fs.writeFile filename, modified_content, callback
_injectDraftOption: (content) ->
content
# With existing options (must be first, otherwise both are applied)
.replace(/\\documentclass\[/, "\\documentclass[draft,")
# Without existing options
.replace(/\\documentclass\{/, "\\documentclass[draft]{")

View File

@@ -24,6 +24,10 @@ module.exports = RequestParser =
response.imageName = @_parseAttribute "imageName", response.imageName = @_parseAttribute "imageName",
compile.options.imageName, compile.options.imageName,
type: "string" type: "string"
response.draft = @_parseAttribute "draft",
compile.options.draft,
default: false,
type: "boolean"
if response.timeout > RequestParser.MAX_TIMEOUT if response.timeout > RequestParser.MAX_TIMEOUT
response.timeout = RequestParser.MAX_TIMEOUT response.timeout = RequestParser.MAX_TIMEOUT

View File

@@ -17,6 +17,7 @@ describe "CompileManager", ->
"logger-sharelatex": @logger = { log: sinon.stub() } "logger-sharelatex": @logger = { log: sinon.stub() }
"child_process": @child_process = {} "child_process": @child_process = {}
"./CommandRunner": @CommandRunner = {} "./CommandRunner": @CommandRunner = {}
"./DraftModeManager": @DraftModeManager = {}
"fs": @fs = {} "fs": @fs = {}
@callback = sinon.stub() @callback = sinon.stub()
@@ -51,31 +52,48 @@ describe "CompileManager", ->
@LatexRunner.runLatex = sinon.stub().callsArg(2) @LatexRunner.runLatex = sinon.stub().callsArg(2)
@OutputFileFinder.findOutputFiles = sinon.stub().callsArgWith(2, null, @output_files) @OutputFileFinder.findOutputFiles = sinon.stub().callsArgWith(2, null, @output_files)
@OutputCacheManager.saveOutputFiles = sinon.stub().callsArgWith(2, null, @build_files) @OutputCacheManager.saveOutputFiles = sinon.stub().callsArgWith(2, null, @build_files)
@CompileManager.doCompile @request, @callback @DraftModeManager.injectDraftMode = sinon.stub().callsArg(1)
describe "normally", ->
beforeEach ->
@CompileManager.doCompile @request, @callback
it "should write the resources to disk", -> it "should write the resources to disk", ->
@ResourceWriter.syncResourcesToDisk @ResourceWriter.syncResourcesToDisk
.calledWith(@project_id, @resources, @compileDir) .calledWith(@project_id, @resources, @compileDir)
.should.equal true .should.equal true
it "should run LaTeX", -> it "should run LaTeX", ->
@LatexRunner.runLatex @LatexRunner.runLatex
.calledWith(@project_id, { .calledWith(@project_id, {
directory: @compileDir directory: @compileDir
mainFile: @rootResourcePath mainFile: @rootResourcePath
compiler: @compiler compiler: @compiler
timeout: @timeout timeout: @timeout
image: @image image: @image
}) })
.should.equal true .should.equal true
it "should find the output files", -> it "should find the output files", ->
@OutputFileFinder.findOutputFiles @OutputFileFinder.findOutputFiles
.calledWith(@resources, @compileDir) .calledWith(@resources, @compileDir)
.should.equal true .should.equal true
it "should return the output files", -> it "should return the output files", ->
@callback.calledWith(null, @build_files).should.equal true @callback.calledWith(null, @build_files).should.equal true
it "should not inject draft mode by default", ->
@DraftModeManager.injectDraftMode.called.should.equal false
describe "with draft mode", ->
beforeEach ->
@request.draft = true
@CompileManager.doCompile @request, @callback
it "should inject the draft mode header", ->
@DraftModeManager.injectDraftMode
.calledWith(@compileDir + "/" + @rootResourcePath)
.should.equal true
describe "clearProject", -> describe "clearProject", ->
describe "succesfully", -> describe "succesfully", ->

View File

@@ -0,0 +1,61 @@
SandboxedModule = require('sandboxed-module')
sinon = require('sinon')
require('chai').should()
modulePath = require('path').join __dirname, '../../../app/js/DraftModeManager'
describe 'DraftModeManager', ->
beforeEach ->
@DraftModeManager = SandboxedModule.require modulePath, requires:
"fs": @fs = {}
"logger-sharelatex": @logger = {log: () ->}
describe "_injectDraftOption", ->
it "should add draft option into documentclass with existing options", ->
@DraftModeManager
._injectDraftOption('''
\\documentclass[a4paper,foo=bar]{article}
''')
.should.equal('''
\\documentclass[draft,a4paper,foo=bar]{article}
''')
it "should add draft option into documentclass with no options", ->
@DraftModeManager
._injectDraftOption('''
\\documentclass{article}
''')
.should.equal('''
\\documentclass[draft]{article}
''')
describe "injectDraftMode", ->
beforeEach ->
@filename = "/mock/filename.tex"
@callback = sinon.stub()
content = '''
\\documentclass{article}
\\begin{document}
Hello world
\\end{document}
'''
@fs.readFile = sinon.stub().callsArgWith(2, null, content)
@fs.writeFile = sinon.stub().callsArg(2)
@DraftModeManager.injectDraftMode @filename, @callback
it "should read the file", ->
@fs.readFile
.calledWith(@filename, "utf8")
.should.equal true
it "should write the modified file", ->
@fs.writeFile
.calledWith(@filename, """
\\documentclass[draft]{article}
\\begin{document}
Hello world
\\end{document}
""")
.should.equal true
it "should call the callback", ->
@callback.called.should.equal true