opulent 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d6fdf705335f29c2162e3b2868398f4015ba29c
4
- data.tar.gz: be920ffc6c6349e76d76ef802425146e5ed734e8
3
+ metadata.gz: a41bc661663219aac5c2cbdbc6def8eedbe6abeb
4
+ data.tar.gz: 68d65112e22329817b60acdf1aa6aad48ad68653
5
5
  SHA512:
6
- metadata.gz: 5ff789a689f140eccd4f853322bef8bec37747e52187a62d8c87a59d799944732451d419cd534fd7fc06ab216a55ac48db0a027db98200b86ce912d85c89ad3f
7
- data.tar.gz: bfcb9e0566c3081bb99f2fe9f30ec697b7f78d35af9924e0fe0fd2835e04176007a62e90a072da4dc0361b23c902213d679d33cc24d486f085155176db67c21a
6
+ metadata.gz: fd1a7efd68cd841e5085ffc2b14f5158f8e8a4a4b0ca07ace88f400857797fc0cd7ba695822b33ad1638c884cf93c8816a70f2dd15021356c88e2d83db2f9446
7
+ data.tar.gz: 07249aab1bf67424862905d9f643b4dd1f80a95c4d59423bb61b9c09ee925d87ca91da6f5f54f80cf0edfc7c054254cbc35b1ede2fc888f2c321e003de1546d5
@@ -5,6 +5,7 @@ require_relative 'compiler/define.rb'
5
5
  require_relative 'compiler/eval.rb'
6
6
  require_relative 'compiler/filter.rb'
7
7
  require_relative 'compiler/node.rb'
8
+ require_relative 'compiler/require.rb'
8
9
  require_relative 'compiler/root.rb'
9
10
  require_relative 'compiler/text.rb'
10
11
 
@@ -19,7 +20,9 @@ module Opulent
19
20
  #
20
21
  # [:node_type, :value, :attributes, :children, :indent]
21
22
  #
22
- def initialize
23
+ # @param path [String] Current file path needed for require nodes
24
+ #
25
+ def initialize(settings = {})
23
26
  # Setup convention accessors
24
27
  @type = 0
25
28
  @value = 1
@@ -27,6 +30,12 @@ module Opulent
27
30
  @children = 3
28
31
  @indent = 4
29
32
 
33
+ # Set current compiled file
34
+ @path = File.dirname settings.delete :path
35
+
36
+ # Extract definitions for require directives
37
+ @definitions = settings.delete :definitions
38
+
30
39
  # Create the HTML Entities encoder/decoder
31
40
  @entities = HTMLEntities.new
32
41
 
@@ -52,7 +61,7 @@ module Opulent
52
61
 
53
62
  # Compile input nodes, replace them with their definitions and
54
63
  #
55
- # @param root [Array] Root node containing all document nodes
64
+ # @param root_node [Array] Root node containing all document nodes
56
65
  # @param context [Context] Context holding environment variables
57
66
  #
58
67
  def compile(root_node, context)
@@ -121,6 +130,8 @@ module Opulent
121
130
  "The \"#{data[0]}\" filter could not be recognized by Opulent."
122
131
  when :filter_load
123
132
  "The gem required for the \"#{data[0]}\" filter is not installed. You can install it by running:\n\n#{data[1]}"
133
+ when :require
134
+ "The required file #{data[0]} does not exist or an incorrect path has been specified."
124
135
  end
125
136
 
126
137
  # Reconstruct lines to display where errors occur
@@ -0,0 +1,24 @@
1
+ # @Opulent
2
+ module Opulent
3
+ # @Compiler
4
+ class Compiler
5
+ # Compile a new Opulent file using the current page context data
6
+ #
7
+ # @param node [Array] Node code generation data
8
+ # @param indent [Fixnum] Size of the indentation to be added
9
+ # @param context [Context] Processing environment data
10
+ #
11
+ def require_node(node, indent, context)
12
+ require_file = File.expand_path context.evaluate(node[@value]), @path
13
+ error :require, node[@value] unless File.file? require_file
14
+
15
+ data = {
16
+ definitions: @definitions,
17
+ overwrite: true
18
+ }
19
+ rendered = Engine.new(data).render_file require_file, &context.block
20
+
21
+ @code += indent_lines rendered, " " * indent
22
+ end
23
+ end
24
+ end
@@ -7,7 +7,7 @@ module Opulent
7
7
  # has its own context
8
8
  #
9
9
  class Context
10
- attr_accessor :binding, :name, :parent
10
+ attr_accessor :block, :binding, :name, :parent
11
11
 
12
12
  # Create a context from the environment binding, extended with the locals
13
13
  # given as arguments
@@ -15,10 +15,10 @@ module Opulent
15
15
  # @param locals [Hash] Binding extension
16
16
  # @param bind [Binding] Call environment binding
17
17
  #
18
- def initialize(locals = {}, &block)
18
+ def initialize(locals = {}, override = false, &block)
19
19
  @block = block || Proc.new
20
20
  @binding = if @block
21
- @block.binding.clone
21
+ override ? @block.binding : @block.binding.clone
22
22
  else
23
23
  Binding.new
24
24
  end
@@ -2,7 +2,7 @@
2
2
  module Opulent
3
3
  # Module method wrapper for creating a new engine instance
4
4
  #
5
- def Opulent.new(settings = nil)
5
+ def Opulent.new(settings = {})
6
6
  return Engine.new settings
7
7
  end
8
8
 
@@ -10,9 +10,17 @@ module Opulent
10
10
  class Engine
11
11
  attr_reader :nodes, :preamble, :buffer
12
12
 
13
- def initialize(settings = nil)
14
- # Update render settings
15
- Settings.update_settings settings if settings
13
+ # Update render settings
14
+ #
15
+ # @param settings [Hash] Opulent settings override
16
+ # @param definitions [Hash] Definitions from previously parsed files
17
+ # @param overwrite [Boolean] Write changes directly to the parent binding
18
+ #
19
+ def initialize(settings = {})
20
+ @definitions = settings.delete(:definitions) || {}
21
+ @overwrite = settings.delete :overwrite
22
+
23
+ Settings.update_settings settings unless settings.empty?
16
24
  end
17
25
 
18
26
  # Analyze the input code and check for matching tokens. In case no match was
@@ -23,8 +31,9 @@ module Opulent
23
31
  # @param block [Proc] Processing environment data
24
32
  #
25
33
  def render_file(file, locals = {}, &block)
26
- # Render the file
27
- render File.read(file), locals, &block
34
+ @mode = :file
35
+
36
+ render file, locals, &block
28
37
  end
29
38
 
30
39
  # Analyze the input code and check for matching tokens. In case no match was
@@ -34,19 +43,22 @@ module Opulent
34
43
  # @param locals [Hash] Render call local variables
35
44
  # @param block [Proc] Processing environment data
36
45
  #
37
- def render(code, locals = {}, &block)
46
+ def render(input, locals = {}, &block)
47
+ # Get input code
48
+ @code = read input
49
+
38
50
  # Get the nodes tree
39
- @nodes = Parser.new.parse code
51
+ @nodes, @definitions = Parser.new(@definitions).parse @code
40
52
 
41
53
  # @TODO
42
54
  # Implement precompiled template handling
43
55
  @preamble = @nodes.inspect.inspect
44
56
 
45
57
  # Create a new context based on our rendering environment
46
- @context = Context.new locals, &block
58
+ @context = Context.new locals, @overwrite, &block
47
59
 
48
60
  # Compile our syntax tree using input context
49
- @output = Compiler.new.compile @nodes, @context
61
+ @output = Compiler.new({path: @file, definitions: @definitions}).compile @nodes, @context
50
62
 
51
63
  # puts "Nodes\n---\n"
52
64
  # pp @nodes
@@ -56,5 +68,21 @@ module Opulent
56
68
 
57
69
  return @output
58
70
  end
71
+
72
+ # Read input parameter based on opening mode. If we have a file mode, we
73
+ # get its path and read the code. We need to reset the mode in case the next
74
+ # render call is on code, not on a file.
75
+ #
76
+ # @param input [String] Input file or code
77
+ #
78
+ def read(input)
79
+ if @mode == :file
80
+ @file = File.expand_path input; @mode = nil
81
+ return File.read @file
82
+ else
83
+ @file = File.expand_path __FILE__
84
+ return input
85
+ end
86
+ end
59
87
  end
60
88
  end
@@ -6,6 +6,7 @@ require_relative 'parser/eval.rb'
6
6
  require_relative 'parser/expression.rb'
7
7
  require_relative 'parser/filter.rb'
8
8
  require_relative 'parser/node.rb'
9
+ require_relative 'parser/require.rb'
9
10
  require_relative 'parser/root.rb'
10
11
  require_relative 'parser/text.rb'
11
12
 
@@ -13,19 +14,23 @@ require_relative 'parser/text.rb'
13
14
  module Opulent
14
15
  # @Parser
15
16
  class Parser
16
- attr_reader :type, :value, :options, :children, :indent
17
+ attr_reader :type, :value, :options, :children, :indent, :definitions
17
18
 
18
19
  # All node Objects (Array) must follow the next convention in order
19
20
  # to make parsing faster
20
21
  #
21
22
  # [:node_type, :value, :attributes, :children, :indent]
22
23
  #
23
- def initialize
24
+ def initialize(definitions = {})
25
+ # Convention accessors
24
26
  @type = 0
25
27
  @value = 1
26
28
  @options = 2
27
29
  @children = 3
28
30
  @indent = 4
31
+
32
+ # Node definitions encountered up to the current point
33
+ @definitions = definitions
29
34
  end
30
35
 
31
36
  # Initialize the parsing process by splitting the code into lines and
@@ -39,17 +44,15 @@ module Opulent
39
44
  # Split the code into lines and parse them one by one
40
45
  @code = code.lines
41
46
 
42
- # Node definitions encountered up to the current point
43
- @definitions = {}
44
-
45
47
  # Current line index
46
48
  @i = -1
47
49
 
48
50
  # Initialize root node
49
51
  @root = [:root, nil, {}, [], -1]
50
52
 
51
- # Get all nodes starting from the root element
52
- root @root
53
+ # Get all nodes starting from the root element and return output
54
+ # nodes and definitions
55
+ [root(@root), @definitions]
53
56
  end
54
57
 
55
58
  # Check and accept or reject a given token as long as we have tokens
@@ -0,0 +1,29 @@
1
+ # @Opulent
2
+ module Opulent
3
+ # @Parser
4
+ class Parser
5
+ # Check if we match a new node definition to use within our page.
6
+ #
7
+ # Definitions will not be recursive because, by the time we parse
8
+ # the definition children, the definition itself is not in the
9
+ # knowledgebase yet.
10
+ #
11
+ # However, we may use previously defined nodes inside new definitions,
12
+ # due to the fact that they are known at parse time.
13
+ #
14
+ # @param nodes [Array] Parent node to which we append to
15
+ #
16
+ def require_file(parent, indent)
17
+ if(match = accept :require)
18
+ # Process data
19
+ name = accept(:exp_string, :*)
20
+
21
+ # Create node
22
+ require_node = [:require, name, {}, [], indent]
23
+
24
+ # Add to parent
25
+ parent[@children] << require_node
26
+ end
27
+ end
28
+ end
29
+ end
@@ -36,7 +36,8 @@ module Opulent
36
36
  evaluate(parent, indent) ||
37
37
  filter(parent, indent) ||
38
38
  block_yield(parent, indent) ||
39
- block(parent, indent)
39
+ block(parent, indent) ||
40
+ require_file(parent, indent)
40
41
 
41
42
  # Throw an error if we couldn't find a valid node
42
43
  error :unknown_node_type unless current_node
@@ -1,6 +1,6 @@
1
1
  module Opulent
2
2
  # Opulent Keywords
3
- Keywords = %i(def block yield if else elsif unless case when each while until)
3
+ Keywords = %i(def block yield require if else elsif unless case when each while until)
4
4
 
5
5
  # @Tokens
6
6
  class Tokens
@@ -29,6 +29,9 @@ module Opulent
29
29
  # Definition
30
30
  def: /\Adef +/,
31
31
 
32
+ # Require file
33
+ require: /\Arequire +/,
34
+
32
35
  # Node Attributes
33
36
  attributes_bracket: /\A\(\[\{/,
34
37
  extend_attributes: /\A(\+)/,
@@ -1,4 +1,4 @@
1
1
  # @Opulent
2
2
  module Opulent
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opulent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Grozav
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-09 00:00:00.000000000 Z
11
+ date: 2015-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -147,6 +147,7 @@ files:
147
147
  - lib/opulent/compiler/eval.rb
148
148
  - lib/opulent/compiler/filter.rb
149
149
  - lib/opulent/compiler/node.rb
150
+ - lib/opulent/compiler/require.rb
150
151
  - lib/opulent/compiler/root.rb
151
152
  - lib/opulent/compiler/text.rb
152
153
  - lib/opulent/context.rb
@@ -162,6 +163,7 @@ files:
162
163
  - lib/opulent/parser/expression.rb
163
164
  - lib/opulent/parser/filter.rb
164
165
  - lib/opulent/parser/node.rb
166
+ - lib/opulent/parser/require.rb
165
167
  - lib/opulent/parser/root.rb
166
168
  - lib/opulent/parser/text.rb
167
169
  - lib/opulent/settings.rb