| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- define [
- "utils/Modal"
- "pdf/CompiledView"
- "pdf/SyncButtonsView"
- "libs/latex-log-parser"
- "libs/jquery.storage"
- "libs/underscore"
- "libs/backbone"
- ], (Modal, CompiledView, SyncButtonsView, LogParser) ->
- class PdfManager
- templates:
- pdfLink: $("#pdfSideBarLinkTemplate").html()
- constructor: (@ide) ->
- _.extend @, Backbone.Events
- @createSyncButtons()
- @createPdfPanel()
- @ide.editor.aceEditor.commands.addCommand
- name: "compile",
- bindKey: win: "Ctrl-Enter", mac: "Command-Enter"
- exec: (editor) =>
- @refreshPdf()
- readOnly: true
- @ide.editor.aceEditor.commands.removeCommand "replace"
- createPdfPanel: () ->
- @view = new CompiledView manager: @, ide: @ide
- @view.on "dblclick", (e) => @syncToCode(e)
- @view.render()
- if $.localStorage("layout.pdf") == "flat"
- @switchToFlatView()
- else if $.localStorage("layout.pdf") == "split"
- @switchToSplitView()
- else if $(window).width() < 1024
- @switchToFlatView()
- else
- @switchToSplitView()
- createSyncButtons: () ->
- unless @ide.userSettings.pdfViewer == "native"
- @syncButtonsView = new SyncButtonsView(ide: @ide)
- @syncButtonsView.on "click:sync-code-to-pdf", () =>
- @syncToPdf()
- @syncButtonsView.on "click:sync-pdf-to-code", () =>
- @syncToCode()
- @syncButtonsView.hide()
- switchToFlatView: (options = {showPdf: false}) ->
- @teardownSplitView()
- @setupFlatView()
- @view.toggleFlatViewButton()
- if options.showPdf
- @ide.sideBarView.selectLink "pdf"
- @ide.mainAreaManager.change "pdf"
- @view.resize()
- switchToSplitView: () ->
- @teardownFlatView()
- @setupSplitView()
- @view.toggleSplitViewButton()
- @view.resize()
- @ide.editor.setIdeToEditorPanel()
- setupFlatView: () ->
- @teardownFlatView()
- @ide.editor.switchToFlatView()
- pdfLink = $(@templates.pdfLink)
- @ide.sideBarView.addLink
- identifier : "pdf"
- before : "history"
- element : pdfLink
- pdfLink.on "click", (e) => @showPdfPanel()
- @ide.mainAreaManager.addArea
- identifier: "pdf"
- element: @view.$el
- @view.resize()
- @view.undelegateEvents()
- @view.delegateEvents()
- teardownFlatView: () ->
- @ide.sideBarView.removeLink("pdf")
- @ide.mainAreaManager.removeArea("pdf")
- @view.afterSwitchView()
- setupSplitView: () ->
- @ide.editor.switchToSplitView()
- @ide.editor.rightPanel.append(
- @view.$el
- )
- @view.$el.show()
- @view.resize()
- @view.undelegateEvents()
- @view.delegateEvents()
- @ide.editor.$splitter.append(
- @syncButtonsView?.$el
- )
- setTimeout(@ide.layoutManager.resizeAllSplitters, 100)
- teardownSplitView: () ->
- @view.afterSwitchView()
- showPdfPanel: () ->
- @ide.sideBarView.selectLink 'pdf'
- @ide.mainAreaManager.change 'pdf'
- @view.resize()
- if !@view.hasPdf()
- @refreshPdf()
-
- showRawLogPanel: () ->
- @ide.mainAreaManager.change 'rawLog'
- refreshPdf: (opts) ->
- if @ide.project?
- @_refreshPdfWhenProjectIsLoaded(opts)
- else
- @ide.on "afterJoinProject", () =>
- @_refreshPdfWhenProjectIsLoaded(opts)
- _refreshPdfWhenProjectIsLoaded: (opts = {}) ->
- if !@ide.project.get("rootDoc_id")?
- new Modal
- title: "No root document selected"
- message: "First you need to choose a root document via the settings menu. This tells ShareLaTeX which file to run LaTeX on."
- buttons: [{
- text: "OK",
- class: "btn-primary"
- }]
- else if !@compiling
- @view.onCompiling()
- @syncButtonsView?.hide()
- @compiling = true
- @_doCompile opts, (error, status, outputFiles) =>
- @compiling = false
- @view.doneCompiling()
- @syncButtonsView?.show()
-
- if error?
- @view.updateLog(systemError: true)
- @view.unsetPdf()
- @view.showLog()
- else if status == "timedout"
- @view.updateLog(timedOut: true)
- @view.unsetPdf()
- @view.showLog()
- else if status == "autocompile-backoff"
- @view.showBeforeCompile()
- else
- pdfExists = (status == "success")
- @fetchLogAndUpdateView(pdfExists)
- if pdfExists
- @view.setPdf("/project/#{@ide.project_id}/output/output.pdf?cache_bust=#{Date.now()}")
- @view.showPdf()
- else
- @view.unsetPdf()
- @view.showLog()
- @syncButtonsView?.hide()
- if outputFiles?
- @view.showOutputFileDownloadLinks(outputFiles)
- _doCompile: (opts, callback = (error, status, outputFiles) ->) ->
- url = "/project/#{@ide.project_id}/compile"
- if opts.isAutoCompile
- url += "?auto_compile=true"
- $.ajax(
- url: url
- type: "POST"
- headers:
- "X-CSRF-Token": window.csrfToken
- contentType: "application/json; charset=utf-8"
- dataType: 'json'
- data: JSON.stringify settingsOverride:
- rootDoc_id: opts.rootDocOverride_id ? null
- success: (body, status, response) ->
- callback null, body.status, body.outputFiles
- error: (error) ->
- callback error
- )
- fetchLogAndUpdateView: (pdfExists) ->
- $.ajax(
- url: "/project/#{@ide.project_id}/output/output.log"
- success: (body, status, response) =>
- @parseLogAndUpdateView(pdfExists, body)
- error: () =>
- @view.updateLog(pdfExists: pdfExists, logExists: false)
- )
- parseLogAndUpdateView: (pdfExists, log) ->
- errors = LogParser.parse(log, ignoreDuplicates: true)
- lastCompileErrors = {}
- for error in errors.all
- error.file = @_normalizeFilePath(error.file)
- doc_id = @ide.fileTreeManager.getDocIdOfPath(error.file)
- if doc_id?
- lastCompileErrors[doc_id] ||= []
- lastCompileErrors[doc_id].push
- row: error.line - 1
- type: if error.level == "error" then "error" else "warning"
- text: error.message
- @ide.editor.compilationErrors = lastCompileErrors
- @ide.editor.refreshCompilationErrors()
- @view.updateLog(pdfExists: pdfExists, logExists: true, compileErrors: errors, rawLog: log)
- _normalizeFilePath: (path) ->
- path = path.replace(/^compiles\/[0-9a-f]{32}\/(\.\/)?/, "")
- path = path.replace(/^\/compile\//, "")
- rootDoc_id = @ide.project.get("rootDoc_id")
- if rootDoc_id?
- rootDocPath = @ide.fileTreeManager.getPathOfEntityId(rootDoc_id)
- if rootDocPath?
- rootDocDir = rootDocPath.split("/").slice(0,-1).map( (part) -> part + "/" ).join("")
- path = path.replace(/^\.\//, rootDocDir)
- return path
- downloadPdf: () ->
- @ide.mainAreaManager.setIframeSrc "/project/#{@ide.project_id}/output/output.pdf?popupDownload=true"
- deleteCachedFiles: () ->
- modal = new Modal
- title: "Clear cache?"
- message: "This will clear all hidden LaTeX files like .aux, .bbl, etc, from our compile server. You generally don't need to do this unless you're having trouble with references. Your project files will not be deleted or changed."
- buttons: [{
- text: "Cancel"
- }, {
- text: "Clear from cache",
- class: "btn-primary",
- close: false
- callback: ($button) =>
- $button.text("Clearing...")
- $button.prop("disabled", true)
- $.ajax({
- url: "/project/#{@ide.project_id}/output"
- type: "DELETE"
- headers:
- "X-CSRF-Token": window.csrfToken
- complete: () -> modal.remove()
- })
- }]
- syncToCode: (e) ->
- if !e?
- e = @view.getPdfPosition()
- return if !e?
- # It's not clear exactly where we should sync to if it was directly
- # clicked on, but a little bit down from the very top seems best.
- e.y = e.y + 80
- $.ajax {
- url: "/project/#{@ide.project_id}/sync/pdf"
- data:
- page: e.page + 1
- h: e.x.toFixed(2)
- v: e.y.toFixed(2)
- type: "GET"
- success: (response) =>
- data = JSON.parse(response)
- if data.code and data.code.length > 0
- file = data.code[0].file
- line = data.code[0].line
- @ide.fileTreeManager.openDocByPath(file, line)
- }
- syncToPdf: () ->
- entity_id = @ide.editor.getCurrentDocId()
- file = @ide.fileTreeManager.getPathOfEntityId(entity_id)
-
- # If the root file is folder/main.tex, then synctex sees the
- # path as folder/./main.tex
- rootFolderPath = @ide.fileTreeManager.getRootFolderPath()
- if rootFolderPath != ""
- file = file.replace(RegExp("^#{rootFolderPath}"), "#{rootFolderPath}/.")
- line = @ide.editor.getCurrentLine()
- column = @ide.editor.getCurrentColumn()
- $.ajax {
- url: "/project/#{@ide.project_id}/sync/code"
- data:
- file: file
- line: line + 1
- column: column
- type: "GET"
- success: (response) =>
- data = JSON.parse(response)
- @view.highlightInPdf(data.pdf or [])
- }
|