From e627190ac81914a28f91d91734622f6651520509 Mon Sep 17 00:00:00 2001 From: Sam Davies Date: Tue, 28 Jul 2020 13:35:30 +0100 Subject: [PATCH] WEB-3513: Parsing errors in chapter metadata are now labelled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't verify the metadata, but we do now add some location info so that it's possible to tell which file has the problem—rather than having to search through every single chapter to find the extra space in the indentation... --- app/lib/linting/linter.rb | 21 +++++++++++++++++++-- app/lib/parser/error.rb | 17 +++++++++++++++++ app/lib/parser/markdown_metadata.rb | 8 +++++++- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 app/lib/parser/error.rb diff --git a/app/lib/linting/linter.rb b/app/lib/linting/linter.rb index d88de75..61630f2 100644 --- a/app/lib/linting/linter.rb +++ b/app/lib/linting/linter.rb @@ -20,7 +20,7 @@ def lint(options: {}) output end - def lint_with_ui(options:, show_ui: true) # rubocop:disable Metrics/MethodLength + def lint_with_ui(options:, show_ui: true) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize with_spinner(title: 'Checking {{bold:publish.yaml}} exists', show: show_ui) do check_publish_file_exists end @@ -31,6 +31,11 @@ def lint_with_ui(options:, show_ui: true) # rubocop:disable Metrics/MethodLength end return unless annotations.blank? + with_spinner(title: 'Attempting to parse book', show: show_ui) do + book + end + return unless annotations.blank? + with_spinner(title: 'Validating image references', show: show_ui) do annotations.concat(Linting::ImageLinter.new(book: book).lint) end @@ -78,11 +83,23 @@ def check_publish_file_exists false end - def book + def book # rubocop:disable Metrics/MethodLength @book ||= begin parser = Parser::Publish.new(file: file) parser.parse end + rescue Parser::Error => e + line_number = (e.message.match(/at line (\d+)/)&.captures&.first&.to_i || 0) + 1 + annotations.push( + Annotation.new( + absolute_path: e.file, + annotation_level: 'failure', + start_line: line_number, + end_line: line_number, + message: e.message, + title: 'Unable to parse book.' + ) + ) end end end diff --git a/app/lib/parser/error.rb b/app/lib/parser/error.rb new file mode 100644 index 0000000..d6e66be --- /dev/null +++ b/app/lib/parser/error.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Parser + # An error for capturing parsing issues + class Error < StandardError + attr_reader :file + + def initialize(file:, error: nil, msg: nil) + message = "There was a problem parsing #{file}" + message += "\n#{error.class.name}\n#{error.message}" if error.present? + message += "\n#{msg}" if msg.present? + + super(message) + @file = file + end + end +end diff --git a/app/lib/parser/markdown_metadata.rb b/app/lib/parser/markdown_metadata.rb index aa7ef55..84b1f38 100644 --- a/app/lib/parser/markdown_metadata.rb +++ b/app/lib/parser/markdown_metadata.rb @@ -12,7 +12,13 @@ def extract_metadata end def metadata - @metadata ||= Psych.load(extract_metadata).deep_symbolize_keys + @metadata ||= begin + Psych.load(extract_metadata, symbolize_names: true).tap do |metadata| + raise Parser::Error.new(file: path, msg: 'Unable to locate metadata at the top of the markdown') unless metadata.present? + end + end + rescue Psych::SyntaxError => e + raise Parser::Error.new(file: path, error: e) end def simple_attributes