Merge pull request #2280 from overleaf/em-show-logs-on-timeout

Decaf cleanup of PdfController

GitOrigin-RevId: 20aecd3abd53034e46129b60f86becbeace18781
This commit is contained in:
Eric Mc Sween 2019-10-28 10:05:23 -04:00 committed by sharelatex
parent 9319229657
commit 9afb911b89

View file

@ -1,22 +1,3 @@
/* eslint-disable
camelcase,
max-len,
no-cond-assign,
no-return-assign,
no-undef,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS103: Rewrite code to no longer use __guard__
* DS205: Consider reworking code to avoid use of IIFEs
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
define([ define([
'base', 'base',
'ace/ace', 'ace/ace',
@ -41,17 +22,10 @@ define([
eventTracking, eventTracking,
localStorage localStorage
) { ) {
// enable per-user containers by default
const perUserCompile = true
let autoCompile = true let autoCompile = true
// pdf.view = uncompiled | pdf | errors // pdf.view = uncompiled | pdf | errors
$scope.pdf.view = __guard__( $scope.pdf.view = $scope.pdf.url ? 'pdf' : 'uncompiled'
$scope != null ? $scope.pdf : undefined,
x => x.url
)
? 'pdf'
: 'uncompiled'
$scope.shouldShowLogs = false $scope.shouldShowLogs = false
$scope.wikiEnabled = window.wikiEnabled $scope.wikiEnabled = window.wikiEnabled
@ -60,30 +34,31 @@ define([
const logsContainerEl = document.querySelector('.pdf-logs') const logsContainerEl = document.querySelector('.pdf-logs')
const filesDropdownEl = const filesDropdownEl =
logsContainerEl != null logsContainerEl && logsContainerEl.querySelector('.files-dropdown')
? logsContainerEl.querySelector('.files-dropdown')
: undefined
// get the top coordinate of the files dropdown as a ratio (to the logs container height) // get the top coordinate of the files dropdown as a ratio (to the logs container height)
// logs container supports scrollable content, so it's possible that ratio > 1. // logs container supports scrollable content, so it's possible that ratio > 1.
const getFilesDropdownTopCoordAsRatio = () => function getFilesDropdownTopCoordAsRatio() {
(filesDropdownEl != null if (filesDropdownEl == null || logsContainerEl == null) {
? filesDropdownEl.getBoundingClientRect().top return 0
: undefined) / }
(logsContainerEl != null return (
? logsContainerEl.getBoundingClientRect().height filesDropdownEl.getBoundingClientRect().top /
: undefined) logsContainerEl.getBoundingClientRect().height
$scope.$watch('shouldShowLogs', function(shouldShow) {
if (shouldShow) {
return $scope.$applyAsync(
() => ($scope.shouldDropUp = getFilesDropdownTopCoordAsRatio() > 0.65)
) )
} }
$scope.$watch('shouldShowLogs', shouldShow => {
if (shouldShow) {
$scope.$applyAsync(() => {
$scope.shouldDropUp = getFilesDropdownTopCoordAsRatio() > 0.65
})
}
}) })
$scope.trackLogHintsLearnMore = () => $scope.trackLogHintsLearnMore = function() {
eventTracking.sendMB('logs-hints-learn-more') eventTracking.sendMB('logs-hints-learn-more')
}
if (ace.require('ace/lib/useragent').isMac) { if (ace.require('ace/lib/useragent').isMac) {
$scope.modifierKey = 'Cmd' $scope.modifierKey = 'Cmd'
@ -92,17 +67,14 @@ define([
} }
// utility for making a query string from a hash, could use jquery $.param // utility for making a query string from a hash, could use jquery $.param
const createQueryString = function(args) { function createQueryString(args) {
const qs_args = (() => { const qsArgs = []
const result = [] for (const k in args) {
for (let k in args) {
const v = args[k] const v = args[k]
result.push(`${k}=${v}`) qsArgs.push(`${k}=${v}`)
} }
return result if (qsArgs.length) {
})() return `?${qsArgs.join('&')}`
if (qs_args.length) {
return `?${qs_args.join('&')}`
} else { } else {
return '' return ''
} }
@ -114,23 +86,23 @@ define([
return tmp.textContent || tmp.innerText || '' return tmp.textContent || tmp.innerText || ''
} }
$scope.$on('project:joined', function() { $scope.$on('project:joined', () => {
if (!autoCompile) { if (!autoCompile) {
return return
} }
autoCompile = false autoCompile = false
$scope.recompile({ isAutoCompileOnLoad: true }) $scope.recompile({ isAutoCompileOnLoad: true })
return ($scope.hasPremiumCompile = $scope.hasPremiumCompile =
$scope.project.features.compileGroup === 'priority') $scope.project.features.compileGroup === 'priority'
}) })
$scope.$on('pdf:error:display', function() { $scope.$on('pdf:error:display', function() {
$scope.pdf.view = 'errors' $scope.pdf.view = 'errors'
return ($scope.pdf.renderingError = true) $scope.pdf.renderingError = true
}) })
let autoCompileInterval = null let autoCompileInterval = null
const autoCompileIfReady = function() { function autoCompileIfReady() {
if ( if (
$scope.pdf.compiling || $scope.pdf.compiling ||
!$scope.autocompile_enabled || !$scope.autocompile_enabled ||
@ -143,12 +115,12 @@ define([
const autoCompileLintingError = const autoCompileLintingError =
ide.$scope.hasLintingError && ide.$scope.settings.syntaxValidation ide.$scope.hasLintingError && ide.$scope.settings.syntaxValidation
if ($scope.autoCompileLintingError !== autoCompileLintingError) { if ($scope.autoCompileLintingError !== autoCompileLintingError) {
$scope.$apply(function() { $scope.$apply(() => {
$scope.autoCompileLintingError = autoCompileLintingError $scope.autoCompileLintingError = autoCompileLintingError
// We've likely been waiting a while until the user fixed the linting, but we // We've likely been waiting a while until the user fixed the linting, but we
// don't want to compile as soon as it is fixed, so reset the timeout. // don't want to compile as soon as it is fixed, so reset the timeout.
$scope.startedTryingAutoCompileAt = Date.now() $scope.startedTryingAutoCompileAt = Date.now()
return ($scope.docLastChangedAt = Date.now()) $scope.docLastChangedAt = Date.now()
}) })
} }
if (autoCompileLintingError && $scope.stop_on_validation_error) { if (autoCompileLintingError && $scope.stop_on_validation_error) {
@ -182,24 +154,25 @@ define([
} }
} }
var triggerAutoCompile = () => function triggerAutoCompile() {
$scope.recompile({ isAutoCompileOnChange: true }) $scope.recompile({ isAutoCompileOnChange: true })
}
const startTryingAutoCompile = function() { function startTryingAutoCompile() {
if (autoCompileInterval != null) { if (autoCompileInterval != null) {
return return
} }
$scope.startedTryingAutoCompileAt = Date.now() $scope.startedTryingAutoCompileAt = Date.now()
return (autoCompileInterval = setInterval(autoCompileIfReady, 200)) autoCompileInterval = setInterval(autoCompileIfReady, 200)
} }
const stopTryingAutoCompile = function() { function stopTryingAutoCompile() {
clearInterval(autoCompileInterval) clearInterval(autoCompileInterval)
return (autoCompileInterval = null) autoCompileInterval = null
} }
$scope.changesToAutoCompile = false $scope.changesToAutoCompile = false
$scope.$watch('pdf.uncompiled', function(uncompiledChanges) { $scope.$watch('pdf.uncompiled', uncompiledChanges => {
// don't autocompile if disabled or the pdf is not visible // don't autocompile if disabled or the pdf is not visible
if ( if (
$scope.pdf.uncompiled && $scope.pdf.uncompiled &&
@ -207,14 +180,14 @@ define([
!$scope.ui.pdfHidden !$scope.ui.pdfHidden
) { ) {
$scope.changesToAutoCompile = true $scope.changesToAutoCompile = true
return startTryingAutoCompile() startTryingAutoCompile()
} else { } else {
$scope.changesToAutoCompile = false $scope.changesToAutoCompile = false
return stopTryingAutoCompile() stopTryingAutoCompile()
} }
}) })
const recalculateUncompiledChanges = function() { function recalculateUncompiledChanges() {
if ($scope.docLastChangedAt == null) { if ($scope.docLastChangedAt == null) {
$scope.pdf.uncompiled = false $scope.pdf.uncompiled = false
} else if ( } else if (
@ -227,23 +200,26 @@ define([
} }
} }
const _updateDocLastChangedAt = function() { function _updateDocLastChangedAt() {
$scope.docLastChangedAt = Date.now() $scope.docLastChangedAt = Date.now()
return recalculateUncompiledChanges() recalculateUncompiledChanges()
} }
const onDocChanged = function() { function onDocChanged() {
$scope.autoCompileLintingError = false $scope.autoCompileLintingError = false
return _updateDocLastChangedAt() _updateDocLastChangedAt()
} }
const onDocSaved = () => function onDocSaved() {
// We use the save as a trigger too, to account for the delay between the client // We use the save as a trigger too, to account for the delay between the client
// and server. Otherwise, we might have compiled after the user made // and server. Otherwise, we might have compiled after the user made
// the change on the client, but before the server had it. // the change on the client, but before the server had it.
_updateDocLastChangedAt() _updateDocLastChangedAt()
}
const onCompilingStateChanged = compiling => recalculateUncompiledChanges() function onCompilingStateChanged(compiling) {
recalculateUncompiledChanges()
}
ide.$scope.$on('doc:changed', onDocChanged) ide.$scope.$on('doc:changed', onDocChanged)
ide.$scope.$on('doc:saved', onDocSaved) ide.$scope.$on('doc:saved', onDocSaved)
@ -251,13 +227,13 @@ define([
$scope.autocompile_enabled = $scope.autocompile_enabled =
localStorage(`autocompile_enabled:${$scope.project_id}`) || false localStorage(`autocompile_enabled:${$scope.project_id}`) || false
$scope.$watch('autocompile_enabled', function(newValue, oldValue) { $scope.$watch('autocompile_enabled', (newValue, oldValue) => {
if (newValue != null && oldValue !== newValue) { if (newValue != null && oldValue !== newValue) {
if (newValue === true) { if (newValue === true) {
autoCompileIfReady() autoCompileIfReady()
} }
localStorage(`autocompile_enabled:${$scope.project_id}`, newValue) localStorage(`autocompile_enabled:${$scope.project_id}`, newValue)
return eventTracking.sendMB('autocompile-setting-changed', { eventTracking.sendMB('autocompile-setting-changed', {
value: newValue value: newValue
}) })
} }
@ -269,24 +245,22 @@ define([
) )
if ($scope.stop_on_validation_error == null) { if ($scope.stop_on_validation_error == null) {
$scope.stop_on_validation_error = true $scope.stop_on_validation_error = true
} // turn on for all users by default }
$scope.$watch('stop_on_validation_error', function(new_value, old_value) { // turn on for all users by default
if (new_value != null && old_value !== new_value) { $scope.$watch('stop_on_validation_error', (newValue, oldValue) => {
return localStorage( if (newValue != null && oldValue !== newValue) {
`stop_on_validation_error:${$scope.project_id}`, localStorage(`stop_on_validation_error:${$scope.project_id}`, newValue)
new_value
)
} }
}) })
$scope.draft = localStorage(`draft:${$scope.project_id}`) || false $scope.draft = localStorage(`draft:${$scope.project_id}`) || false
$scope.$watch('draft', function(new_value, old_value) { $scope.$watch('draft', (newValue, oldValue) => {
if (new_value != null && old_value !== new_value) { if (newValue != null && oldValue !== newValue) {
return localStorage(`draft:${$scope.project_id}`, new_value) localStorage(`draft:${$scope.project_id}`, newValue)
} }
}) })
const sendCompileRequest = function(options) { function sendCompileRequest(options) {
if (options == null) { if (options == null) {
options = {} options = {}
} }
@ -305,24 +279,24 @@ define([
eventTracking.sendMB('syntax-check-request') eventTracking.sendMB('syntax-check-request')
} }
// send appropriate check type to clsi // send appropriate check type to clsi
let checkType = (() => { let checkType
switch (false) { if ($scope.check) {
case !$scope.check: checkType = 'validate' // validate only
return 'validate' // validate only } else if (options.try) {
case !options.try: checkType = 'silent' // allow use to try compile once
return 'silent' // allow use to try compile once } else if ($scope.stop_on_validation_error) {
case !$scope.stop_on_validation_error: checkType = 'error' // try to compile
return 'error' // try to compile } else {
default: checkType = 'silent' // ignore errors
return 'silent' // ignore errors
} }
})()
// FIXME: Temporarily disable syntax checking as it is causing // FIXME: Temporarily disable syntax checking as it is causing
// excessive support requests for projects migrated from v1 // excessive support requests for projects migrated from v1
// https://github.com/overleaf/sharelatex/issues/911 // https://github.com/overleaf/sharelatex/issues/911
if (checkType === 'error') { if (checkType === 'error') {
checkType = 'silent' checkType = 'silent'
} }
return $http.post( return $http.post(
url, url,
{ {
@ -338,7 +312,7 @@ define([
) )
} }
const buildPdfDownloadUrl = function(pdfDownloadDomain, path) { function buildPdfDownloadUrl(pdfDownloadDomain, path) {
// we only download builds from compiles server for security reasons // we only download builds from compiles server for security reasons
if ( if (
pdfDownloadDomain != null && pdfDownloadDomain != null &&
@ -351,10 +325,9 @@ define([
} }
} }
const parseCompileResponse = function(response) { function parseCompileResponse(response) {
// keep last url // keep last url
let file const lastPdfUrl = $scope.pdf.url
const last_pdf_url = $scope.pdf.url
const { pdfDownloadDomain } = response const { pdfDownloadDomain } = response
// Reset everything // Reset everything
$scope.pdf.error = false $scope.pdf.error = false
@ -373,10 +346,8 @@ define([
// make a cache to look up files by name // make a cache to look up files by name
const fileByPath = {} const fileByPath = {}
if ((response != null ? response.outputFiles : undefined) != null) { if (response.outputFiles != null) {
for (file of Array.from( for (const file of response.outputFiles) {
response != null ? response.outputFiles : undefined
)) {
fileByPath[file.path] = file fileByPath[file.path] = file
} }
} }
@ -414,7 +385,7 @@ define([
['validation-fail', 'validation-pass'].includes(response.status) ['validation-fail', 'validation-pass'].includes(response.status)
) { ) {
$scope.pdf.view = 'pdf' $scope.pdf.view = 'pdf'
$scope.pdf.url = buildPdfDownloadUrl(pdfDownloadDomain, last_pdf_url) $scope.pdf.url = buildPdfDownloadUrl(pdfDownloadDomain, lastPdfUrl)
$scope.shouldShowLogs = true $scope.shouldShowLogs = true
if (response.status === 'validation-fail') { if (response.status === 'validation-fail') {
$scope.pdf.failedCheck = true $scope.pdf.failedCheck = true
@ -424,7 +395,7 @@ define([
} else if (response.status === 'exited') { } else if (response.status === 'exited') {
$scope.pdf.view = 'pdf' $scope.pdf.view = 'pdf'
$scope.pdf.compileExited = true $scope.pdf.compileExited = true
$scope.pdf.url = buildPdfDownloadUrl(pdfDownloadDomain, last_pdf_url) $scope.pdf.url = buildPdfDownloadUrl(pdfDownloadDomain, lastPdfUrl)
$scope.shouldShowLogs = true $scope.shouldShowLogs = true
fetchLogs(fileByPath, { pdfDownloadDomain }) fetchLogs(fileByPath, { pdfDownloadDomain })
} else if (response.status === 'autocompile-backoff') { } else if (response.status === 'autocompile-backoff') {
@ -462,26 +433,17 @@ define([
$scope.pdf.view = 'errors' $scope.pdf.view = 'errors'
$scope.pdf.compileInProgress = true $scope.pdf.compileInProgress = true
} else if (response.status === 'success') { } else if (response.status === 'success') {
let build
$scope.pdf.view = 'pdf' $scope.pdf.view = 'pdf'
$scope.shouldShowLogs = false $scope.shouldShowLogs = false
// define the base url. if the pdf file has a build number, pass it to the clsi in the url // define the base url. if the pdf file has a build number, pass it to the clsi in the url
if ( if (fileByPath['output.pdf'] && fileByPath['output.pdf'].url) {
(fileByPath['output.pdf'] != null
? fileByPath['output.pdf'].url
: undefined) != null
) {
$scope.pdf.url = buildPdfDownloadUrl( $scope.pdf.url = buildPdfDownloadUrl(
pdfDownloadDomain, pdfDownloadDomain,
fileByPath['output.pdf'].url fileByPath['output.pdf'].url
) )
} else if ( } else if (fileByPath['output.pdf'] && fileByPath['output.pdf'].build) {
(fileByPath['output.pdf'] != null const { build } = fileByPath['output.pdf']
? fileByPath['output.pdf'].build
: undefined) != null
) {
;({ build } = fileByPath['output.pdf'])
$scope.pdf.url = buildPdfDownloadUrl( $scope.pdf.url = buildPdfDownloadUrl(
pdfDownloadDomain, pdfDownloadDomain,
`/project/${$scope.project_id}/build/${build}/output/output.pdf` `/project/${$scope.project_id}/build/${build}/output/output.pdf`
@ -493,11 +455,7 @@ define([
) )
} }
// check if we need to bust cache (build id is unique so don't need it in that case) // check if we need to bust cache (build id is unique so don't need it in that case)
if ( if (fileByPath['output.pdf'] && fileByPath['output.pdf'].build) {
(fileByPath['output.pdf'] != null
? fileByPath['output.pdf'].build
: undefined) == null
) {
qs.cache_bust = `${Date.now()}` qs.cache_bust = `${Date.now()}`
} }
// convert the qs hash into a query string and append it // convert the qs hash into a query string and append it
@ -530,7 +488,7 @@ define([
if (response.clsiServerId != null) { if (response.clsiServerId != null) {
qs.clsiserverid = response.clsiServerId qs.clsiserverid = response.clsiServerId
} }
for (file of Array.from(response.outputFiles)) { for (const file of response.outputFiles) {
if (IGNORE_FILES.indexOf(file.path) === -1) { if (IGNORE_FILES.indexOf(file.path) === -1) {
const isOutputFile = /^output\./.test(file.path) const isOutputFile = /^output\./.test(file.path)
$scope.pdf.outputFiles.push({ $scope.pdf.outputFiles.push({
@ -539,7 +497,7 @@ define([
? `${file.path.replace(/^output\./, '')} file` ? `${file.path.replace(/^output\./, '')} file`
: file.path, : file.path,
url: url:
`/project/${project_id}/output/${file.path}` + `/project/${$scope.project_id}/output/${file.path}` +
createQueryString(qs), createQueryString(qs),
main: !!isOutputFile main: !!isOutputFile
}) })
@ -547,13 +505,13 @@ define([
} }
// sort the output files into order, main files first, then others // sort the output files into order, main files first, then others
return $scope.pdf.outputFiles.sort( $scope.pdf.outputFiles.sort(
(a, b) => b.main - a.main || a.name.localeCompare(b.name) (a, b) => b.main - a.main || a.name.localeCompare(b.name)
) )
} }
var fetchLogs = function(fileByPath, options) { function fetchLogs(fileByPath, options) {
let blgFile, chktexFile, logFile, response let blgFile, chktexFile, logFile
if (options != null ? options.validation : undefined) { if (options != null ? options.validation : undefined) {
chktexFile = fileByPath['output.chktex'] chktexFile = fileByPath['output.chktex']
} else { } else {
@ -561,7 +519,7 @@ define([
blgFile = fileByPath['output.blg'] blgFile = fileByPath['output.blg']
} }
const getFile = function(name, file) { function getFile(name, file) {
const opts = { const opts = {
method: 'GET', method: 'GET',
params: { params: {
@ -569,10 +527,10 @@ define([
clsiserverid: ide.clsiServerId clsiserverid: ide.clsiServerId
} }
} }
if ((file != null ? file.url : undefined) != null) { if (file && file.url) {
// FIXME clean this up when we have file.urls out consistently // FIXME clean this up when we have file.urls out consistently
opts.url = file.url opts.url = file.url
} else if ((file != null ? file.build : undefined) != null) { } else if (file && file.build) {
opts.url = `/project/${$scope.project_id}/build/${ opts.url = `/project/${$scope.project_id}/build/${
file.build file.build
}/output/${name}` }/output/${name}`
@ -580,7 +538,7 @@ define([
opts.url = `/project/${$scope.project_id}/output/${name}` opts.url = `/project/${$scope.project_id}/output/${name}`
} }
// check if we need to bust cache (build id is unique so don't need it in that case) // check if we need to bust cache (build id is unique so don't need it in that case)
if ((file != null ? file.build : undefined) == null) { if (file && file.build) {
opts.params.cache_bust = `${Date.now()}` opts.params.cache_bust = `${Date.now()}`
} }
opts.url = buildPdfDownloadUrl(options.pdfDownloadDomain, opts.url) opts.url = buildPdfDownloadUrl(options.pdfDownloadDomain, opts.url)
@ -594,36 +552,31 @@ define([
warnings: [] warnings: []
} }
const accumulateResults = newEntries => function accumulateResults(newEntries) {
(() => {
const result = []
for (let key of ['all', 'errors', 'warnings']) { for (let key of ['all', 'errors', 'warnings']) {
if (newEntries.type != null) { if (newEntries.type != null) {
for (let entry of Array.from(newEntries[key])) { for (let entry of newEntries[key]) {
entry.type = newEntries.type entry.type = newEntries.type
} }
} }
result.push( logEntries[key] = logEntries[key].concat(newEntries[key])
(logEntries[key] = logEntries[key].concat(newEntries[key])) }
)
} }
return result
})()
// use the parsers for each file type // use the parsers for each file type
const processLog = function(log) { function processLog(log) {
$scope.pdf.rawLog = log $scope.pdf.rawLog = log
const { errors, warnings, typesetting } = HumanReadableLogs.parse(log, { const { errors, warnings, typesetting } = HumanReadableLogs.parse(log, {
ignoreDuplicates: true ignoreDuplicates: true
}) })
const all = [].concat(errors, warnings, typesetting) const all = [].concat(errors, warnings, typesetting)
return accumulateResults({ all, errors, warnings }) accumulateResults({ all, errors, warnings })
} }
const processChkTex = function(log) { function processChkTex(log) {
const errors = [] const errors = []
const warnings = [] const warnings = []
for (let line of Array.from(log.split('\n'))) { for (let line of log.split('\n')) {
var m var m
if ((m = line.match(/^(\S+):(\d+):(\d+): (Error|Warning): (.*)/))) { if ((m = line.match(/^(\S+):(\d+):(\d+): (Error|Warning): (.*)/))) {
const result = { const result = {
@ -651,27 +604,25 @@ define([
errors: errors.length, errors: errors.length,
warnings: warnings.length warnings: warnings.length
}) })
return accumulateResults(logHints) accumulateResults(logHints)
} }
const processBiber = function(log) { function processBiber(log) {
const { errors, warnings } = BibLogParser.parse(log, {}) const { errors, warnings } = BibLogParser.parse(log, {})
const all = [].concat(errors, warnings) const all = [].concat(errors, warnings)
return accumulateResults({ type: 'BibTeX', all, errors, warnings }) accumulateResults({ type: 'BibTeX', all, errors, warnings })
} }
// output the results // output the results
const handleError = function() { function handleError() {
$scope.pdf.logEntries = [] $scope.pdf.logEntries = []
return ($scope.pdf.rawLog = '') $scope.pdf.rawLog = ''
} }
const annotateFiles = function() { function annotateFiles() {
$scope.pdf.logEntries = logEntries $scope.pdf.logEntries = logEntries
$scope.pdf.logEntryAnnotations = {} $scope.pdf.logEntryAnnotations = {}
return (() => { for (const entry of logEntries.all) {
const result = []
for (let entry of Array.from(logEntries.all)) {
if (entry.file != null) { if (entry.file != null) {
entry.file = normalizeFilePath(entry.file) entry.file = normalizeFilePath(entry.file)
const entity = ide.fileTreeManager.findEntityByPath(entry.file) const entity = ide.fileTreeManager.findEntityByPath(entry.file)
@ -679,25 +630,18 @@ define([
if (!$scope.pdf.logEntryAnnotations[entity.id]) { if (!$scope.pdf.logEntryAnnotations[entity.id]) {
$scope.pdf.logEntryAnnotations[entity.id] = [] $scope.pdf.logEntryAnnotations[entity.id] = []
} }
result.push(
$scope.pdf.logEntryAnnotations[entity.id].push({ $scope.pdf.logEntryAnnotations[entity.id].push({
row: entry.line - 1, row: entry.line - 1,
type: entry.level === 'error' ? 'error' : 'warning', type: entry.level === 'error' ? 'error' : 'warning',
text: entry.message text: entry.message
}) })
)
} else {
result.push(undefined)
}
} else {
result.push(undefined)
} }
} }
return result }
})()
} }
// retrieve the logfile and process it // retrieve the logfile and process it
let response
if (logFile != null) { if (logFile != null) {
response = getFile('output.log', logFile).then(response => response = getFile('output.log', logFile).then(response =>
processLog(response.data) processLog(response.data)
@ -735,16 +679,16 @@ define([
// display the combined result // display the combined result
if (response != null) { if (response != null) {
return response.finally(annotateFiles) response.finally(annotateFiles)
} }
} }
const getRootDocOverride_id = function() { function getRootDocOverrideId() {
const doc = ide.editorManager.getCurrentDocValue() const doc = ide.editorManager.getCurrentDocValue()
if (doc == null) { if (doc == null) {
return null return null
} }
for (let line of Array.from(doc.split('\n'))) { for (let line of doc.split('\n')) {
if (/^[^%]*\\documentclass/.test(line)) { if (/^[^%]*\\documentclass/.test(line)) {
return ide.editorManager.getCurrentDocId() return ide.editorManager.getCurrentDocId()
} }
@ -752,7 +696,7 @@ define([
return null return null
} }
var normalizeFilePath = function(path) { function normalizeFilePath(path) {
path = path.replace( path = path.replace(
/^(.*)\/compiles\/[0-9a-f]{24}(-[0-9a-f]{24})?\/(\.\/)?/, /^(.*)\/compiles\/[0-9a-f]{24}(-[0-9a-f]{24})?\/(\.\/)?/,
'' ''
@ -796,32 +740,36 @@ define([
ide.$scope.$broadcast('flush-changes') ide.$scope.$broadcast('flush-changes')
options.rootDocOverride_id = getRootDocOverride_id() options.rootDocOverride_id = getRootDocOverrideId()
return sendCompileRequest(options) sendCompileRequest(options)
.then(function(response) { .then(function(response) {
const { data } = response const { data } = response
$scope.pdf.view = 'pdf' $scope.pdf.view = 'pdf'
$scope.pdf.compiling = false $scope.pdf.compiling = false
return parseCompileResponse(data) parseCompileResponse(data)
}) })
.catch(function(response) { .catch(function(response) {
const { data, status } = response const { status } = response
if (status === 429) { if (status === 429) {
$scope.pdf.rateLimited = true $scope.pdf.rateLimited = true
} }
$scope.pdf.compiling = false $scope.pdf.compiling = false
$scope.pdf.renderingError = false $scope.pdf.renderingError = false
$scope.pdf.error = true $scope.pdf.error = true
return ($scope.pdf.view = 'errors') $scope.pdf.view = 'errors'
})
.finally(() => {
$scope.lastFinishedCompileAt = Date.now()
}) })
.finally(() => ($scope.lastFinishedCompileAt = Date.now()))
} }
// This needs to be public. // This needs to be public.
ide.$scope.recompile = $scope.recompile ide.$scope.recompile = $scope.recompile
// This method is a simply wrapper and exists only for tracking purposes. // This method is a simply wrapper and exists only for tracking purposes.
ide.$scope.recompileViaKey = () => $scope.recompile({ keyShortcut: true }) ide.$scope.recompileViaKey = function() {
$scope.recompile({ keyShortcut: true })
}
$scope.stop = function() { $scope.stop = function() {
if (!$scope.pdf.compiling) { if (!$scope.pdf.compiling) {
@ -840,8 +788,8 @@ define([
}) })
} }
$scope.clearCache = () => $scope.clearCache = function() {
$http({ return $http({
url: `/project/${$scope.project_id}/output`, url: `/project/${$scope.project_id}/output`,
method: 'DELETE', method: 'DELETE',
params: { params: {
@ -851,56 +799,54 @@ define([
'X-Csrf-Token': window.csrfToken 'X-Csrf-Token': window.csrfToken
} }
}) })
}
$scope.toggleLogs = function() { $scope.toggleLogs = function() {
$scope.shouldShowLogs = !$scope.shouldShowLogs $scope.shouldShowLogs = !$scope.shouldShowLogs
if ($scope.shouldShowLogs) { if ($scope.shouldShowLogs) {
return eventTracking.sendMBOnce('ide-open-logs-once') eventTracking.sendMBOnce('ide-open-logs-once')
} }
} }
$scope.showPdf = function() { $scope.showPdf = function() {
$scope.pdf.view = 'pdf' $scope.pdf.view = 'pdf'
return ($scope.shouldShowLogs = false) $scope.shouldShowLogs = false
} }
$scope.toggleRawLog = function() { $scope.toggleRawLog = function() {
$scope.pdf.showRawLog = !$scope.pdf.showRawLog $scope.pdf.showRawLog = !$scope.pdf.showRawLog
if ($scope.pdf.showRawLog) { if ($scope.pdf.showRawLog) {
return eventTracking.sendMB('logs-view-raw') eventTracking.sendMB('logs-view-raw')
} }
} }
$scope.openClearCacheModal = function() { $scope.openClearCacheModal = function() {
let modalInstance $modal.open({
return (modalInstance = $modal.open({
templateUrl: 'clearCacheModalTemplate', templateUrl: 'clearCacheModalTemplate',
controller: 'ClearCacheModalController', controller: 'ClearCacheModalController',
scope: $scope scope: $scope
})) })
} }
return ($scope.syncToCode = position => $scope.syncToCode = function(position) {
synctex.syncToCode(position).then(function(data) { synctex.syncToCode(position).then(function(data) {
const { doc, line } = data const { doc, line } = data
return ide.editorManager.openDoc(doc, { gotoLine: line }) ide.editorManager.openDoc(doc, { gotoLine: line })
})) })
}
}) })
App.factory('synctex', function(ide, $http, $q) { App.factory('synctex', function(ide, $http, $q) {
// enable per-user containers by default
const perUserCompile = true
const synctex = { const synctex = {
syncToPdf(cursorPosition) { syncToPdf(cursorPosition) {
const deferred = $q.defer() const deferred = $q.defer()
const doc_id = ide.editorManager.getCurrentDocId() const docId = ide.editorManager.getCurrentDocId()
if (doc_id == null) { if (docId == null) {
deferred.reject() deferred.reject()
return deferred.promise return deferred.promise
} }
const doc = ide.fileTreeManager.findEntityById(doc_id) const doc = ide.fileTreeManager.findEntityById(docId)
if (doc == null) { if (doc == null) {
deferred.reject() deferred.reject()
return deferred.promise return deferred.promise
@ -946,7 +892,6 @@ define([
}, },
syncToCode(position, options) { syncToCode(position, options) {
let v
if (options == null) { if (options == null) {
options = {} options = {}
} }
@ -968,6 +913,7 @@ define([
// down. This matches the browser's DOM coordinate of the // down. This matches the browser's DOM coordinate of the
// click point, but the pdf position is measured from the // click point, but the pdf position is measured from the
// bottom of the page so we need to invert it. // bottom of the page so we need to invert it.
let v
if ( if (
options.fromPdfPosition && options.fromPdfPosition &&
(position.pageSize != null ? position.pageSize.height : undefined) != (position.pageSize != null ? position.pageSize.height : undefined) !=
@ -1031,18 +977,18 @@ define([
this.cursorPosition = cursorPosition this.cursorPosition = cursorPosition
}) })
$scope.syncToPdf = () => { $scope.syncToPdf = function() {
if (this.cursorPosition == null) { if (this.cursorPosition == null) {
return return
} }
return synctex synctex.syncToPdf(this.cursorPosition).then(highlights => {
.syncToPdf(this.cursorPosition) $scope.pdf.highlights = highlights
.then(highlights => ($scope.pdf.highlights = highlights)) })
} }
ide.$scope.$on('cursor:editor:syncToPdf', $scope.syncToPdf) ide.$scope.$on('cursor:editor:syncToPdf', $scope.syncToPdf)
return ($scope.syncToCode = () => $scope.syncToCode = function() {
synctex synctex
.syncToCode($scope.pdf.position, { .syncToCode($scope.pdf.position, {
includeVisualOffset: true, includeVisualOffset: true,
@ -1050,14 +996,13 @@ define([
}) })
.then(function(data) { .then(function(data) {
const { doc, line } = data const { doc, line } = data
return ide.editorManager.openDoc(doc, { gotoLine: line }) ide.editorManager.openDoc(doc, { gotoLine: line })
})) })
}
}) })
App.controller( App.controller('PdfLogEntryController', function($scope, ide, eventTracking) {
'PdfLogEntryController', $scope.openInEditor = function(entry) {
($scope, ide, eventTracking) =>
($scope.openInEditor = function(entry) {
let column, line let column, line
eventTracking.sendMBOnce('logs-jump-to-location-once') eventTracking.sendMBOnce('logs-jump-to-location-once')
const entity = ide.fileTreeManager.findEntityByPath(entry.file) const entity = ide.fileTreeManager.findEntityByPath(entry.file)
@ -1065,38 +1010,29 @@ define([
return return
} }
if (entry.line != null) { if (entry.line != null) {
;({ line } = entry) line = entry.line
} }
if (entry.column != null) { if (entry.column != null) {
;({ column } = entry) column = entry.column
} }
return ide.editorManager.openDoc(entity, { ide.editorManager.openDoc(entity, {
gotoLine: line, gotoLine: line,
gotoColumn: column gotoColumn: column
}) })
}
}) })
)
return App.controller('ClearCacheModalController', function( App.controller('ClearCacheModalController', function($scope, $modalInstance) {
$scope,
$modalInstance
) {
$scope.state = { inflight: false } $scope.state = { inflight: false }
$scope.clear = function() { $scope.clear = function() {
$scope.state.inflight = true $scope.state.inflight = true
return $scope.clearCache().then(function() { $scope.clearCache().then(function() {
$scope.state.inflight = false $scope.state.inflight = false
return $modalInstance.close() $modalInstance.close()
}) })
} }
return ($scope.cancel = () => $modalInstance.dismiss('cancel')) $scope.cancel = () => $modalInstance.dismiss('cancel')
}) })
}) })
function __guard__(value, transform) {
return typeof value !== 'undefined' && value !== null
? transform(value)
: undefined
}