diff --git a/services/web/Gruntfile.coffee b/services/web/Gruntfile.coffee index 63d0eb6f79..4307621af5 100644 --- a/services/web/Gruntfile.coffee +++ b/services/web/Gruntfile.coffee @@ -381,6 +381,7 @@ module.exports = (grunt) -> grunt.registerTask 'test:modules:unit', 'Run the unit tests for the modules', ['compile:modules:server', 'compile:modules:unit_tests'].concat(moduleUnitTestTasks) grunt.registerTask 'run', "Compile and run the web-sharelatex server", ['compile', 'env:run', 'parallel'] + grunt.registerTask 'runq', "Compile and run the web-sharelatex server", ['compile', 'env:run', 'exec'] grunt.registerTask 'default', 'run' diff --git a/services/web/app/coffee/infrastructure/Modules.coffee b/services/web/app/coffee/infrastructure/Modules.coffee index 2df8907f7e..0dfbf3fa22 100644 --- a/services/web/app/coffee/infrastructure/Modules.coffee +++ b/services/web/app/coffee/infrastructure/Modules.coffee @@ -25,14 +25,14 @@ module.exports = Modules = for module in @modules for view, partial of module.viewIncludes or {} @viewIncludes[view] ||= [] - @viewIncludes[view].push fs.readFileSync(Path.join(MODULE_BASE_PATH, module.name, "app/views", partial + ".jade")) + @viewIncludes[view].push jade.compile(fs.readFileSync(Path.join(MODULE_BASE_PATH, module.name, "app/views", partial + ".jade")), doctype: "html") moduleIncludes: (view, locals) -> - partials = Modules.viewIncludes[view] or [] + compiledPartials = Modules.viewIncludes[view] or [] html = "" - for partial in partials - compiler = jade.compile(partial, doctype: "html") - html += compiler(locals) + for compiledPartial in compiledPartials + d = new Date() + html += compiledPartial(locals) return html moduleIncludesAvailable: (view) -> diff --git a/services/web/app/views/project/editor/pdf.jade b/services/web/app/views/project/editor/pdf.jade index 492f75f582..4463043435 100644 --- a/services/web/app/views/project/editor/pdf.jade +++ b/services/web/app/views/project/editor/pdf.jade @@ -36,11 +36,19 @@ div.full-size.pdf(ng-controller="PdfController") i.fa.fa-fw(ng-class="{'fa-check': draft}") |  #{translate("fast")}  span.subdued [draft] - li.dropdown-header #{translate("file_checks")} + li.dropdown-header #{translate("compile_time_checks")} + li + a(href, ng-click="stop_on_validation_error = true") + i.fa.fa-fw(ng-class="{'fa-check': stop_on_validation_error}") + |  #{translate("stop_on_validation_error")} + li + a(href, ng-click="stop_on_validation_error = false") + i.fa.fa-fw(ng-class="{'fa-check': !stop_on_validation_error}") + |  #{translate("ignore_validation_errors")} li a(href, ng-click="recompile({check:true})") i.fa.fa-fw() - |  #{translate("run_syntax_check")} + |  #{translate("run_syntax_check_now")} a( href ng-click="stop()" @@ -105,6 +113,23 @@ div.full-size.pdf(ng-controller="PdfController") strong #{translate("compile_error")}. span #{translate("generic_failed_compile_message")}. + .alert.alert-danger(ng-show="pdf.failedCheck") + strong #{translate("failed_compile_check")}. + p + p.text-center(ng-show="!check") + a.text-info( + href, + ng-disabled="pdf.compiling", + ng-click="recompile({try:true})" + ) #{translate("failed_compile_check_try")} + | #{translate("failed_compile_option_or")} + a.text-info( + href, + ng-disabled="pdf.compiling", + ng-click="recompile({force:true})" + ) #{translate("failed_compile_check_ignore")} + | . + div(ng-repeat="entry in pdf.logEntries.all", ng-controller="PdfLogEntryController") .alert( ng-class="{\ diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index a31a336885..c79d654dbc 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -73,6 +73,12 @@ define [ $scope.pdf.view = 'errors' $scope.pdf.renderingError = true + # abort compile if syntax checks fail + $scope.stop_on_validation_error = localStorage("stop_on_validation_error:#{$scope.project_id}") or ide.$scope?.user?.betaProgram + $scope.$watch "stop_on_validation_error", (new_value, old_value) -> + if new_value? and old_value != new_value + localStorage("stop_on_validation_error:#{$scope.project_id}", new_value) + $scope.draft = localStorage("draft:#{$scope.project_id}") or false $scope.$watch "draft", (new_value, old_value) -> if new_value? and old_value != new_value @@ -83,10 +89,21 @@ define [ params = {} if options.isAutoCompile params["auto_compile"]=true + # if the previous run was a check, clear the error logs + $scope.pdf.logEntries = [] if $scope.check + # keep track of whether this is a compile or check + $scope.check = if options.check then true else false + event_tracking.sendMB "syntax-check-request" if options.check + # send appropriate check type to clsi + checkType = switch + when $scope.check then "validate" # validate only + when options.try then "silent" # allow use to try compile once + when $scope.stop_on_validation_error then "error" # try to compile + else "silent" # ignore errors return $http.post url, { rootDoc_id: options.rootDocOverride_id or null draft: $scope.draft - check: if options.check then "validate" else "silent" + check: checkType _csrf: window.csrfToken }, {params: params} @@ -105,6 +122,8 @@ define [ $scope.pdf.renderingError = false $scope.pdf.projectTooLarge = false $scope.pdf.compileTerminated = false + $scope.pdf.compileExited = false + $scope.pdf.failedCheck = false # make a cache to look up files by name fileByPath = {} @@ -131,9 +150,10 @@ define [ fetchLogs(fileByPath) else if response.status in ["validation-fail", "validation-pass"] $scope.pdf.view = 'pdf' - $scope.pdf.compileExited = true $scope.pdf.url = last_pdf_url $scope.shouldShowLogs = true + $scope.pdf.failedCheck = true if response.status is "validation-fail" + event_tracking.sendMB "syntax-check-#{response.status}" fetchLogs(fileByPath, { validation: true }) else if response.status == "exited" $scope.pdf.view = 'pdf' @@ -262,7 +282,8 @@ define [ else warnings.push result all = [].concat errors, warnings - logHints = HumanReadableLogs.parse {type: "Validation", all, errors, warnings} + logHints = HumanReadableLogs.parse {type: "Syntax", all, errors, warnings} + event_tracking.sendMB "syntax-check-return-count", {errors:errors.length, warnings:warnings.length} accumulateResults logHints processBiber = (log) -> @@ -347,6 +368,16 @@ define [ $scope.pdf.compiling = true + if options?.force + # for forced compile, turn off validation check and ignore errors + $scope.stop_on_validation_error = false + $scope.shouldShowLogs = false # hide the logs while compiling + event_tracking.sendMB "syntax-check-turn-off-checking" + + if options?.try + $scope.shouldShowLogs = false # hide the logs while compiling + event_tracking.sendMB "syntax-check-try-compile-anyway" + ide.$scope.$broadcast("flush-changes") options.rootDocOverride_id = getRootDocOverride_id() diff --git a/services/web/public/stylesheets/app/editor/pdf.less b/services/web/public/stylesheets/app/editor/pdf.less index 2183798650..12c86a6190 100644 --- a/services/web/public/stylesheets/app/editor/pdf.less +++ b/services/web/public/stylesheets/app/editor/pdf.less @@ -161,6 +161,10 @@ .dropdown { position: relative; } + .force-recompile { + margin-top: 10px; + text-align: right; + } } .synctex-controls {