eggshell 0.8.3 → 1.0.0

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: b7a48d71b9acc52446c52cbadca553afd4243db7
4
- data.tar.gz: 3b1ec8bc1780691e2441bec34f693b6871d6a153
3
+ metadata.gz: 8e4e19e3f5d40c57dfd10437821105c1cb38d836
4
+ data.tar.gz: d96074a2df9b741327a3a7ebe626afdcab7a27d8
5
5
  SHA512:
6
- metadata.gz: 66988afe180033c03dbeb032eab24559c5bfc6c368b9fe753560894fbf2ae5779d92e5b7bb905ce025b5cc10fd6c7c1611b3f223f88957ab9099cddaa187c440
7
- data.tar.gz: 7b652c3a9ad4acc6c6aec68f89a3080d4312134c9a4ff22c78579c93c024f4bfa7b5c9ff43cba68295fe72ee6e061e4d9c351e9bee25d407845df6be588425b9
6
+ metadata.gz: a4664c527b16f16c3fe1ad8f908e67e05cc3b11c8b7012fc0224571a184a33d889c2767064da38aca52c48aac2b1d6e520b185af13f7e7d72d104c5df62d705a
7
+ data.tar.gz: 55e1c0cfc1ec5788ce799446bfd717e9fcd18b211b6fb80ac6453d2c6627246a1abf16de726383a7dcd55434064d6db139f8c488c34bab8e993076e7abe09ea6
data/bin/eggshell CHANGED
@@ -1,4 +1,17 @@
1
1
  #!/usr/bin/ruby
2
+ helptext = """
3
+ Process Eggshell files from the command line:
4
+
5
+ eggshell <source> # outputs to console
6
+ eggshell <source> out=filename
7
+ eggshell <source> format=format_hint
8
+
9
+ Note that 'format' parameter hints at the source file (e.g. supplying 'md' loads the markdown support libraries)
10
+ """
11
+
12
+ # @todo parse args
13
+ # @todo set output redirect
14
+
2
15
  require_relative '../lib/eggshell.rb'
3
16
 
4
17
  f = ARGV[0]
@@ -1,4 +1,34 @@
1
+ # A block handler handles one or more lines as a unit as long as all the lines
2
+ # conform to the block's expectations.
3
+ #
4
+ # Blocks are either identified explicitly:
5
+ #
6
+ # pre. block_name. some content
7
+ # \
8
+ # block_name({}). some content
9
+ #
10
+ # Or, through some non-alphanumeric character:
11
+ #
12
+ # pre. |table|start|inferred
13
+ # |another|row|here
14
+ #
15
+ # When a handler can handle a line, it sets an internal block type (retrieved
16
+ # with {{current_type()}}). Subsequent lines are passed to {{continue_with()}}
17
+ # which returns `true` if the line conforms to the current type or `false` to
18
+ # close the block.
19
+ #
20
+ # The line or lines are finally passed to {{process()}} to generate the output.
21
+ #
22
+ # h2. Block Standards
23
+ #
24
+ # When explicitly calling a block and passing a parameter, always expect the first
25
+ # argument to be a hash of various attributes:
26
+ #
27
+ # pre. p({'class': '', 'id': '', 'attributes': {}}, other, arguments, ...). paragraph start
1
28
  module Eggshell::BlockHandler
29
+ include Eggshell::BaseHandler
30
+ include Eggshell::ProcessHandler
31
+
2
32
  # Indicates that subsequent lines should be collected.
3
33
  COLLECT = :collect
4
34
 
@@ -15,35 +45,43 @@ module Eggshell::BlockHandler
15
45
  # started.
16
46
  RETRY = :retry
17
47
 
18
- def set_processor(proc)
19
- end
20
-
21
- def set_block_params(name)
22
- @block_params = {} if !@block_params
23
- @block_params[name] = @proc.get_block_params(name)
48
+ def set_processor(proc, opts = nil)
49
+ @eggshell = proc
50
+ @eggshell.add_block_handler(self, *@block_types)
51
+ @vars = @eggshell.vars
52
+ @vars[:block_params] = {} if !@vars[:block_params]
24
53
  end
25
-
26
- def create_tag(tag, attribs, open = true)
27
- # @todo escape val?
28
- abuff = []
29
- attribs.each do |key,val|
30
- if val == nil
31
- abuff << key
32
- else
33
- abuff << "#{key}='#{val}'"
34
- end
35
- end
36
- "<#{tag} #{abuff.join(' ')}#{open ? '>' : '/>'}"
54
+
55
+ # Resets state of line inspection.
56
+ def reset
57
+ @block_type = nil
37
58
  end
38
59
 
39
- def start(name, line, buffer, indents = '', indent_level = 0)
60
+ # Returns the handler's current type.
61
+ def current_type
62
+ @block_type
40
63
  end
41
64
 
42
- def collect(line, buffer, indents = '', indent_level = 0)
65
+ # Sets the type based on the line given, and returns one of the following:
66
+ #
67
+ # - {{RETRY}}: doesn't handle this line;
68
+ # - {{COLLECT}}: will collect lines following normal processing.
69
+ # - {{COLLECT_RAW}}: will collect lines before macro/block checks can take place.
70
+ # - {{DONE}}: line processed, no need to collect more lines.
71
+ def can_handle(line)
72
+ RETRY
43
73
  end
44
-
45
- # For exception handling, optional information to provide context about error
46
- def offsets
74
+
75
+ # Determines if processing for the current type ends (e.g. a blank line usually
76
+ # terminates the block).
77
+ # @return Symbol {{RETRY}} if not handled at all; {{COLLECT}} to collect and
78
+ # continue; {{DONE}} to collect this line but end the block.
79
+ def continue_with(line)
80
+ if line != nil && line != ''
81
+ COLLECT
82
+ else
83
+ RETRY
84
+ end
47
85
  end
48
86
 
49
87
  module Defaults
@@ -51,4 +89,104 @@ module Eggshell::BlockHandler
51
89
  include Eggshell::BlockHandler
52
90
  end
53
91
  end
92
+
93
+ # Block parameters are default parameters given to a block type (e.g. setting a class).
94
+ # The parameters should be a map. Any keys are allowed, but for HTML, the standard keys
95
+ # that blocks will generally use are:
96
+ #
97
+ # - {{CLASS}}: string
98
+ # - {{ID}}: string
99
+ # - {{STYLE}}: string or map of styles.
100
+ # - {{ATTRIBUTES}}: map of extra tag attributes.
101
+ #
102
+ # This module has pre-filled methods to make it is to drop in the functionality
103
+ # wherever it's needed. The assumption is that {{@vars}} is a hash.
104
+ module BlockParams
105
+ CLASS = 'class'
106
+ ID = 'id'
107
+ STYLE = 'style'
108
+ ATTRIBUTES = 'attributes'
109
+ KEYS = [CLASS, ID, STYLE, ATTRIBUTES].freeze
110
+
111
+ # Sets the default parameters for a block type.
112
+ def set_block_params(name, params)
113
+ params = {} if !params.is_a?(Hash)
114
+ @vars[:block_params][name] = params
115
+ end
116
+
117
+ # Gets the block params for a block type, merging in any defaults
118
+ # with the passed in parameters.
119
+ #
120
+ # For the key {{ATTRIBUTES}}, individual keys within that are
121
+ # compared to the default param's {{ATTRIBUTES}}.
122
+ def get_block_params(name, params = {})
123
+ params = {} if !params.is_a?(Hash)
124
+ bparams = @vars[:block_params][name]
125
+ if bparams
126
+ bparams.each do |key, val|
127
+ if key == ATTRIBUTES
128
+ if !params[key].is_a?(Hash)
129
+ params[key] = val
130
+ else
131
+ val.each do |akey, aval|
132
+ if !params[key].has_key?(akey)
133
+ params[key][akey] = aval
134
+ end
135
+ end
136
+ end
137
+ elsif !params.has_key?(key)
138
+ params[key] = val
139
+ end
140
+ end
141
+ end
142
+ params
143
+ end
144
+ end
145
+
146
+ # Useful methods for generating HTML tags
147
+ module HtmlUtils
148
+ def create_tag(tag, attribs, open = true)
149
+ nattribs = attribs.is_a?(Hash) ? attribs.clone : {}
150
+ if nattribs[BlockParams::STYLE].is_a?(Hash)
151
+ nattribs[BlockParams::STYLE] = css_string(nattribs[BlockParams::STYLE])
152
+ end
153
+
154
+ "<#{tag}#{attrib_string(nattribs, BlockParams::KEYS)}#{open ? '' : '/'}>"
155
+ end
156
+
157
+ def attrib_string(map, keys = nil)
158
+ keys = map.keys if !keys
159
+ buff = []
160
+ keys.each do |key|
161
+ val = map[key]
162
+ if val.is_a?(Hash)
163
+ buff << attrib_string(val)
164
+ elsif val && key[0] != '@'
165
+ buff << " #{key}='#{html_escape(val)}'"
166
+ end
167
+ end
168
+ buff.join()
169
+ end
170
+
171
+ def css_string(map)
172
+ css = []
173
+ map.each do |s,v|
174
+ css << "#{s}: #{html_escape(v)};"
175
+ end
176
+ css.join(' ')
177
+ end
178
+
179
+ HASH_HTML_ESCAPE = {
180
+ "'" => '&#039;',
181
+ '"' => '&quot;',
182
+ '<' => '&lt;',
183
+ '>' => '&gt;',
184
+ '&' => '&amp;'
185
+ }.freeze
186
+
187
+ # @todo more chars
188
+ def html_escape(str)
189
+ return str.gsub(/("|'|<|>|&)/, HASH_HTML_ESCAPE)
190
+ end
191
+ end
54
192
  end
@@ -1,9 +1,10 @@
1
1
  # For multiline macros, the block collects lines specific to the block (including other nested macros).
2
2
  # This allows for proper execution when dealing with loops and branches.
3
3
  class Eggshell::Block
4
- def initialize(macro, handler, args, depth, delim = nil)
4
+ def initialize(macro, handler, args, depth, line_count, delim = nil)
5
5
  @stack = [self]
6
6
  @lines = []
7
+ @line_count = line_count
7
8
  @macro = macro
8
9
  @handler = handler
9
10
  @args = args
@@ -27,7 +28,7 @@ class Eggshell::Block
27
28
  end
28
29
 
29
30
  # Adds a nested block to collect lines into.
30
- def push(block)
31
+ def push(block, line_count = -1)
31
32
  @stack[-1].lines << block
32
33
  @stack << block
33
34
  end