opulent 1.0.2 → 1.0.3

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
  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