-
Notifications
You must be signed in to change notification settings - Fork 520
/
synctex.ts
72 lines (67 loc) · 3.15 KB
/
synctex.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import type {ILatexWorkshopPdfViewer, IPDFViewerApplication} from './interface.js'
declare const PDFViewerApplication: IPDFViewerApplication
export class SyncTex {
private readonly lwApp: ILatexWorkshopPdfViewer
reverseSynctexKeybinding: string = 'ctrl-click'
constructor(lwApp: ILatexWorkshopPdfViewer) {
this.lwApp = lwApp
// Since DOM of each page is recreated when a PDF document is reloaded,
// we must register listeners every time.
this.lwApp.onPagesInit(() => {
this.registerListenerOnEachPage()
})
}
private callSynctex(e: MouseEvent, page: number, pageDom: HTMLElement, viewerContainer: HTMLElement) {
const canvasDom = pageDom.getElementsByTagName('canvas')[0]
const selection = window.getSelection()
let textBeforeSelection = ''
let textAfterSelection = ''
// workaround for https://github.com/James-Yu/LaTeX-Workshop/issues/1314
if(selection && selection.anchorNode && selection.anchorNode.nodeName === '#text'){
const text = selection.anchorNode.textContent
if (text) {
textBeforeSelection = text.substring(0, selection.anchorOffset)
textAfterSelection = text.substring(selection.anchorOffset)
}
}
const trimSelect = document.getElementById('trimSelect') as HTMLSelectElement
let left = e.pageX - pageDom.offsetLeft + viewerContainer.scrollLeft
const top = e.pageY - pageDom.offsetTop + viewerContainer.scrollTop
if (trimSelect.selectedIndex > 0) {
const m = canvasDom.style.left.match(/-(.*)px/)
const offsetLeft = m ? Number(m[1]) : 0
left += offsetLeft
}
const pos = PDFViewerApplication.pdfViewer._pages[page-1].getPagePoint(left, canvasDom.offsetHeight - top)
this.lwApp.send({type: 'reverse_synctex', pdfFileUri: this.lwApp.pdfFileUri, pos, page, textBeforeSelection, textAfterSelection})
}
registerListenerOnEachPage() {
const keybinding = this.reverseSynctexKeybinding
const viewerDom = document.getElementById('viewer') as HTMLElement
for (const pageDom of viewerDom.childNodes as NodeListOf<HTMLElement>) {
const page = Number(pageDom.dataset.pageNumber)
const viewerContainer = document.getElementById('viewerContainer') as HTMLElement
switch (keybinding) {
case 'ctrl-click': {
pageDom.onclick = (e) => {
if (!(e.ctrlKey || e.metaKey)) {
return
}
this.callSynctex(e, page, pageDom, viewerContainer)
}
break
}
case 'double-click': {
pageDom.ondblclick = (e) => {
this.callSynctex(e, page, pageDom, viewerContainer)
}
break
}
default: {
console.log(`Unknown keybinding ${keybinding} (view.pdf.internal.synctex.keybinding)`)
break
}
}
}
}
}