From 7d9c39427f8a8bb749e0dd47e6c4d4a577a9e48a Mon Sep 17 00:00:00 2001 From: Jimmy Domagala-Tang Date: Thu, 31 Aug 2023 11:22:52 -0400 Subject: [PATCH] Merge pull request #14160 from overleaf/ds-missing-package-errors Adding improved user facing messages for missing packages GitOrigin-RevId: d1ad4111b5f2c3596ee88ef69dab8094df065ee0 --- .../HumanReadableLogsHints.js | 100 +++++++++++++----- .../HumanReadableLogsPackageSuggestions.js | 43 +++++++- .../HumanReadableLogsRules.js | 39 +++++-- 3 files changed, 146 insertions(+), 36 deletions(-) diff --git a/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsHints.js b/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsHints.js index 21a5d8b0b0..50909a12db 100644 --- a/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsHints.js +++ b/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsHints.js @@ -1,5 +1,8 @@ import PropTypes from 'prop-types' -import packageSuggestions from './HumanReadableLogsPackageSuggestions' +import { + packageSuggestionsForCommands, + packageSuggestionsForEnvironments, +} from './HumanReadableLogsPackageSuggestions' function WikiLink({ url, children }) { if (window.wikiEnabled) { @@ -162,22 +165,25 @@ const hints = { ), }, hint_undefined_control_sequence: { - extraInfoURL: - 'https://www.overleaf.com/learn/Errors/Undefined_control_sequence', formattedContent: details => { - if (details?.length && packageSuggestions.has(details[0])) { + if (details?.length && packageSuggestionsForCommands.has(details[0])) { const command = details[0] - const suggestion = packageSuggestions.get(command) + const suggestion = packageSuggestionsForCommands.get(command) return ( <> - Undefined control sequence. You have used the command{' '} - {command}, which is part of the{' '} - {suggestion.name} package. Make sure to include the - package in your{' '} - - preamble - {' '} - using {suggestion.command}. +

+ We think you’ve got a missing package! The {command}{' '} + command won't work unless you include + {suggestion.command} in your{' '} + + document preamble + + .{' '} + + Learn more about packages + + . +

) } @@ -188,6 +194,61 @@ const hints = { a package, make sure you have included the package in your preamble using \usepackage {'{...}'}. +
+ + Learn more + +
+ + ) + }, + }, + hint_undefined_environment: { + formattedContent: details => { + if ( + details?.length && + packageSuggestionsForEnvironments.has(details[0]) + ) { + const environment = details[0] + const suggestion = packageSuggestionsForEnvironments.get(environment) + return ( + <> +

+ We think you’ve got a missing package! The{' '} + {environment} environment won't work unless you + include {suggestion.command} in your{' '} + + document preamble + + .{' '} + + Learn more about packages + + . +

+ + ) + } + return ( + <> + You have created an environment (using \begin + {'{…}'} and \end + {'{…}'} commands) which is not recognized. Make sure you have included + the required package for that environment in your preamble, and that + the environment is spelled correctly. +
+ + Learn more + +
) }, @@ -339,19 +400,6 @@ const hints = { ), }, - hint_environment_undefined: { - extraInfoURL: - 'https://www.overleaf.com/learn/Errors%2FLaTeX%20Error%3A%20Environment%20XXX%20undefined', - formattedContent: () => ( - <> - You have created an environment (using \begin - {'{…}'} and \end - {'{…}'} commands) which is not recognized. Make sure you have included - the required package for that environment in your preamble, and that the - environment is spelled correctly. - - ), - }, hint_somethings_wrong_perhaps_a_missing_item: { extraInfoURL: 'https://www.overleaf.com/learn/Errors/LaTeX_Error:_Something%27s_wrong--perhaps_a_missing_%5Citem', diff --git a/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsPackageSuggestions.js b/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsPackageSuggestions.js index ba043588c1..8f4dd0000b 100644 --- a/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsPackageSuggestions.js +++ b/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsPackageSuggestions.js @@ -1,7 +1,46 @@ -const suggestions = [ +const commandSuggestions = [ [ '\\includegraphics', { name: 'graphicx', command: '\\usepackage{graphicx}' }, ], + ['\\toprule', { name: 'booktabs', command: '\\usepackage{booktabs}' }], + ['\\midrule', { name: 'booktabs', command: '\\usepackage{booktabs}' }], + ['\\bottomrule', { name: 'booktabs', command: '\\usepackage{booktabs}' }], + ['\\cmidrule', { name: 'booktabs', command: '\\usepackage{booktabs}' }], + ['\\multirow', { name: 'multirow', command: '\\usepackage{multirow}' }], + ['\\justifying', { name: 'ragged2e', command: '\\usepackage{ragged2e}' }], + ['\\tag', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\notag', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\text', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\boldsymbol', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\eqref', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\iint', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\iiint', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['\\nmid', { name: 'amssymb', command: '\\usepackage{amssymb}' }], + ['\\varnothing', { name: 'amssymb', command: '\\usepackage{amssymb}' }], + ['\\Box', { name: 'amssymb', command: '\\usepackage{amssymb}' }], + ['\\citep', { name: 'natbib', command: '\\usepackage{natbib}' }], + ['\\citet', { name: 'natbib', command: '\\usepackage{natbib}' }], + ['\\url', { name: 'url', command: '\\usepackage{url}' }], + ['\\href', { name: 'hyperref', command: '\\usepackage{hyperref}' }], + ['\\texorpdfstring', { name: 'hyperref', command: '\\usepackage{hyperref}' }], + ['\\phantomsection', { name: 'hyperref', command: '\\usepackage{hyperref}' }], ] -export default new Map(suggestions) + +const environmentSuggestions = [ + ['justify', { name: 'ragged2e', command: '\\usepackage{ragged2e}' }], + ['align', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['align*', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['split', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['gather', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['cases', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['matrix', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['pmatrix', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['bmatrix', { name: 'amsmath', command: '\\usepackage{amsmath}' }], + ['subequations', { name: 'amsmath', command: '\\usepackage{amsmath}' }], +] + +const packageSuggestionsForCommands = new Map(commandSuggestions) +const packageSuggestionsForEnvironments = new Map(environmentSuggestions) + +export { packageSuggestionsForCommands, packageSuggestionsForEnvironments } diff --git a/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsRules.js b/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsRules.js index 7d1359e844..97ed03b35b 100644 --- a/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsRules.js +++ b/services/web/frontend/js/ide/human-readable-logs/HumanReadableLogsRules.js @@ -1,5 +1,8 @@ /* eslint-disable no-useless-escape */ -import packageSuggestions from './HumanReadableLogsPackageSuggestions' +import { + packageSuggestionsForCommands, + packageSuggestionsForEnvironments, +} from './HumanReadableLogsPackageSuggestions' const rules = [ { @@ -48,10 +51,34 @@ const rules = [ contentRegex: /^(?:l\.[0-9]+|<(?:recently read|inserted text|to be read again)>)\s*(\\\S+)/, improvedTitle: (currentTitle, details) => { - if (details?.length && packageSuggestions.has(details[0])) { + if (details?.length && packageSuggestionsForCommands.has(details[0])) { const command = details[0] - const suggestion = packageSuggestions.get(command) - return `${suggestion.command} is missing.` + const suggestion = packageSuggestionsForCommands.get(command) + return ( + + Is {suggestion.command} missing? + + ) + } + return currentTitle + }, + }, + { + ruleId: 'hint_undefined_environment', + regexToMatch: /LaTeX Error: Environment .+ undefined/, + contentRegex: /\\begin\{(\S+)\}/, + improvedTitle: (currentTitle, details) => { + if ( + details?.length && + packageSuggestionsForEnvironments.has(details[0]) + ) { + const environment = details[0] + const suggestion = packageSuggestionsForEnvironments.get(environment) + return ( + + Is {suggestion.command} missing? + + ) } return currentTitle }, @@ -108,10 +135,6 @@ const rules = [ ruleId: 'hint_no_author_given', regexToMatch: /No \\author given/, }, - { - ruleId: 'hint_environment_undefined', - regexToMatch: /LaTeX Error: Environment .+ undefined/, - }, { ruleId: 'hint_somethings_wrong_perhaps_a_missing_item', regexToMatch: /LaTeX Error: Something's wrong--perhaps a missing \\item/,