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 +4 -4
- data/bin/eggshell +13 -0
- data/lib/eggshell/block-handler.rb +161 -23
- data/lib/eggshell/block.rb +3 -2
- data/lib/eggshell/bundles/basics-old.rb +850 -0
- data/lib/eggshell/bundles/basics.rb +650 -589
- data/lib/eggshell/bundles/loader.rb +6 -5
- data/lib/eggshell/expression-evaluator.rb +13 -3
- data/lib/eggshell/format-handler.rb +40 -0
- data/lib/eggshell/macro-handler.rb +16 -10
- data/lib/eggshell/parse-tree.rb +149 -0
- data/lib/eggshell/processor-context.rb +5 -18
- data/lib/eggshell/processor.rb +707 -0
- data/lib/eggshell.rb +42 -740
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e4e19e3f5d40c57dfd10437821105c1cb38d836
|
4
|
+
data.tar.gz: d96074a2df9b741327a3a7ebe626afdcab7a27d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
60
|
+
# Returns the handler's current type.
|
61
|
+
def current_type
|
62
|
+
@block_type
|
40
63
|
end
|
41
64
|
|
42
|
-
|
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
|
-
#
|
46
|
-
|
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
|
+
"'" => ''',
|
181
|
+
'"' => '"',
|
182
|
+
'<' => '<',
|
183
|
+
'>' => '>',
|
184
|
+
'&' => '&'
|
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
|
data/lib/eggshell/block.rb
CHANGED
@@ -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
|