opulent 1.5.5 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +13 -0
  3. data/{LICENSE → LICENSE.md} +0 -0
  4. data/bin/opulent +0 -0
  5. data/lib/opulent.rb +10 -10
  6. data/lib/opulent/compiler.rb +15 -9
  7. data/lib/opulent/compiler/buffer.rb +123 -62
  8. data/lib/opulent/compiler/comment.rb +3 -4
  9. data/lib/opulent/compiler/control.rb +20 -26
  10. data/lib/opulent/compiler/define.rb +88 -36
  11. data/lib/opulent/compiler/doctype.rb +20 -22
  12. data/lib/opulent/compiler/eval.rb +23 -2
  13. data/lib/opulent/compiler/filter.rb +4 -5
  14. data/lib/opulent/compiler/node.rb +18 -12
  15. data/lib/opulent/compiler/root.rb +4 -5
  16. data/lib/opulent/compiler/text.rb +7 -2
  17. data/lib/opulent/compiler/yield.rb +2 -3
  18. data/lib/opulent/engine.rb +21 -20
  19. data/lib/opulent/exec.rb +21 -63
  20. data/lib/opulent/logger.rb +230 -3
  21. data/lib/opulent/parser.rb +14 -76
  22. data/lib/opulent/parser/comment.rb +45 -34
  23. data/lib/opulent/parser/control.rb +132 -111
  24. data/lib/opulent/parser/define.rb +15 -12
  25. data/lib/opulent/parser/doctype.rb +15 -15
  26. data/lib/opulent/parser/eval.rb +16 -6
  27. data/lib/opulent/parser/expression.rb +87 -84
  28. data/lib/opulent/parser/filter.rb +31 -25
  29. data/lib/opulent/parser/include.rb +38 -42
  30. data/lib/opulent/parser/node.rb +136 -118
  31. data/lib/opulent/parser/root.rb +24 -18
  32. data/lib/opulent/parser/text.rb +150 -123
  33. data/lib/opulent/parser/yield.rb +23 -23
  34. data/lib/opulent/settings.rb +70 -51
  35. data/lib/opulent/tokens.rb +17 -15
  36. data/lib/opulent/utils.rb +5 -4
  37. data/lib/opulent/version.rb +1 -1
  38. metadata +4 -43
  39. data/.libold/opulent.rb +0 -96
  40. data/.libold/opulent/context.rb +0 -80
  41. data/.libold/opulent/engine.rb +0 -88
  42. data/.libold/opulent/filter.rb +0 -101
  43. data/.libold/opulent/logger.rb +0 -67
  44. data/.libold/opulent/nodes.rb +0 -13
  45. data/.libold/opulent/nodes/block.rb +0 -29
  46. data/.libold/opulent/nodes/comment.rb +0 -35
  47. data/.libold/opulent/nodes/control.rb +0 -230
  48. data/.libold/opulent/nodes/define.rb +0 -42
  49. data/.libold/opulent/nodes/eval.rb +0 -41
  50. data/.libold/opulent/nodes/expression.rb +0 -28
  51. data/.libold/opulent/nodes/filter.rb +0 -70
  52. data/.libold/opulent/nodes/helper.rb +0 -69
  53. data/.libold/opulent/nodes/node.rb +0 -101
  54. data/.libold/opulent/nodes/root.rb +0 -62
  55. data/.libold/opulent/nodes/text.rb +0 -54
  56. data/.libold/opulent/nodes/theme.rb +0 -36
  57. data/.libold/opulent/parser.rb +0 -252
  58. data/.libold/opulent/parser/block.rb +0 -70
  59. data/.libold/opulent/parser/comment.rb +0 -32
  60. data/.libold/opulent/parser/control.rb +0 -83
  61. data/.libold/opulent/parser/define.rb +0 -39
  62. data/.libold/opulent/parser/eval.rb +0 -33
  63. data/.libold/opulent/parser/expression.rb +0 -350
  64. data/.libold/opulent/parser/filter.rb +0 -41
  65. data/.libold/opulent/parser/node.rb +0 -232
  66. data/.libold/opulent/parser/root.rb +0 -96
  67. data/.libold/opulent/parser/text.rb +0 -114
  68. data/.libold/opulent/parser/theme.rb +0 -36
  69. data/.libold/opulent/preprocessor.rb +0 -102
  70. data/.libold/opulent/runtime.rb +0 -144
  71. data/.libold/opulent/template.rb +0 -43
  72. data/.libold/opulent/tokens.rb +0 -276
  73. data/.libold/opulent/version.rb +0 -5
  74. data/.travis.yml +0 -4
  75. data/benchmark/benchmark.rb +0 -57
  76. data/benchmark/cases/node/node.haml +0 -7
  77. data/benchmark/cases/node/node.op +0 -7
  78. data/benchmark/cases/node/node.slim +0 -7
@@ -1,123 +1,150 @@
1
- # @Opulent
2
- module Opulent
3
- # @Parser
4
- class Parser
5
- # Match one line or multiline, escaped or unescaped text
6
- #
7
- # @param parent [Array] Parent node element
8
- # @param indent [Fixnum] Size of the current indentation
9
- # @param multiline_or_print [Boolean] Allow only multiline text or print
10
- #
11
- def text(parent, indent = nil, multiline_or_print = true)
12
- # Try to see if we can match a multiline operator. If we can accept_stripped only
13
- # multiline, which is the case for filters, undo the operation.
14
- if accept :multiline
15
- multiline = true
16
- elsif multiline_or_print
17
- return nil unless lookahead :print_lookahead
18
- end
19
-
20
- # Get text node type
21
- type = if accept(:print) then :print else :text end
22
-
23
- # Check if the text or print node is escaped or unescaped
24
- escaped = accept(:unescaped_value) ? false : true
25
-
26
- # Get text value
27
- value = accept :line_feed
28
- value = value[1..-1] if value[0] == '\\'
29
-
30
- # Create the text node using input data
31
- text_node = [:plain, type, {value: value.strip, escaped: escaped}, nil, indent]
32
-
33
- # If we have a multiline node, get all the text which has higher
34
- # indentation than our indentation node.
35
- if multiline
36
- text_node[@options][:value] += accept(:newline) || ""
37
- text_node[@options][:value] += get_indented_lines(indent)
38
- text_node[@options][:value].strip!
39
- elsif value.empty?
40
- # If our value is empty and we're not going to add any more lines to
41
- # our buffer, skip the node
42
- return nil
43
- end
44
-
45
- # Increase indentation if this is an inline text node
46
- text_node[@indent] += Settings[:indent] unless multiline_or_print
47
-
48
- # Add text node to the parent element
49
- parent[@children] << text_node
50
- end
51
-
52
- # Match one line or multiline, escaped or unescaped text
53
- #
54
- def html_text(parent, indent)
55
- if (text_feed = accept :html_text)
56
- text_node = [:plain, :text, {value: text_feed.strip, escaped: false}, nil, indent]
57
-
58
- parent[@children] << text_node
59
- end
60
- end
61
-
62
- # Match a whitespace by preventing code trimming
63
- #
64
- def whitespace(required = false)
65
- accept :whitespace, required
66
- end
67
-
68
- # Gather all the lines which have higher indentation than the one given as
69
- # parameter and put them into the buffer
70
- #
71
- # @param indentation [Fixnum] parent node strating indentation
72
- #
73
- def get_indented_lines(indent)
74
- buffer = ''
75
-
76
- # Gather multiple blank lines between lines of text
77
- blank_lines = Proc.new do
78
- while lookahead_next_line :line_whitespace
79
- @line = @code[(@i += 1)]
80
- @offset = 0
81
-
82
- buffer += accept :line_whitespace
83
- end
84
- end
85
-
86
- # Get blank lines until we match something
87
- blank_lines[]
88
-
89
- # Get the next indentation after the parent line
90
- # and set it as primary indent
91
- next_indent = first_indent = (lookahead_next_line(:indent).to_s || "").size
92
-
93
- # While the indentation is smaller, add the line feed to our buffer
94
- while next_indent > indent
95
- # Advance current line and reset offset
96
- @line = @code[(@i += 1)]
97
- @offset = 0
98
-
99
- # Get leading whitespace trimmed with first_indent's size
100
- next_line_indent = accept(:indent)[first_indent..-1] || ""
101
- next_line_indent = next_line_indent.size
102
-
103
- # Add next line feed, prepend the indent and append the newline
104
- buffer += " " * next_line_indent if next_line_indent > 0
105
- buffer += accept_stripped(:line_feed) || ""
106
- buffer += accept(:newline) || ""
107
-
108
- # Get blank lines until we match something
109
- blank_lines[]
110
-
111
- # Check the indentation on the following line. When we reach EOF,
112
- # set the indentation to 0 and cause the loop to stop
113
- if (next_indent = lookahead_next_line :indent)
114
- next_indent = next_indent[0].size
115
- else
116
- next_indent = 0
117
- end
118
- end
119
-
120
- return buffer
121
- end
122
- end
123
- end
1
+ # @Opulent
2
+ module Opulent
3
+ # @Parser
4
+ class Parser
5
+ # Match one line or multiline, escaped or unescaped text
6
+ #
7
+ # @param parent [Array] Parent node element
8
+ # @param indent [Fixnum] Size of the current indentation
9
+ # @param multiline_or_print [Boolean] Allow only multiline text or print
10
+ #
11
+ def text(parent, indent = nil, multiline_or_print = true)
12
+ # Try to see if we can match a multiline operator. If we can accept_stripped only
13
+ # multiline, which is the case for filters, undo the operation.
14
+ if accept :multiline
15
+ multiline = true
16
+ elsif multiline_or_print
17
+ return nil unless lookahead :print_lookahead
18
+ end
19
+
20
+ # Get text node type
21
+ type = accept(:print) ? :print : :text
22
+
23
+ # Check if the text or print node is escaped or unescaped
24
+ escaped = accept(:unescaped_value) ? false : true
25
+
26
+ # Get leading whitespace
27
+ leading_whitespace = accept(:leading_whitespace)
28
+
29
+ # Get trailing whitespace
30
+ trailing_whitespace = accept(:trailing_whitespace)
31
+
32
+ # Get text value
33
+ value = accept :line_feed
34
+ value = value[1..-1] if value[0] == '\\'
35
+
36
+ # Create the text node using input data
37
+ text_node = [
38
+ :plain,
39
+ type,
40
+ {
41
+ value: value.strip,
42
+ escaped: escaped,
43
+ leading_whitespace: leading_whitespace,
44
+ trailing_whitespace: trailing_whitespace
45
+ },
46
+ nil,
47
+ indent
48
+ ]
49
+
50
+ # If we have a multiline node, get all the text which has higher
51
+ # indentation than our indentation node.
52
+ if multiline
53
+ text_node[@options][:value] += accept(:newline) || ''
54
+ text_node[@options][:value] += get_indented_lines(indent)
55
+ text_node[@options][:value].strip!
56
+ elsif value.empty?
57
+ # If our value is empty and we're not going to add any more lines to
58
+ # our buffer, skip the node
59
+ return nil
60
+ end
61
+
62
+ # Increase indentation if this is an inline text node
63
+ text_node[@indent] += @settings[:indent] unless multiline_or_print
64
+
65
+ # Add text node to the parent element
66
+ parent[@children] << text_node
67
+ end
68
+
69
+ # Match one line or multiline, escaped or unescaped text
70
+ #
71
+ def html_text(parent, indent)
72
+ return unless (text_feed = accept :html_text)
73
+
74
+ text_node = [
75
+ :plain,
76
+ :text,
77
+ {
78
+ value: text_feed.strip,
79
+ escaped: false
80
+ },
81
+ nil,
82
+ indent
83
+ ]
84
+
85
+ parent[@children] << text_node
86
+ end
87
+
88
+ # Match a whitespace by preventing code trimming
89
+ #
90
+ def whitespace(required = false)
91
+ accept :whitespace, required
92
+ end
93
+
94
+ # Gather all the lines which have higher indentation than the one given as
95
+ # parameter and put them into the buffer
96
+ #
97
+ # @param indentation [Fixnum] parent node strating indentation
98
+ #
99
+ def get_indented_lines(indent)
100
+ buffer = ''
101
+
102
+ # Gather multiple blank lines between lines of text
103
+ blank_lines = proc do
104
+ while lookahead_next_line :line_whitespace
105
+ @line = @code[(@i += 1)]
106
+ @offset = 0
107
+
108
+ buffer += accept :line_whitespace
109
+ end
110
+ end
111
+
112
+ # Get blank lines until we match something
113
+ blank_lines[]
114
+
115
+ # Get the next indentation after the parent line
116
+ # and set it as primary indent
117
+ first_indent = (lookahead_next_line(:indent).to_s || '').size
118
+ next_indent = first_indent
119
+
120
+ # While the indentation is smaller, add the line feed to our buffer
121
+ while next_indent > indent
122
+ # Advance current line and reset offset
123
+ @line = @code[(@i += 1)]
124
+ @offset = 0
125
+
126
+ # Get leading whitespace trimmed with first_indent's size
127
+ next_line_indent = accept(:indent)[first_indent..-1] || ''
128
+ next_line_indent = next_line_indent.size
129
+
130
+ # Add next line feed, prepend the indent and append the newline
131
+ buffer += ' ' * next_line_indent if next_line_indent > 0
132
+ buffer += accept_stripped(:line_feed) || ''
133
+ buffer += accept(:newline) || ''
134
+
135
+ # Get blank lines until we match something
136
+ blank_lines[]
137
+
138
+ # Check the indentation on the following line. When we reach EOF,
139
+ # set the indentation to 0 and cause the loop to stop
140
+ if (next_indent = lookahead_next_line :indent)
141
+ next_indent = next_indent[0].size
142
+ else
143
+ next_indent = 0
144
+ end
145
+ end
146
+
147
+ buffer
148
+ end
149
+ end
150
+ end
@@ -1,23 +1,23 @@
1
- # @Opulent
2
- module Opulent
3
- # @Parser
4
- class Parser
5
- # Match a yield with a explicit or implicit target
6
- #
7
- # yield target
8
- #
9
- # @param parent [Node] Parent node to which we append the definition
10
- #
11
- def block_yield(parent, indent)
12
- if accept :yield
13
- # Consume the newline from the end of the element
14
- error :yield unless accept(:line_feed).strip.empty?
15
-
16
- # Create a new node
17
- yield_node = [:yield, nil, {}, [], indent]
18
-
19
- parent[@children] << yield_node
20
- end
21
- end
22
- end
23
- end
1
+ # @Opulent
2
+ module Opulent
3
+ # @Parser
4
+ class Parser
5
+ # Match a yield with a explicit or implicit target
6
+ #
7
+ # yield target
8
+ #
9
+ # @param parent [Node] Parent node to which we append the definition
10
+ #
11
+ def block_yield(parent, indent)
12
+ return unless accept :yield
13
+
14
+ # Consume the newline from the end of the element
15
+ error :yield unless accept(:line_feed).strip.empty?
16
+
17
+ # Create a new node
18
+ yield_node = [:yield, nil, {}, [], indent]
19
+
20
+ parent[@children] << yield_node
21
+ end
22
+ end
23
+ end
@@ -1,7 +1,7 @@
1
1
  # @Opulent
2
2
  module Opulent
3
3
  # @Settings
4
- module Settings
4
+ class Settings
5
5
  # Set buffer variable name
6
6
  BUFFER = :@_opulent_buffer
7
7
 
@@ -9,76 +9,95 @@ module Opulent
9
9
  FILE_EXTENSION = '.op'
10
10
 
11
11
  # Default yield target which is used for child block replacements
12
- DefaultEachKey = :key
12
+ DEFAULT_EACH_KEY = :key
13
13
 
14
14
  # Default yield target which is used for child block replacements
15
- DefaultEachValue = :value
15
+ DEFAULT_EACH_VALUE = :value
16
16
 
17
17
  # List of self enclosing node elements
18
- SelfEnclosing = %i(img link input meta br hr area base col command embed keygen param source track wbr)
18
+ SELF_ENCLOSING = %i(
19
+ img link input meta br hr area base col command embed keygen param source
20
+ track wbr
21
+ )
19
22
 
20
23
  # List of inline node parents which can be either inline or have complex
21
24
  # structures inside of them, such as anchor tags
22
- MultiNode = %i(a)
25
+ MULTI_NODE = %i(a)
23
26
 
24
27
  # List of inline node names
25
- InlineNode = %i(text a span strong em br i b small label sub sup abbr var code kbd)
28
+ INLINE_NODE = %i(
29
+ text a span strong em br i b small label sub sup abbr var code kbd
30
+ )
26
31
 
27
32
  # Check whether text should or shouldn't be evaluated
28
- InterpolationCheck = /(?<!\\)\#\{.*\}/
33
+ INTERPOLATION_CHECK = /(?<!\\)\#\{.*\}/
29
34
 
30
35
  # Check if the attribute value is a bare string
31
- EvaluationCheck = /\A(("((?:[^"\\]|\\.)*?)")|('(?:[^'\\]|\\.)*?')|true|false|nil)\Z/
36
+ EVALUATION_CHECK = /\A(("((?:[^"\\]|\\.)*?)")|('(?:[^'\\]|\\.)*?')|true|false|nil)\Z/
37
+
38
+ # Check to see if we need to insert an end block for the current evaluation
39
+ # control do || .* end
40
+ END_INSERTION = /\A(if|begin|unless|else|elsif|when|rescue|ensure)\b|\bdo\s*(\|[^\|]*\|)?\s*$/
41
+ END_REMOVAL = /\A(else|elsif|when|rescue|ensure)/
42
+ END_EXPLICIT = /\A(end)/
32
43
 
33
44
  # Shorthand attribute associations
34
- Shorthand = {
35
- :'.' => :class,
36
- :'#' => :id,
37
- :'&' => :name
45
+ SHORTHAND = {
46
+ '.': :class,
47
+ '#': :id,
48
+ '&': :name
38
49
  }
39
50
 
40
- # @Singleton
41
- class << self
42
- # Opulent runtime options
43
- Defaults = {
44
- #pretty: true, # At the moment, code cannot be uglified
45
- #dependency_manager: true, # Soon to be implemented
46
- indent: 2,
47
- layouts: false,
48
- pretty: false, # Under work
49
- default_layout: :'views/layouts/application'
50
- }
51
-
52
- # Set defaults as initial options
53
- @@options = Defaults
54
-
55
- # Get an option at runtime
56
- #
57
- # @param name [Symbol] Identifier for the option
58
- #
59
- def [](name)
60
- @@options[name]
61
- end
51
+ # Opulent runtime settings
52
+ DEFAULTS = {
53
+ # dependency_manager: true, # Soon to be implemented
54
+ indent: 2,
55
+ layouts: false,
56
+ pretty: false,
57
+ default_layout: :'views/layouts/application'
58
+ }
62
59
 
63
- # Set a new option at runtime
64
- #
65
- # @param name [Symbol] Identifier for the option
66
- # @param value Option value to be set
67
- #
68
- def []=(name, value)
69
- @@options[name] = value
70
- end
60
+ # Set defaults as initial settings
61
+ #
62
+ def initialize
63
+ @settings = DEFAULTS
64
+ end
65
+
66
+ # Get an option at runtime
67
+ #
68
+ # @param name [Symbol] Identifier for the option
69
+ #
70
+ def [](name)
71
+ @settings[name]
72
+ end
73
+
74
+ # Set a new option at runtime
75
+ #
76
+ # @param name [Symbol] Identifier for the option
77
+ # @param value Option value to be set
78
+ #
79
+ def []=(name, value)
80
+ @settings[name] = value
81
+ end
82
+
83
+ # Remove an option at runtime
84
+ #
85
+ # @param name [Symbol] Identifier for the option
86
+ # @param value Option value to be set
87
+ #
88
+ def delete(name)
89
+ @settings.delete name
90
+ end
71
91
 
72
- # Update the engine options with the required option changes
73
- #
74
- # @param opts [Hash] Option extension hash
75
- #
76
- def update_settings(opts)
77
- @@options = Defaults
92
+ # Update the engine settings with the required option changes
93
+ #
94
+ # @param opts [Hash] Option extension hash
95
+ #
96
+ def update_settings(opts)
97
+ @settings = DEFAULTS
78
98
 
79
- opts.each do |key, value|
80
- @@options[key] = value
81
- end
99
+ opts.each do |key, value|
100
+ @settings[key] = value
82
101
  end
83
102
  end
84
103
  end