PdfManager.coffee 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. define [
  2. "utils/Modal"
  3. "pdf/CompiledView"
  4. "libs/latex-log-parser"
  5. "libs/jquery.storage"
  6. "libs/underscore"
  7. "libs/backbone"
  8. ], (Modal, CompiledView, LogParser) ->
  9. class PdfManager
  10. templates:
  11. pdfLink: $("#pdfSideBarLinkTemplate").html()
  12. constructor: (@ide) ->
  13. _.extend @, Backbone.Events
  14. @createPdfPanel()
  15. @ide.editor.aceEditor.commands.addCommand
  16. name: "compile",
  17. bindKey: win: "Ctrl-Enter", mac: "Command-Enter"
  18. exec: (editor) =>
  19. @refreshPdf()
  20. readOnly: true
  21. @ide.editor.aceEditor.commands.removeCommand "replace"
  22. createPdfPanel: () ->
  23. @view = new CompiledView manager: @, ide: @ide
  24. @view.render()
  25. if $.localStorage("layout.pdf") == "flat"
  26. @switchToFlatView()
  27. else if $.localStorage("layout.pdf") == "split"
  28. @switchToSplitView()
  29. else if $(window).width() < 1024
  30. @switchToFlatView()
  31. else
  32. @switchToSplitView()
  33. switchToFlatView: (options = {showPdf: false}) ->
  34. @teardownSplitView()
  35. @setupFlatView()
  36. @view.toggleFlatViewButton()
  37. if options.showPdf
  38. @ide.sideBarView.selectLink "pdf"
  39. @ide.mainAreaManager.change "pdf"
  40. @view.resize()
  41. switchToSplitView: () ->
  42. @teardownFlatView()
  43. @setupSplitView()
  44. @view.toggleSplitViewButton()
  45. @view.resize()
  46. @ide.editor.setIdeToEditorPanel()
  47. setupFlatView: () ->
  48. @teardownFlatView()
  49. @ide.editor.switchToFlatView()
  50. pdfLink = $(@templates.pdfLink)
  51. @ide.sideBarView.addLink
  52. identifier : "pdf"
  53. before : "history"
  54. element : pdfLink
  55. pdfLink.on "click", (e) => @showPdfPanel()
  56. @ide.mainAreaManager.addArea
  57. identifier: "pdf"
  58. element: @view.$el
  59. @view.resize()
  60. @view.undelegateEvents()
  61. @view.delegateEvents()
  62. teardownFlatView: () ->
  63. @ide.sideBarView.removeLink("pdf")
  64. @ide.mainAreaManager.removeArea("pdf")
  65. @view.afterSwitchView()
  66. setupSplitView: () ->
  67. @ide.editor.switchToSplitView()
  68. @ide.editor.rightPanel.append(
  69. @view.$el
  70. )
  71. @view.$el.show()
  72. @view.resize()
  73. @view.undelegateEvents()
  74. @view.delegateEvents()
  75. setTimeout(@ide.layoutManager.resizeAllSplitters, 100)
  76. teardownSplitView: () ->
  77. @view.afterSwitchView()
  78. showPdfPanel: () ->
  79. @ide.sideBarView.selectLink 'pdf'
  80. @ide.mainAreaManager.change 'pdf'
  81. @view.resize()
  82. if !@view.hasPdf()
  83. @refreshPdf()
  84. showRawLogPanel: () ->
  85. @ide.mainAreaManager.change 'rawLog'
  86. refreshPdf: (opts) ->
  87. if @ide.project?
  88. @_refreshPdfWhenProjectIsLoaded(opts)
  89. else
  90. @ide.on "afterJoinProject", () =>
  91. @_refreshPdfWhenProjectIsLoaded(opts)
  92. _refreshPdfWhenProjectIsLoaded: (opts) ->
  93. doneCompiling = _.once =>
  94. @compiling = false
  95. @view.doneCompiling()
  96. setTimeout doneCompiling, 1000 * 60
  97. if !@ide.project.get("rootDoc_id")?
  98. new Modal
  99. title: "No root document selected"
  100. message: "First you need to choose a root document via the settings menu. This tells ShareLaTeX which file to run LaTeX on."
  101. buttons: [{
  102. text: "OK",
  103. class: "btn-primary"
  104. }]
  105. else if !@compiling
  106. @view.onCompiling()
  107. @compiling = true
  108. @ide.socket.emit "pdfProject", opts, (err, pdfExists, outputFiles) =>
  109. @compiling = false
  110. doneCompiling()
  111. if err? and err.rateLimitHit
  112. @view.showBeforeCompile()
  113. else
  114. if err?
  115. @view.updateLog(pdfExists: false, logExists: false)
  116. else
  117. @fetchLogAndUpdateView(pdfExists)
  118. if pdfExists
  119. @view.setPdf("/project/#{@ide.project_id}/output/output.pdf?cache_bust=#{Date.now()}")
  120. @view.showPdf()
  121. else
  122. @view.unsetPdf()
  123. @view.showLog()
  124. if outputFiles?
  125. @view.showOutputFileDownloadLinks(outputFiles)
  126. fetchLogAndUpdateView: (pdfExists) ->
  127. $.ajax(
  128. url: "/project/#{@ide.project_id}/output/output.log"
  129. success: (body, status, response) =>
  130. @parseLogAndUpdateView(pdfExists, body)
  131. error: () =>
  132. @view.updateLog(pdfExists: pdfExists, logExists: false)
  133. )
  134. parseLogAndUpdateView: (pdfExists, log) ->
  135. errors = LogParser.parse(log, ignoreDuplicates: true)
  136. lastCompileErrors = {}
  137. for error in errors.all
  138. error.file = @_normalizeFilePath(error.file)
  139. doc_id = @ide.fileTreeManager.getDocIdOfPath(error.file)
  140. if doc_id?
  141. lastCompileErrors[doc_id] ||= []
  142. lastCompileErrors[doc_id].push
  143. row: error.line - 1
  144. type: if error.level == "error" then "error" else "warning"
  145. text: error.message
  146. @ide.editor.compilationErrors = lastCompileErrors
  147. @ide.editor.refreshCompilationErrors()
  148. @view.updateLog(pdfExists: pdfExists, logExists: true, compileErrors: errors, rawLog: log)
  149. _normalizeFilePath: (path) ->
  150. path = path.replace(/^compiles\/[0-9a-f]{32}\/(\.\/)?/, "")
  151. path = path.replace(/^\/compile\//, "")
  152. rootDoc_id = @ide.project.get("rootDoc_id")
  153. if rootDoc_id?
  154. rootDocPath = @ide.fileTreeManager.getPathOfEntityId(rootDoc_id)
  155. if rootDocPath?
  156. rootDocDir = rootDocPath.split("/").slice(0,-1).map( (part) -> part + "/" ).join("")
  157. path = path.replace(/^\.\//, rootDocDir)
  158. return path
  159. downloadPdf: () ->
  160. @ide.mainAreaManager.setIframeSrc "/project/#{@ide.project_id}/output/output.pdf?popupDownload=true"