actionview_precompiler 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fadda94921df406ea9a921ae1c2a0ef61cb9a70a5a082ed906ead3a91ca0ab79
4
- data.tar.gz: a4eb7f984757e30d29eecdf348dc4ce1456f1f2d51e1092dd1bbc86b50d5511a
3
+ metadata.gz: 8f61275e9c390cf6a14ce7a3fa9bc4fb4473887547e7da8f07587cd26144b8c7
4
+ data.tar.gz: c125ff85f50d91ca77b80ee0eef47cb51e70373a17e2fc8c99d3b826e1176348
5
5
  SHA512:
6
- metadata.gz: c86dcaa26a379be5cb1832c7ea036e0dcca6ea2a26582706aa54fc35ba9abc95cd23507bba329e1f6968b70516878b5b8ea153bf419c7b2b67bf249197e3f430
7
- data.tar.gz: f00fd1a1202d766df59977b982c75364dfe350f54a47131f74dde6ba0413c9e19b14818b2bc56f94f26521b3516bf383319fcc7a3663a9dd3bbf8c89f2fae269
6
+ metadata.gz: 9e6d53ba2a4eb030cff6d57635a7d0e77eec0016e1c1af6255f9f134d438030ec4f45669bcd506dd00b1f8d36a64138b9690c3cd4f17dcfc4fe9e7c7562ec72f
7
+ data.tar.gz: bcc61e6a911a98886b74bfc8df1c29b6b6b3efabfbc50bf0178b34f3a7948867bfeaa7f2aec79945363fa34146b974909893c3e405033540b2bbcee0024c74cc
data/README.md CHANGED
@@ -11,7 +11,7 @@ Right now this assumes every template with the same `virtual_path` takes the sam
11
11
  A curse/blessing/actually still a curse of this approach is that mis-predicting render calls doesn't cause any issues, it just wastes RAM.
12
12
 
13
13
  Templates are half-compiled using standard ActionView handlers, so this should work for erb/builder/haml/whatever.
14
- Parsing is done using Ruby 2.6's `RubyVM::AbstractSyntaxTree`.
14
+ Parsing is done using either Ruby 2.6's `RubyVM::AbstractSyntaxTree` or JRuby's parser.
15
15
 
16
16
  ## Installation
17
17
 
@@ -1,4 +1,5 @@
1
1
  require "actionview_precompiler/version"
2
+ require "actionview_precompiler/ast_parser"
2
3
  require "actionview_precompiler/template_parser"
3
4
  require "actionview_precompiler/render_parser"
4
5
  require "actionview_precompiler/precompiler"
@@ -0,0 +1,5 @@
1
+ if RUBY_ENGINE == 'jruby'
2
+ require "actionview_precompiler/ast_parser/jruby"
3
+ else
4
+ require "actionview_precompiler/ast_parser/ruby26"
5
+ end
@@ -0,0 +1,68 @@
1
+ module ActionviewPrecompiler
2
+ module ASTParser
3
+ class Node
4
+ def self.wrap(node)
5
+ if org::jruby::ast::Node === node
6
+ new(node)
7
+ else
8
+ node
9
+ end
10
+ end
11
+
12
+ def initialize(node)
13
+ @node = node
14
+ end
15
+
16
+ def children
17
+ @children ||= @node.child_nodes.map do |child|
18
+ self.class.wrap(child)
19
+ end
20
+ end
21
+
22
+ def array?; org::jruby::ast::ArrayNode === @node; end
23
+ def fcall?; org::jruby::ast::FCallNode === @node; end
24
+ def hash?; org::jruby::ast::HashNode === @node; end
25
+ def string?; org::jruby::ast::StrNode === @node; end
26
+ def symbol?; org::jruby::ast::SymbolNode === @node; end
27
+
28
+ def argument_nodes
29
+ @node.args_node.to_a[0...@node.args_node.size].map do |arg|
30
+ self.class.wrap(arg)
31
+ end
32
+ end
33
+
34
+ def to_hash
35
+ @node.pairs.each_with_object({}) do |pair, object|
36
+ object[self.class.wrap(pair.key)] = self.class.wrap(pair.value)
37
+ end
38
+ end
39
+
40
+ def to_string
41
+ @node.value
42
+ end
43
+
44
+ def to_symbol
45
+ @node.name
46
+ end
47
+
48
+ def fcall_named?(name)
49
+ fcall? &&
50
+ @node.name == name &&
51
+ @node.args_node &&
52
+ org::jruby::ast::ArrayNode === @node.args_node
53
+ end
54
+ end
55
+
56
+ def parse(code)
57
+ Node.wrap(JRuby.parse(code))
58
+ end
59
+
60
+ def node?(node)
61
+ Node === node
62
+ end
63
+
64
+ def fcall?(node, name)
65
+ node.fcall_named?(name)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,88 @@
1
+ module ActionviewPrecompiler
2
+ module ASTParser
3
+ class Node
4
+ def self.wrap(node)
5
+ if RubyVM::AbstractSyntaxTree::Node === node
6
+ new(node)
7
+ else
8
+ node
9
+ end
10
+ end
11
+
12
+ def initialize(node)
13
+ @node = node
14
+ end
15
+
16
+ def children
17
+ @children ||= @node.children.map do |child|
18
+ self.class.wrap(child)
19
+ end
20
+ end
21
+
22
+ def inspect
23
+ "#<#{self.class} #{@node.inspect}>"
24
+ end
25
+
26
+ def argument_nodes
27
+ children[1].children[0...-1]
28
+ end
29
+
30
+ def array?
31
+ type == :ARRAY
32
+ end
33
+
34
+ def fcall?
35
+ type == :FCALL
36
+ end
37
+
38
+ def hash?
39
+ type == :HASH
40
+ end
41
+
42
+ def string?
43
+ type == :STR && String === children[0]
44
+ end
45
+
46
+ def symbol?
47
+ type == :LIT && Symbol === children[0]
48
+ end
49
+
50
+ def to_hash
51
+ children[0].children[0..-2].each_slice(2).to_h
52
+ end
53
+
54
+ def to_string
55
+ children[0]
56
+ end
57
+
58
+ def to_symbol
59
+ children[0]
60
+ end
61
+
62
+ def fcall_named?(name)
63
+ fcall? &&
64
+ children[0] == name &&
65
+ children[1] &&
66
+ children[1].array?
67
+ end
68
+
69
+ private
70
+
71
+ def type
72
+ @node.type
73
+ end
74
+ end
75
+
76
+ def parse(code)
77
+ Node.wrap(RubyVM::AbstractSyntaxTree.parse(code))
78
+ end
79
+
80
+ def node?(node)
81
+ Node === node
82
+ end
83
+
84
+ def fcall?(node, name)
85
+ node.fcall_named?(name)
86
+ end
87
+ end
88
+ end
@@ -10,9 +10,11 @@ module ActionviewPrecompiler
10
10
  end
11
11
 
12
12
  class RenderParser
13
+ include ASTParser
14
+
13
15
  def initialize(code)
14
16
  @code = code
15
- @code = RubyVM::AbstractSyntaxTree.parse(code) if code.is_a?(String)
17
+ @code = parse(code) if code.is_a?(String)
16
18
  end
17
19
 
18
20
  def render_calls
@@ -25,18 +27,17 @@ module ActionviewPrecompiler
25
27
  private
26
28
 
27
29
  def parse_render(node)
28
- node = node.children[1]
29
- node = node.children
30
- if (node.length == 2 || node.length == 3) && node[0].type == :STR
30
+ node = node.argument_nodes
31
+ if (node.length == 1 || node.length == 2) && node[0].string?
31
32
  # FIXME: from template vs controller
32
33
  options = {}
33
34
  options[:partial] = node[0]
34
- if node.length == 3
35
- return unless node[1].type == :HASH
35
+ if node.length == 2
36
+ return unless node[1].hash?
36
37
  options[:locals] = node[1]
37
38
  end
38
39
  return parse_render_from_options(options)
39
- elsif node.length == 2 && node[0].type == :HASH
40
+ elsif node.length == 1 && node[0].hash?
40
41
  options = parse_hash_to_symbols(node[0])
41
42
  return parse_render_from_options(options)
42
43
  else
@@ -45,9 +46,7 @@ module ActionviewPrecompiler
45
46
  end
46
47
 
47
48
  def parse_hash(node)
48
- return nil unless node.type == :HASH
49
-
50
- node.children[0].children[0..-2].each_slice(2).to_h
49
+ node.hash? && node.to_hash
51
50
  end
52
51
 
53
52
  def parse_hash_to_symbols(node)
@@ -86,8 +85,8 @@ module ActionviewPrecompiler
86
85
  parsed_locals = parse_hash(locals)
87
86
  return nil unless parsed_locals
88
87
  locals_keys = parsed_locals.keys.map do |local|
89
- return nil unless local.type == :LIT
90
- local.children[0]
88
+ return nil unless local.symbol?
89
+ local.to_symbol
91
90
  end
92
91
  else
93
92
  locals = nil
@@ -98,11 +97,11 @@ module ActionviewPrecompiler
98
97
  end
99
98
 
100
99
  def parse_str(node)
101
- node.children[0] if node.type == :STR && String === node.children[0]
100
+ node.string? && node.to_string
102
101
  end
103
102
 
104
103
  def parse_sym(node)
105
- node.children[0] if node.type == :LIT && Symbol === node.children[0]
104
+ node.symbol? && node.to_symbol
106
105
  end
107
106
 
108
107
  def debug(message)
@@ -110,7 +109,7 @@ module ActionviewPrecompiler
110
109
  end
111
110
 
112
111
  def extract_render_nodes(node)
113
- return [] unless RubyVM::AbstractSyntaxTree::Node === node
112
+ return [] unless node?(node)
114
113
  renders = node.children.flat_map { |c| extract_render_nodes(c) }
115
114
  if render_call?(node)
116
115
  renders << node
@@ -119,10 +118,7 @@ module ActionviewPrecompiler
119
118
  end
120
119
 
121
120
  def render_call?(node)
122
- node.type == :FCALL &&
123
- node.children[0] == :render &&
124
- node.children[1] &&
125
- node.children[1].type == :ARRAY
121
+ fcall?(node, :render)
126
122
  end
127
123
  end
128
124
  end
@@ -2,6 +2,8 @@ require "action_view"
2
2
 
3
3
  module ActionviewPrecompiler
4
4
  class TemplateParser
5
+ include ASTParser
6
+
5
7
  attr_reader :filename, :basename, :handler
6
8
 
7
9
  class FakeTemplate
@@ -27,7 +29,7 @@ module ActionviewPrecompiler
27
29
  end
28
30
 
29
31
  def parsed
30
- @parsed ||= RubyVM::AbstractSyntaxTree.parse(compiled_source)
32
+ @parsed ||= parse(compiled_source)
31
33
  end
32
34
 
33
35
  def compiled_source
@@ -1,3 +1,3 @@
1
1
  module ActionviewPrecompiler
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview_precompiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-03 00:00:00.000000000 Z
11
+ date: 2019-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.0'
33
+ version: '1.17'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.0'
40
+ version: '1.17'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -73,16 +73,11 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - ".gitignore"
77
- - CODE_OF_CONDUCT.md
78
- - Gemfile
79
- - Gemfile.lock
80
76
  - README.md
81
- - Rakefile
82
- - actionview_precompiler.gemspec
83
- - bin/console
84
- - bin/setup
85
77
  - lib/actionview_precompiler.rb
78
+ - lib/actionview_precompiler/ast_parser.rb
79
+ - lib/actionview_precompiler/ast_parser/jruby.rb
80
+ - lib/actionview_precompiler/ast_parser/ruby26.rb
86
81
  - lib/actionview_precompiler/parsed_filename.rb
87
82
  - lib/actionview_precompiler/precompiler.rb
88
83
  - lib/actionview_precompiler/render_parser.rb
data/.gitignore DELETED
@@ -1,8 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
data/CODE_OF_CONDUCT.md DELETED
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at john@hawthorn.email. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "pry"
4
-
5
- # Specify your gem's dependencies in actionview_precompiler.gemspec
6
- gemspec
data/Gemfile.lock DELETED
@@ -1,62 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- actionview_precompiler (0.1.0)
5
- actionview (>= 6.0.a)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- actionview (6.0.0.rc1)
11
- activesupport (= 6.0.0.rc1)
12
- builder (~> 3.1)
13
- erubi (~> 1.4)
14
- rails-dom-testing (~> 2.0)
15
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
16
- activesupport (6.0.0.rc1)
17
- concurrent-ruby (~> 1.0, >= 1.0.2)
18
- i18n (>= 0.7, < 2)
19
- minitest (~> 5.1)
20
- tzinfo (~> 1.1)
21
- zeitwerk (~> 2.1, >= 2.1.4)
22
- builder (3.2.3)
23
- coderay (1.1.2)
24
- concurrent-ruby (1.1.5)
25
- crass (1.0.4)
26
- erubi (1.8.0)
27
- i18n (1.6.0)
28
- concurrent-ruby (~> 1.0)
29
- loofah (2.2.3)
30
- crass (~> 1.0.2)
31
- nokogiri (>= 1.5.9)
32
- method_source (0.9.2)
33
- mini_portile2 (2.4.0)
34
- minitest (5.11.3)
35
- nokogiri (1.10.3)
36
- mini_portile2 (~> 2.4.0)
37
- pry (0.12.2)
38
- coderay (~> 1.1.0)
39
- method_source (~> 0.9.0)
40
- rails-dom-testing (2.0.3)
41
- activesupport (>= 4.2.0)
42
- nokogiri (>= 1.6)
43
- rails-html-sanitizer (1.0.4)
44
- loofah (~> 2.2, >= 2.2.2)
45
- rake (12.3.2)
46
- thread_safe (0.3.6)
47
- tzinfo (1.2.5)
48
- thread_safe (~> 0.1)
49
- zeitwerk (2.1.5)
50
-
51
- PLATFORMS
52
- ruby
53
-
54
- DEPENDENCIES
55
- actionview_precompiler!
56
- bundler (~> 2.0)
57
- minitest (~> 5.0)
58
- pry
59
- rake (~> 12.0)
60
-
61
- BUNDLED WITH
62
- 2.0.1
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- end
9
-
10
- task :default => :test
@@ -1,31 +0,0 @@
1
- lib = File.expand_path("lib", __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "actionview_precompiler/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "actionview_precompiler"
7
- spec.version = ActionviewPrecompiler::VERSION
8
- spec.authors = ["John Hawthorn"]
9
- spec.email = ["john@hawthorn.email"]
10
-
11
- spec.summary = %q{Precompiles ActionView templates}
12
- spec.description = %q{Parses templates for render calls and uses them to precompile}
13
- spec.homepage = "https://github.com/jhawthorn/actionview_precompiler"
14
-
15
- # Specify which files should be added to the gem when it is released.
16
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
- end
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
23
-
24
- spec.required_ruby_version = ">= 2.6"
25
-
26
- spec.add_dependency "actionview", ">= 6.0.a"
27
-
28
- spec.add_development_dependency "bundler", "~> 2.0"
29
- spec.add_development_dependency "rake", "~> 12.0"
30
- spec.add_development_dependency "minitest", "~> 5.0"
31
- end
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "actionview_precompiler"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here