mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-27 02:51:57 +02:00
Get synctex working
This commit is contained in:
@@ -27,4 +27,24 @@ div.full-size(
|
||||
)
|
||||
|
||||
.ui-layout-east
|
||||
include ./pdf
|
||||
include ./pdf
|
||||
|
||||
.ui-layout-resizer-controls.synctex-controls(
|
||||
ng-show="!!pdf.url"
|
||||
ng-controller="PdfSynctexController"
|
||||
)
|
||||
a.btn.btn-default.btn-xs(
|
||||
tooltip="Go to code location in PDF"
|
||||
tooltip-placement="right"
|
||||
tooltip-append-to-body="true"
|
||||
ng-click="syncToPdf()"
|
||||
)
|
||||
i.fa.fa-long-arrow-right
|
||||
br
|
||||
a.btn.btn-default.btn-xs(
|
||||
tooltip-html-unsafe="Go to PDF location in code<br/>(or double click PDF)"
|
||||
tooltip-placement="right"
|
||||
tooltip-append-to-body="true"
|
||||
ng-click="syncToCode()"
|
||||
)
|
||||
i.fa.fa-long-arrow-left
|
||||
@@ -33,6 +33,9 @@ div.full-size(ng-controller="PdfController")
|
||||
pdf-src="pdf.url"
|
||||
key="project_id"
|
||||
resize-on="layout:main:resize,layout:pdf:resize"
|
||||
highlights="pdf.highlights"
|
||||
position="pdf.position"
|
||||
dbl-click-callback="syncToCode"
|
||||
)
|
||||
|
||||
.pdf-uncompiled(ng-show="pdf.uncompiled && !pdf.compiling")
|
||||
|
||||
@@ -12,6 +12,7 @@ define [
|
||||
onresize: () =>
|
||||
console.log "Triggering", "layout:#{name}:resize", name
|
||||
scope.$broadcast "layout:#{name}:resize"
|
||||
repositionControls()
|
||||
#maskIframesOnResize: true
|
||||
|
||||
# Restore previously recorded state
|
||||
@@ -28,4 +29,13 @@ define [
|
||||
# Save state when exiting
|
||||
$(window).unload () ->
|
||||
$.localStorage("layout.#{name}", element.layout().readState())
|
||||
|
||||
repositionControls = () ->
|
||||
state = element.layout().readState()
|
||||
if state.east?
|
||||
element.find(".ui-layout-resizer-controls").css({
|
||||
position: "absolute"
|
||||
right: state.east.size
|
||||
"z-index": 10
|
||||
})
|
||||
}
|
||||
@@ -95,6 +95,10 @@ define [
|
||||
parts = path.split("/")
|
||||
name = parts.shift()
|
||||
rest = parts.join("/")
|
||||
|
||||
if name == "."
|
||||
return @_findEntityByPathInFolder(folder, rest)
|
||||
|
||||
for entity in folder.children
|
||||
if entity.name == name
|
||||
if rest == ""
|
||||
@@ -115,6 +119,26 @@ define [
|
||||
if entity.children?
|
||||
@_forEachEntityInFolder(entity, callback)
|
||||
|
||||
getEntityPath: (entity) ->
|
||||
@_getEntityPathInFolder @$scope.rootFolder, entity
|
||||
|
||||
_getEntityPathInFolder: (folder, entity) ->
|
||||
for child in folder.children or []
|
||||
if child == entity
|
||||
return entity.name
|
||||
else if child.type == "folder"
|
||||
path = @_getEntityPathInFolder(child, entity)
|
||||
if path?
|
||||
return child.name + "/" + path
|
||||
return null
|
||||
|
||||
getRootDocDirname: () ->
|
||||
rootDoc = @findEntityById @$scope.project.rootDoc_id
|
||||
return if !rootDoc?
|
||||
path = @getEntityPath(rootDoc)
|
||||
return if !path?
|
||||
return path.split("/").slice(0, -1).join("/")
|
||||
|
||||
# forEachFolder: (callback) ->
|
||||
# @forEachEntity (entity) ->
|
||||
# if entity.type == "folder"
|
||||
|
||||
@@ -16,3 +16,5 @@ define [
|
||||
rawLog: ""
|
||||
view: null # 'pdf' 'logs'
|
||||
showRawLog: false
|
||||
highlights: []
|
||||
position: null
|
||||
|
||||
@@ -2,7 +2,7 @@ define [
|
||||
"base"
|
||||
"libs/latex-log-parser"
|
||||
], (App, LogParser) ->
|
||||
App.controller "PdfController", ["$scope", "$http", "ide", "$modal", ($scope, $http, ide, $modal) ->
|
||||
App.controller "PdfController", ["$scope", "$http", "ide", "$modal", "synctex", ($scope, $http, ide, $modal, synctex) ->
|
||||
autoCompile = true
|
||||
$scope.$on "doc:opened", () ->
|
||||
return if !autoCompile
|
||||
@@ -59,8 +59,7 @@ define [
|
||||
|
||||
$scope.pdf.logEntryAnnotations = {}
|
||||
for entry in logEntries.all
|
||||
entry.file = entry.file.replace(/^(.*)\/compiles\/[0-9a-f]{24}\/(\.\/)?/, "")
|
||||
entry.file = entry.file.replace(/^\/compile\//, "")
|
||||
entry.file = normalizeFilePath(entry.file)
|
||||
|
||||
entity = ide.fileTreeManager.findEntityByPath(entry.file)
|
||||
if entity?
|
||||
@@ -84,6 +83,16 @@ define [
|
||||
return ide.editorManager.getCurrentDocId()
|
||||
return null
|
||||
|
||||
normalizeFilePath = (path) ->
|
||||
path = path.replace(/^(.*)\/compiles\/[0-9a-f]{24}\/(\.\/)?/, "")
|
||||
path = path.replace(/^\/compile\//, "")
|
||||
|
||||
rootDocDirname = ide.fileTreeManager.getRootDocDirname()
|
||||
if rootDocDirname?
|
||||
path = path.replace(/^\.\//, rootDocDirname)
|
||||
|
||||
return path
|
||||
|
||||
$scope.recompile = (options = {}) ->
|
||||
console.log "Recompiling", options
|
||||
return if $scope.pdf.compiling
|
||||
@@ -129,13 +138,115 @@ define [
|
||||
controller: "ClearCacheModalController"
|
||||
scope: $scope
|
||||
)
|
||||
|
||||
$scope.syncToCode = (position) ->
|
||||
console.log "SYNCING VIA DBL CLICK", position
|
||||
synctex
|
||||
.syncToCode(position)
|
||||
.then (data) ->
|
||||
{doc, line} = data
|
||||
ide.editorManager.openDoc(doc, gotoLine: line)
|
||||
|
||||
]
|
||||
|
||||
App.factory "synctex", ["ide", "$http", "$q", (ide, $http, $q) ->
|
||||
synctex =
|
||||
syncToPdf: (cursorPosition) ->
|
||||
deferred = $q.defer()
|
||||
|
||||
doc_id = ide.editorManager.getCurrentDocId()
|
||||
if !doc_id?
|
||||
deferred.reject()
|
||||
return deferred.promise()
|
||||
doc = ide.fileTreeManager.findEntityById(doc_id)
|
||||
if !doc?
|
||||
deferred.reject()
|
||||
return deferred.promise()
|
||||
path = ide.fileTreeManager.getEntityPath(doc)
|
||||
if !path?
|
||||
deferred.reject()
|
||||
return deferred.promise()
|
||||
|
||||
# If the root file is folder/main.tex, then synctex sees the
|
||||
# path as folder/./main.tex
|
||||
rootDocDirname = ide.fileTreeManager.getRootDocDirname()
|
||||
if rootDocDirname? and rootDocDirname != ""
|
||||
path = path.replace(RegExp("^#{rootDocDirname}"), "#{rootDocDirname}/.")
|
||||
|
||||
{row, column} = cursorPosition
|
||||
|
||||
$http({
|
||||
url: "/project/#{ide.project_id}/sync/code",
|
||||
method: "GET",
|
||||
params: {
|
||||
file: path
|
||||
line: row + 1
|
||||
column: column
|
||||
}
|
||||
})
|
||||
.success (data) ->
|
||||
console.log "SYNCTEX RESPONSE", data
|
||||
deferred.resolve(data.pdf or [])
|
||||
.error (error) ->
|
||||
deferred.reject(error)
|
||||
|
||||
return deferred.promise
|
||||
|
||||
syncToCode: (position, options = {}) ->
|
||||
deferred = $q.defer()
|
||||
if !position?
|
||||
deferred.reject()
|
||||
return deferred.promise()
|
||||
|
||||
# It's not clear exactly where we should sync to if it wasn't directly
|
||||
# clicked on, but a little bit down from the very top seems best.
|
||||
if options.includeVisualOffset
|
||||
position.offset.top = position.offset.top + 80
|
||||
|
||||
$http({
|
||||
url: "/project/#{ide.project_id}/sync/pdf",
|
||||
method: "GET",
|
||||
params: {
|
||||
page: position.page + 1
|
||||
h: position.offset.left.toFixed(2)
|
||||
v: position.offset.top.toFixed(2)
|
||||
}
|
||||
})
|
||||
.success (data) ->
|
||||
console.log "SYNCTEX RESPONSE", data
|
||||
if data.code? and data.code.length > 0
|
||||
doc = ide.fileTreeManager.findEntityByPath(data.code[0].file)
|
||||
return if !doc?
|
||||
deferred.resolve({doc: doc, line: data.code[0].line})
|
||||
.error (error) ->
|
||||
deferred.reject(error)
|
||||
|
||||
return deferred.promise
|
||||
|
||||
return synctex
|
||||
]
|
||||
|
||||
App.controller "PdfSynctexController", ["$scope", "synctex", "ide", ($scope, synctex, ide) ->
|
||||
$scope.syncToPdf = () ->
|
||||
synctex
|
||||
.syncToPdf($scope.editor.cursorPosition)
|
||||
.then (highlights) ->
|
||||
$scope.pdf.highlights = highlights
|
||||
|
||||
$scope.syncToCode = () ->
|
||||
synctex
|
||||
.syncToCode($scope.pdf.position, includeVisualOffset: true)
|
||||
.then (data) ->
|
||||
{doc, line} = data
|
||||
console.log "OPENING DOC", doc, line
|
||||
ide.editorManager.openDoc(doc, gotoLine: line)
|
||||
]
|
||||
|
||||
App.controller "PdfLogEntryController", ["$scope", "ide", ($scope, ide) ->
|
||||
$scope.openInEditor = (entry) ->
|
||||
console.log "OPENING", entry.file, entry.line
|
||||
entity = ide.fileTreeManager.findEntityByPath(entry.file)
|
||||
return if entity.type != "doc"
|
||||
return if !entity? or entity.type != "doc"
|
||||
if entry.line?
|
||||
line = entry.line
|
||||
ide.editorManager.openDoc(entity, gotoLine: line)
|
||||
|
||||
@@ -28,12 +28,16 @@ define [
|
||||
return {
|
||||
scope: {
|
||||
"pdfSrc": "="
|
||||
"highlights": "="
|
||||
"position": "="
|
||||
"dblClickCallback": "="
|
||||
}
|
||||
link: (scope, element, attrs) ->
|
||||
pdfListView = new PDFListView element.find(".pdfjs-viewer")[0],
|
||||
textLayerBuilder: TextLayerBuilder
|
||||
annotationsLayerBuilder: AnnotationsLayerBuilder
|
||||
highlightsLayerBuilder: HighlightsLayerBuilder
|
||||
ondblclick: (e) -> onDoubleClick(e)
|
||||
logLevel: PDFListView.Logger.DEBUG
|
||||
pdfListView.listView.pageWidthOffset = 20
|
||||
pdfListView.listView.pageHeightOffset = 20
|
||||
@@ -58,6 +62,8 @@ define [
|
||||
if (position = $.localStorage("pdf.position.#{attrs.key}"))
|
||||
pdfListView.setPdfPosition(position)
|
||||
|
||||
scope.position = pdfListView.getPdfPosition(true)
|
||||
|
||||
$(window).unload () =>
|
||||
$.localStorage "pdf.scale", {
|
||||
scaleMode: pdfListView.getScaleMode()
|
||||
@@ -69,7 +75,14 @@ define [
|
||||
scope.flashControls = true
|
||||
$timeout () ->
|
||||
scope.flashControls = false
|
||||
, 1000
|
||||
, 1000
|
||||
|
||||
element.find(".pdfjs-viewer").scroll () ->
|
||||
console.log "UPDATING POSITION", pdfListView.getPdfPosition(true)
|
||||
scope.position = pdfListView.getPdfPosition(true)
|
||||
|
||||
onDoubleClick = (e) ->
|
||||
scope.dblClickCallback?(page: e.page, offset: { top: e.y, left: e.x })
|
||||
|
||||
scope.$watch "pdfSrc", (url) ->
|
||||
if url
|
||||
@@ -85,6 +98,35 @@ define [
|
||||
initializePosition()
|
||||
flashControls()
|
||||
|
||||
scope.$watch "highlights", (areas) ->
|
||||
console.log "UPDATING HIGHLIGHTS", areas
|
||||
return if !areas?
|
||||
highlights = for area in areas or []
|
||||
{
|
||||
page: area.page - 1
|
||||
highlight:
|
||||
left: area.h
|
||||
top: area.v
|
||||
height: area.height
|
||||
width: area.width
|
||||
}
|
||||
|
||||
if highlights.length > 0
|
||||
first = highlights[0]
|
||||
pdfListView.setPdfPosition({
|
||||
page: first.page
|
||||
offset:
|
||||
left: first.highlight.left
|
||||
top: first.highlight.top - 80
|
||||
}, true)
|
||||
|
||||
pdfListView.clearHighlights()
|
||||
pdfListView.setHighlights(highlights, true)
|
||||
|
||||
setTimeout () =>
|
||||
pdfListView.clearHighlights()
|
||||
, 1000
|
||||
|
||||
scope.fitToHeight = () ->
|
||||
pdfListView.setToFitHeight()
|
||||
|
||||
|
||||
@@ -112,4 +112,12 @@
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.synctex-controls {
|
||||
padding: 68px 2px 0;
|
||||
.btn-xs {
|
||||
line-height: 1.3;
|
||||
padding: 0 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user