diff --git a/services/web/app/views/project/editor/pdf.jade b/services/web/app/views/project/editor/pdf.jade index ce5bd16b53..34c9ece719 100644 --- a/services/web/app/views/project/editor/pdf.jade +++ b/services/web/app/views/project/editor/pdf.jade @@ -100,11 +100,35 @@ div.full-size.pdf(ng-controller="PdfController") 'alert-info': entry.level == 'typesetting'\ }" ng-click="openInEditor(entry)" + ng-init="feedbackSent = false;" ) span.line-no span(ng-show="entry.file") {{ entry.file }} span(ng-show="entry.line") , line {{ entry.line }} p.entry-message(ng-show="entry.message") {{ entry.message }} + .card.card-hint(ng-if="entry.humanReadableHint") + figure.card-hint-icon-container + i.fa.fa-lightbulb-o(aria-hidden="true") + p.card-hint-text(ng-show="entry.humanReadableHint", ng-bind-html="entry.humanReadableHint") + .card-hint-actions + .card-hint-ext-link + a(ng-href="{{ entry.extraInfoURL }}", target="_blank") + i.fa.fa-external-link + | #{translate("log_hint_extra_info")} + .card-hint-feedback( + ng-show="!feedbackSent" + ng-class="entry.ruleId" + ) + label.card-hint-feedback-label #{translate("log_hint_feedback_label")} + a.card-hint-feedback-positive( + ng-click="feedbackSent = true;" + ) #{translate("answer_yes")} + span  /  + a.card-hint-feedback-negative( + ng-click="feedbackSent = true;" + ) #{translate("answer_no")} + .card-hint-feedback(ng-show="feedbackSent") + label.card-hint-feedback-label #{translate("log_hint_feedback_gratitude")} p.entry-content(ng-show="entry.content") {{ entry.content }} p diff --git a/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogs.coffee b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogs.coffee new file mode 100644 index 0000000000..31fc11b6a3 --- /dev/null +++ b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogs.coffee @@ -0,0 +1,19 @@ +define [ + "libs/latex-log-parser" + "ide/human-readable-logs/HumanReadableLogsRules" +], (LogParser, ruleset) -> + parse : (rawLog, options) -> + parsedLogEntries = LogParser.parse(rawLog, options) + + _getRule = (logMessage) -> + return rule for rule in ruleset when rule.regexToMatch.test logMessage + + for entry in parsedLogEntries.all + ruleDetails = _getRule entry.message + + if (ruleDetails?) + entry.ruleId = 'hint_' + ruleDetails.regexToMatch.toString().replace(/[^a-zA-Z0-9]/g, '_').toLowerCase() if ruleDetails.regexToMatch? + entry.humanReadableHint = ruleDetails.humanReadableHint if ruleDetails.humanReadableHint? + entry.extraInfoURL = ruleDetails.extraInfoURL if ruleDetails.extraInfoURL? + + return parsedLogEntries diff --git a/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee new file mode 100644 index 0000000000..a94e756244 --- /dev/null +++ b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee @@ -0,0 +1,43 @@ +define -> [ + # regexToMatch: /Too many }'s/ + # extraInfoURL: "" + # humanReadableHint: """ + # The reason LaTeX thinks there are too many }'s here is that the opening curly brace is missing after the \\date control sequence and before the word December, so the closing curly brace is seen as one too many (which it is!). + # """ + # , + # regexToMatch: /Undefined control sequence/ + # extraInfoURL: "/learn/Errors:Undefined_control_sequence." + # humanReadableHint: """ + # In this example, LaTeX is complaining that it has no such command ("control sequence") as \\dtae. Obviously it's been mistyped, but only a human can detect that fact: all LaTeX knows is that \\dtae is not a command it knows about: it's undefined. + # """ + # , + # regexToMatch: /Missing \$ inserted/ + # extraInfoURL: "/learn/Errors:Missing_$_inserted" + # humanReadableHint: """ + # A character that can only be used in the mathematics was inserted in normal text. If you intended to use mathematics mode, then use $...$ or \\begin{math}...\\end{math} or use the 'quick math mode': \\ensuremath{...}. + # """ + # , + # regexToMatch: /Runaway argument/ + # extraInfoURL: "/learn/Errors:Undefined_control_sequence." + # humanReadableHint: """ + # In this error, the closing curly brace has been omitted from the date. It's the opposite of the error of too many }'s, and it results in \\maketitle trying to format the title page while LaTeX is still expecting more text for the date! + # """ + # , + # regexToMatch: /Underfull \\hbox/ + # extraInfoURL: "/learn/Errors:Underfull_%5Chbox" + # humanReadableHint: """ + # This is a warning that LaTeX cannot stretch the line wide enough to fit, without making the spacing bigger than its currently permitted maximum. The badness (0-10,000) indicates how severe this is (here you can probably ignore a badness of 1394). + # """ + # , + # regexToMatch: /Overfull \\hbox/ + # extraInfoURL: "" + # humanReadableHint: """ + # An overfull \\hbox means that there is a hyphenation or justification problem: moving the last word on the line to the next line would make the spaces in the line wider than the current limit; keeping the word on the line would make the spaces smaller than the current limit, so the word is left on the line, but with the minimum allowed space between words, and which makes the line go over the edge. + # """ + # , + # regexToMatch: /LaTeX Error: File .* not found/ + # extraInfoURL: "/learn/Errors:missing_package" + # humanReadableHint: """ + # When you use the \\usepackage command to request LaTeX to use a certain package, it will look for a file with the specified name and the filetype .sty. In this case the user has mistyped the name of the paralist package, so it's easy to fix. + # """ +] diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 37b055a204..f503437407 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -1,9 +1,9 @@ define [ "base" "ace/ace" - "libs/latex-log-parser" + "ide/human-readable-logs/HumanReadableLogs" "libs/bib-log-parser" -], (App, Ace, LogParser, BibLogParser) -> +], (App, Ace, HumanReadableLogs, BibLogParser) -> App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, localStorage) -> # enable per-user containers if querystring includes isolated=true @@ -173,11 +173,11 @@ define [ accumulateResults = (newEntries) -> for key in ['all', 'errors', 'warnings'] logEntries[key] = logEntries[key].concat newEntries[key] - + # use the parsers for each file type processLog = (log) -> $scope.pdf.rawLog = log - {errors, warnings, typesetting} = LogParser.parse(log, ignoreDuplicates: true) + {errors, warnings, typesetting} = HumanReadableLogs.parse(log, ignoreDuplicates: true) all = [].concat errors, warnings, typesetting accumulateResults {all, errors, warnings} diff --git a/services/web/public/stylesheets/app/editor/pdf.less b/services/web/public/stylesheets/app/editor/pdf.less index 6e813d5eaf..f77d497eb0 100644 --- a/services/web/public/stylesheets/app/editor/pdf.less +++ b/services/web/public/stylesheets/app/editor/pdf.less @@ -177,4 +177,79 @@ .keyboard-shortcut { white-space: nowrap; -} \ No newline at end of file +} + +.card-hint:extend(.card-thin) { + margin-top: 10px; + + &-icon-container { + background: currentColor; + width: 2.5rem; + height: 2.5rem; + font-size: 1.5rem; + text-align: center; + border-radius: 50%; + float: left; + margin-right: 10px; + + .fa { + color: #FFF; + } + + .alert-danger & { + color: @alert-danger-border; + } + + .alert-warning & { + color: @alert-warning-border; + } + + .alert-info & { + color: @alert-info-border; + } + + } + + &-text, + &-feedback-label { + color: @gray-dark; + font-size: 0.9rem; + margin-bottom: 20px; + } + + &-feedback-label { + font-size: inherit; + margin-right: 0.5em; + margin-bottom: 0; + font-weight: normal; + } + + &-ext-link, + &-feedback { + display: inline-block; + font-size: 0.8rem; + } + + &-actions a { + .alert-danger & { + color: @alert-danger-text; + } + + .alert-warning & { + color: @alert-warning-text; + } + + .alert-info & { + color: @alert-info-text; + } + } + + &-feedback { + color: @gray-dark; + float: right; + } + + & + p { + margin-top: 20px; + } +}