class RuboCop::Markdown::Preprocess
by commenting out all non-code lines
Transform source Markdown file into valid Ruby file
def autodetect?
Whether to try to detect Ruby by parsing codeblock.
def autodetect? config["Markdown"]&.fetch("Autodetect", true) end
def call(src)
def call(src) src.gsub(MD_REGEXP) do |full_match| m = Regexp.last_match open_backticks = m[1] syntax = m[2] code = m[3] close_backticks = m[4] markdown = m[5] if markdown # We got markdown outside of a codeblock comment_lines(markdown) elsif ruby_codeblock?(syntax, code) # The codeblock we parsed is assumed ruby, keep as is and append markers to backticks "#{comment_lines(open_backticks + syntax)}\n#{code}#{comment_lines(close_backticks)}" else # The codeblock is not relevant, comment it out comment_lines(full_match) end end end
def comment_lines(src)
def comment_lines(src) src.gsub(/^/, "##{MARKER}") end
def initialize(file)
def initialize(file) @config = Markdown.config_store.for(file) end
def maybe_ruby?(syntax)
Check codeblock attribute to prevent from parsing
def maybe_ruby?(syntax) (autodetect? && syntax.empty?) || ruby?(syntax) end
def restore!(src)
def restore!(src) src.gsub!(/^#\s*#{MARKER}/m, "") end
def restore_and_save!(file)
using preproccessed source buffer.
When autocorrect is applied, RuboCop re-writes the file
Revert preprocess changes.
def restore_and_save!(file) contents = File.read(file) restore!(contents) File.write(file, contents) end
def ruby?(syntax)
def ruby?(syntax) RUBY_TYPES.include?(syntax) end
def ruby_codeblock?(syntax, src)
def ruby_codeblock?(syntax, src) maybe_ruby?(syntax) && valid_syntax?(syntax, src) end
def valid_syntax?(syntax, src)
Invalid Ruby code (or non-Ruby) returns `nil`.
Try to parse with Ripper
def valid_syntax?(syntax, src) return true if ruby?(syntax) && warn_invalid? !Ripper.sexp(src).nil? end
def warn_invalid?
def warn_invalid? config["Markdown"]&.fetch("WarnInvalid", true) end