From 6705a94decce0c16445d1dbfcab83dcfef0aba9d Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Wed, 11 Nov 2020 17:46:15 +0000 Subject: [PATCH 1/3] Support setting the Erb parser on the factory --- lib/packwerk/parsers/factory.rb | 11 ++++++++++- test/unit/parsers/factory_test.rb | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/packwerk/parsers/factory.rb b/lib/packwerk/parsers/factory.rb index 0b9c5c96a..f5958621f 100644 --- a/lib/packwerk/parsers/factory.rb +++ b/lib/packwerk/parsers/factory.rb @@ -26,9 +26,18 @@ def for_path(path) when RUBY_REGEX @ruby_parser ||= Ruby.new when ERB_REGEX - @erb_parser ||= Erb.new + @erb_parser ||= erb_parser_class.new end end + + def erb_parser_class + @erb_parser_class || Erb + end + + def erb_parser_class=(klass) + @erb_parser_class = klass + @erb_parser = nil + end end end end diff --git a/test/unit/parsers/factory_test.rb b/test/unit/parsers/factory_test.rb index 93e747b4b..c62ef5413 100644 --- a/test/unit/parsers/factory_test.rb +++ b/test/unit/parsers/factory_test.rb @@ -23,6 +23,11 @@ class FactoryTest < Minitest::Test assert_instance_of(Parsers::Erb, factory.for_path("foo.html.erb")) assert_instance_of(Parsers::Erb, factory.for_path("foo.md.erb")) assert_instance_of(Parsers::Erb, factory.for_path("/sub/directory/foo.erb")) + + fake_class = Class.new + with_erb_parser_class(fake_class) do + assert_instance_of(fake_class, factory.for_path("foo.html.erb")) + end end test "#for_path gives nil for unknown path" do @@ -33,6 +38,13 @@ class FactoryTest < Minitest::Test private + def with_erb_parser_class(klass) + factory.erb_parser_class = klass + yield + ensure + factory.erb_parser_class = nil + end + def factory Parsers::Factory.instance end From edbc5b52b9943b952cfa2086c14a6f1384373956 Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Wed, 11 Nov 2020 17:48:31 +0000 Subject: [PATCH 2/3] Split reading the file from parsing the buffer --- lib/packwerk/parsers/erb.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/packwerk/parsers/erb.rb b/lib/packwerk/parsers/erb.rb index 702a7e1bc..03d3d3748 100644 --- a/lib/packwerk/parsers/erb.rb +++ b/lib/packwerk/parsers/erb.rb @@ -19,6 +19,10 @@ def initialize(parser_class: BetterHtml::Parser, ruby_parser: Ruby.new) def call(io:, file_path: "") buffer = Parser::Source::Buffer.new(file_path) buffer.source = io.read + parse_buffer(buffer, file_path: file_path) + end + + def parse_buffer(buffer, file_path:) parser = @parser_class.new(buffer, template_language: :html) to_ruby_ast(parser.ast, file_path) rescue EncodingError => e From 428e2e9c5b3058bffee8da6f1983f9d25bd1d9f6 Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Wed, 11 Nov 2020 20:05:04 +0000 Subject: [PATCH 3/3] Document how to set the custom ERB parser class --- USAGE.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/USAGE.md b/USAGE.md index 8819fd505..c8d1aedb6 100644 --- a/USAGE.md +++ b/USAGE.md @@ -67,6 +67,27 @@ Packwerk reads from the `packwerk.yml` configuration file in the root directory. | load_paths | All application autoload paths | list of load paths | | custom_associations | N/A | list of custom associations, if any | +### Using a custom ERB parser + +You can specify a custom ERB parser if needed. For example, if you're using `<%graphql>` tags from https://github.com/github/graphql-client in your ERBs, you can use a custom parser subclass to comment them out so that Packwerk can parse the rest of the file: + +```ruby +class CustomParser < Packwerk::Parsers::Erb + def parse_buffer(buffer, file_path:) + preprocessed_source = buffer.source + + # Comment out <%graphql ... %> tags. They won't contain any object + # references anyways. + preprocessed_source = preprocessed_source.gsub(/<%graphql/, "<%#") + + preprocessed_buffer = Parser::Source::Buffer.new(file_path) + preprocessed_buffer.source = preprocessed_source + super(preprocessed_buffer, file_path: file_path) + end +end + +Packwerk::Parsers::Factory.instance.erb_parser_class = CustomParser +``` ### Inflections