glyph 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +19 -40
- data/benchmark.rb +1 -2
- data/book/config.yml +8 -8
- data/book/document.glyph +18 -19
- data/book/images/glyph/commands_tasks.png +0 -0
- data/book/lib/layouts/bookindex.glyph +113 -111
- data/book/lib/layouts/bookpage.glyph +112 -108
- data/book/lib/macros/reference.rb +2 -2
- data/book/lib/tasks/tasks.rake +1 -1
- data/book/text/acknowledgements.glyph +1 -0
- data/book/text/changelog.glyph +140 -112
- data/book/text/compiling/compiling.glyph +36 -24
- data/book/text/compiling/lite_mode.glyph +11 -11
- data/book/text/compiling/programmatic_usage.glyph +57 -57
- data/book/text/config/document.glyph +7 -1
- data/book/text/config/options.glyph +5 -3
- data/book/text/config/output.glyph +41 -8
- data/book/text/extending/bookmarks_headers.glyph +13 -11
- data/book/text/extending/command.glyph +1 -1
- data/book/text/extending/commands_tasks.glyph +2 -2
- data/book/text/extending/internals.glyph +29 -29
- data/book/text/extending/interpreting.glyph +48 -9
- data/book/text/extending/macro_def.glyph +80 -32
- data/book/text/extending/output_format.glyph +2 -2
- data/book/text/extending/placeholders.glyph +27 -15
- data/book/text/extending/validators.glyph +1 -1
- data/book/text/getting_started/configuration.glyph +1 -1
- data/book/text/getting_started/create_project.glyph +4 -5
- data/book/text/getting_started/structure.glyph +2 -2
- data/book/text/macros/macros_core.glyph +341 -199
- data/book/text/macros/macros_filters.glyph +1 -1
- data/book/text/macros/macros_inline.glyph +3 -3
- data/book/text/macros/macros_structure.glyph +1 -1
- data/book/text/ref_commands.glyph +98 -93
- data/book/text/snippets.glyph +18 -0
- data/book/text/stats/bookmarks.glyph +16 -16
- data/book/text/stats/links.glyph +23 -23
- data/book/text/stats/macros.glyph +14 -14
- data/book/text/stats/snippets.glyph +26 -26
- data/book/text/stats/stats.glyph +14 -15
- data/book/text/text_editing/attribute_intro.glyph +8 -8
- data/book/text/text_editing/code.glyph +16 -16
- data/book/text/text_editing/conditionals.glyph +12 -13
- data/book/text/text_editing/esc_quot.glyph +3 -3
- data/book/text/text_editing/evaluation.glyph +57 -3
- data/book/text/text_editing/inclusions.glyph +34 -25
- data/book/text/text_editing/macro_composition.glyph +28 -0
- data/book/text/text_editing/macro_intro.glyph +4 -4
- data/book/text/text_editing/section_aliases.glyph +23 -23
- data/book/text/text_editing/sections.glyph +22 -22
- data/book/text/text_editing/stylesheets.glyph +33 -33
- data/book/text/text_editing/topics.glyph +6 -6
- data/book/text/text_editing/xml_fallback.glyph +1 -1
- data/book/text/troubleshooting/errors_command.glyph +4 -4
- data/book/text/troubleshooting/errors_generic.glyph +16 -10
- data/book/text/troubleshooting/errors_macro.glyph +18 -21
- data/book/text/troubleshooting/errors_parser.glyph +7 -7
- data/config.yml +51 -29
- data/document.glyph +18 -18
- data/glyph.gemspec +39 -287
- data/layouts/web5/topic.glyph +1 -1
- data/lib/glyph.rb +42 -10
- data/lib/glyph/analyzer.rb +5 -2
- data/lib/glyph/bookmark.rb +3 -1
- data/lib/glyph/commands.rb +11 -9
- data/lib/glyph/commands/add.rb +3 -1
- data/lib/glyph/commands/compile.rb +10 -7
- data/lib/glyph/commands/config.rb +7 -5
- data/lib/glyph/commands/init.rb +2 -0
- data/lib/glyph/commands/outline.rb +2 -0
- data/lib/glyph/commands/stats.rb +3 -0
- data/lib/glyph/commands/todo.rb +2 -0
- data/lib/glyph/config.rb +2 -0
- data/lib/glyph/document.rb +34 -9
- data/lib/glyph/interpreter.rb +2 -0
- data/lib/glyph/macro.rb +97 -25
- data/lib/glyph/macro_validators.rb +9 -6
- data/lib/glyph/node.rb +3 -1
- data/lib/glyph/parser.rb +68 -33
- data/lib/glyph/reporter.rb +3 -1
- data/lib/glyph/syntax_node.rb +23 -28
- data/lib/glyph/system_extensions.rb +21 -0
- data/lib/glyph/utils.rb +24 -4
- data/macros/block.rb +111 -0
- data/macros/core.rb +163 -33
- data/macros/filters.rb +3 -2
- data/macros/inline.rb +97 -0
- data/macros/reps/html.rb +180 -0
- data/macros/reps/html5.rb +100 -0
- data/macros/reps/web.rb +4 -0
- data/macros/reps/web5.rb +4 -0
- data/macros/structure.rb +229 -0
- data/macros/xml.rb +29 -24
- data/spec/config.yml +7 -0
- data/spec/files/article.glyph +2 -2
- data/spec/files/web_doc.glyph +9 -5
- data/spec/lib/commands_spec.rb +13 -9
- data/spec/lib/config_spec.rb +2 -2
- data/spec/lib/document_spec.rb +10 -0
- data/spec/lib/glyph_spec.rb +30 -8
- data/spec/lib/macro_spec.rb +39 -4
- data/spec/lib/macro_validators_spec.rb +3 -4
- data/spec/lib/parser_spec.rb +7 -0
- data/spec/lib/reporter_spec.rb +1 -0
- data/spec/lib/syntax_node_spec.rb +40 -6
- data/spec/macros/core_spec.rb +154 -21
- data/spec/macros/filters_spec.rb +1 -1
- data/spec/macros/html5_spec.rb +4 -5
- data/spec/macros/macros_spec.rb +6 -7
- data/spec/macros/web5_spec.rb +3 -3
- data/spec/macros/web_spec.rb +10 -7
- data/spec/macros/xml_spec.rb +11 -2
- data/spec/spec_helper.rb +11 -5
- data/spec/tasks/generate_spec.rb +40 -5
- data/spec/tasks/load_spec.rb +1 -13
- data/styles/coderay.css +147 -38
- data/styles/default.css +19 -22
- data/styles/pagination.css +30 -30
- data/tasks/generate.rake +54 -18
- data/tasks/load.rake +9 -24
- data/tasks/project.rake +0 -2
- metadata +208 -207
- data/.gitignore +0 -7
- data/VERSION +0 -1
- data/book/snippets.yml +0 -18
- data/lib/glyph/macro_helpers.rb +0 -282
- data/macros/html/block.rb +0 -124
- data/macros/html/inline.rb +0 -42
- data/macros/html/structure.rb +0 -191
- data/macros/html5/block.rb +0 -69
- data/macros/html5/inline.rb +0 -24
- data/macros/html5/structure.rb +0 -140
data/lib/glyph/interpreter.rb
CHANGED
data/lib/glyph/macro.rb
CHANGED
@@ -8,14 +8,14 @@ module Glyph
|
|
8
8
|
class Macro
|
9
9
|
|
10
10
|
include Validators
|
11
|
-
include Helpers
|
12
11
|
include Utils
|
13
12
|
|
14
|
-
attr_reader :node, :source_name, :source_file, :source_topic
|
13
|
+
attr_reader :node, :source_name, :source_file, :source_topic, :name
|
15
14
|
|
16
15
|
# Creates a new macro instance from a Node
|
17
16
|
# @param [Node] node a node populated with macro data
|
18
17
|
def initialize(node)
|
18
|
+
@data = {}
|
19
19
|
@node = node
|
20
20
|
@name = @node[:name]
|
21
21
|
@updated_source = nil
|
@@ -34,7 +34,7 @@ module Glyph
|
|
34
34
|
file ||= @node[:source][:file] rescue nil
|
35
35
|
@updated_source = {:name => name, :file => file, :topic => topic}
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Returns a Glyph code representation of the specified parameter
|
39
39
|
# @param [Fixnum] n the index of the parameter
|
40
40
|
# @return [String, nil] the string representation of the parameter
|
@@ -109,8 +109,8 @@ module Glyph
|
|
109
109
|
@parameters = []
|
110
110
|
@node.parameters.each do |value|
|
111
111
|
@parameters << value.evaluate(@node, :params => true)
|
112
|
-
@parameters.
|
113
|
-
@parameters.
|
112
|
+
@parameters[@parameters.length-1].strip! if options[:strip]
|
113
|
+
@parameters[@parameters.length-1] = nil if @parameters.last.blank? && options[:null_if_blank]
|
114
114
|
end
|
115
115
|
@parameters
|
116
116
|
end
|
@@ -163,7 +163,7 @@ module Glyph
|
|
163
163
|
end
|
164
164
|
macros.reverse.compact.join('/')
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
# Returns a todo message to include in the document in case of errors.
|
168
168
|
# @param [String] message the message to include in the document
|
169
169
|
# @return [String] the resulting todo message
|
@@ -209,23 +209,10 @@ module Glyph
|
|
209
209
|
# @param [String] string the string to interpret
|
210
210
|
# @return [String] the interpreted output
|
211
211
|
def interpret(string)
|
212
|
-
|
213
|
-
result = string
|
214
|
-
else
|
215
|
-
context = {}
|
216
|
-
context[:source] = @updated_source || @node[:source]
|
217
|
-
context[:embedded] = true
|
218
|
-
context[:document] = @node[:document]
|
219
|
-
interpreter = Glyph::Interpreter.new string, context
|
220
|
-
subtree = interpreter.parse
|
221
|
-
subtree[:source] = context[:source]
|
222
|
-
@node << subtree
|
223
|
-
result = interpreter.document.output
|
224
|
-
end
|
225
|
-
result
|
212
|
+
@node[:escape] ? string : inject(string).document.output
|
226
213
|
end
|
227
214
|
|
228
|
-
|
215
|
+
# @see Glyph::Document#placeholder
|
229
216
|
def placeholder(&block)
|
230
217
|
@node[:document].placeholder &block
|
231
218
|
end
|
@@ -250,14 +237,99 @@ module Glyph
|
|
250
237
|
@node[:document].header hash
|
251
238
|
end
|
252
239
|
|
240
|
+
# @see Glyph::Document#snippet
|
241
|
+
def snippet(key, value)
|
242
|
+
@node[:document].snippet key, value
|
243
|
+
end
|
244
|
+
|
245
|
+
# @see Glyph::Document#snippet?
|
246
|
+
def snippet?(ident)
|
247
|
+
@node[:document].snippet? ident
|
248
|
+
end
|
249
|
+
|
250
|
+
# @since 0.5.0
|
251
|
+
# Renders a macro representation
|
252
|
+
# @param [Symbol, String] rep the representation to render
|
253
|
+
# @param [Hash] data the data to pass to the representation
|
254
|
+
def render(rep=nil, data=nil)
|
255
|
+
rep ||= @name
|
256
|
+
data ||= @data
|
257
|
+
block = Glyph::REPS[rep.to_sym]
|
258
|
+
macro_error "No macro representation for '#{rep}'", e unless block
|
259
|
+
instance_exec(data, &block).to_s
|
260
|
+
end
|
261
|
+
|
262
|
+
# Stores a block of code to be "dispatched" via macro composition
|
263
|
+
# @since 0.5.0
|
264
|
+
# @example
|
265
|
+
# # Macro definition (Ruby)
|
266
|
+
# macro :greet do
|
267
|
+
# dispatch do |node|
|
268
|
+
# "#{node[:name]}, #{node.param 0}!"
|
269
|
+
# end
|
270
|
+
# end
|
271
|
+
#
|
272
|
+
# # macro usage (Glyph)
|
273
|
+
# greet/Hello[World] --[Outputs: Hello, World!]
|
274
|
+
# greet/GoodBye[John] --[Outputs: Goodbye, John!]
|
275
|
+
def dispatch(&block)
|
276
|
+
@node[:dispatch] = block
|
277
|
+
value
|
278
|
+
end
|
279
|
+
|
280
|
+
# Performs parameter/attribute substitution and interprets text
|
281
|
+
# @since 0.5.0
|
282
|
+
# @param [String] text the text to interpret
|
283
|
+
# @return [String] the interpreted output
|
284
|
+
def apply(text)
|
285
|
+
body = text.dup
|
286
|
+
# Parameters
|
287
|
+
body.gsub!(/\{\{(\d+)\}\}/) do
|
288
|
+
raw_param($1.to_i).to_s.strip
|
289
|
+
end
|
290
|
+
# Attributes
|
291
|
+
body.gsub!(/\{\{([^\[\]\|\\\s]+)\}\}/) do
|
292
|
+
raw_attr($1.to_sym).to_s.strip
|
293
|
+
end
|
294
|
+
interpret body
|
295
|
+
end
|
296
|
+
|
297
|
+
# Parses text and injects the syntax tree into the current node
|
298
|
+
# @since 0.5.0
|
299
|
+
# @param [String] text the text to parse
|
300
|
+
# @return [Glyph::Interpreter] the interpreter instance used to parse text
|
301
|
+
def inject(text)
|
302
|
+
context = create_context
|
303
|
+
interpreter = Glyph::Interpreter.new text, context
|
304
|
+
subtree = interpreter.parse
|
305
|
+
subtree[:source] = context[:source]
|
306
|
+
@node << subtree
|
307
|
+
interpreter
|
308
|
+
end
|
309
|
+
|
310
|
+
# Parses text
|
311
|
+
# @since 0.5.0
|
312
|
+
# @param [String] text the text to parse
|
313
|
+
# @return [Glyph::Node] the syntax tree generated by parsing
|
314
|
+
def parse(text)
|
315
|
+
Glyph::Interpreter.new(text, create_context).parse
|
316
|
+
end
|
317
|
+
|
253
318
|
# Executes a macro definition in the context of self
|
254
319
|
def expand
|
255
320
|
block = Glyph::MACROS[@name]
|
256
|
-
macro_error "Undefined macro '#@name'
|
257
|
-
|
258
|
-
res.gsub!(/\\?([\[\]\|])/){"\\#$1"}
|
259
|
-
res
|
321
|
+
macro_error "Undefined macro '#@name'" unless block
|
322
|
+
instance_exec(@node, &block).to_s.gsub(/\\?([\[\]\|])/){"\\#$1"}
|
260
323
|
end
|
261
324
|
|
325
|
+
private
|
326
|
+
|
327
|
+
def create_context
|
328
|
+
context = {}
|
329
|
+
context[:source] = @updated_source || @node[:source]
|
330
|
+
context[:embedded] = true
|
331
|
+
context[:document] = @node[:document]
|
332
|
+
context
|
333
|
+
end
|
262
334
|
end
|
263
335
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Glyph
|
2
4
|
class Macro
|
3
5
|
|
@@ -20,12 +22,13 @@ module Glyph
|
|
20
22
|
result
|
21
23
|
end
|
22
24
|
|
23
|
-
# Ensures that the
|
25
|
+
# Ensures that the provided name is a valid XML element name.
|
26
|
+
# @param [String, Symbol] name the element name to validate
|
24
27
|
# @param [Hash] options a hash containing validation options (for now the only option is :level)
|
25
28
|
# @return [Boolean] whether the validation passed or not
|
26
29
|
# @since 0.3.0
|
27
|
-
def valid_xml_element(options={:level => :error})
|
28
|
-
validate("Invalid XML element '#{
|
30
|
+
def valid_xml_element(name, options={:level => :error})
|
31
|
+
validate("Invalid XML element '#{name}'", options) { name.to_s.match(/^([^[:punct:]0-9<>]|_)[^<>"']*/) }
|
29
32
|
end
|
30
33
|
|
31
34
|
# Ensures that a macro attribute name is a valid XML attribute name.
|
@@ -118,7 +121,7 @@ module Glyph
|
|
118
121
|
macro_error "Macro '#@name' cannot be used in safe mode" if Glyph.safe?
|
119
122
|
end
|
120
123
|
|
121
|
-
#
|
124
|
+
# Ensures that no mutual inclusion occurs within the specified parameter or attribute
|
122
125
|
# @param [Fixnum, Symbol] the parameter index or attribute name to check
|
123
126
|
# @raise [Glyph::MacroError] mutual inclusion was detected
|
124
127
|
# @since 0.3.0
|
@@ -146,7 +149,7 @@ module Glyph
|
|
146
149
|
end
|
147
150
|
end
|
148
151
|
|
149
|
-
#
|
152
|
+
# Ensures that the macros is within another
|
150
153
|
# @param [String, Symbol] arg the name of the container macro
|
151
154
|
# @param [Hash] options a hash containing validation options
|
152
155
|
# @option options :level the error level (:error, :warning)
|
@@ -158,7 +161,7 @@ module Glyph
|
|
158
161
|
end
|
159
162
|
end
|
160
163
|
|
161
|
-
#
|
164
|
+
# Ensures that the macros is _not_ within another
|
162
165
|
# @param [String, Symbol] arg the name of the container macro
|
163
166
|
# @param [Hash] options a hash containing validation options
|
164
167
|
# @option options :level the error level (:error, :warning)
|
data/lib/glyph/node.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Core Hash class.
|
1
4
|
class Hash
|
2
5
|
|
3
6
|
# Converts self to a Node
|
@@ -85,7 +88,6 @@ class Node < Hash
|
|
85
88
|
|
86
89
|
# Iterates through children recursively (including self)
|
87
90
|
# @param [Node, nil] element the node to process
|
88
|
-
# @yieldparam [Integer] level the initial tree depth
|
89
91
|
# @yieldparam [Node] element the current node
|
90
92
|
# @yieldparam [Integer] level the current tree depth
|
91
93
|
def descend(element=nil, level=0, &block)
|
data/lib/glyph/parser.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
require 'strscan'
|
3
4
|
|
4
5
|
module Glyph
|
@@ -13,6 +14,7 @@ module Glyph
|
|
13
14
|
# @param [String] source_name the name of the source file (stored in the root node)
|
14
15
|
# @since 0.3.0
|
15
16
|
def initialize(text, source_name="--")
|
17
|
+
@ruby19 = RUBY_VERSION >= '1.9' ? true : false
|
16
18
|
@source_name = source_name || "--"
|
17
19
|
@input = StringScanner.new text
|
18
20
|
@output = create_node DocumentNode, :name => @source_name.to_sym
|
@@ -29,8 +31,8 @@ module Glyph
|
|
29
31
|
@output << result
|
30
32
|
count +=1
|
31
33
|
end
|
32
|
-
if @input.pos < @input.string.
|
33
|
-
current_char = @input.string[@input.pos].chr
|
34
|
+
if @input.pos < @input.string.bytesize then
|
35
|
+
current_char = @input.string[@input.pos].chr rescue nil
|
34
36
|
illegal_delimiter = current_char.match(/\]|\[/) rescue nil
|
35
37
|
error "Macro delimiter '#{current_char}' not escaped" if illegal_delimiter
|
36
38
|
end
|
@@ -58,18 +60,15 @@ module Glyph
|
|
58
60
|
name = @input.matched
|
59
61
|
name.chop!
|
60
62
|
name.chop!
|
61
|
-
error "#{name}[
|
62
|
-
node =
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
})
|
68
|
-
while contents = parse_escaped_contents(node) do
|
69
|
-
node << contents unless contents.is_a?(AttributeNode)
|
63
|
+
error "#{name}[=...=] - A macro cannot start with a digit or contain '@'" if (name.match(/^[0-1]/) || name.match(/@/)) && !name.match(/^@:?$/)
|
64
|
+
node = macro_node_for name, true
|
65
|
+
leaf = node
|
66
|
+
node.descend { |n, level| leaf = n }
|
67
|
+
while contents = parse_escaped_contents(leaf) do
|
68
|
+
leaf << contents unless contents.is_a?(AttributeNode)
|
70
69
|
end
|
71
70
|
@input.scan(/\=\]/) or error "Escaping macro '#{name}' not closed"
|
72
|
-
organize_children_for
|
71
|
+
organize_children_for leaf
|
73
72
|
node
|
74
73
|
else
|
75
74
|
nil
|
@@ -77,9 +76,9 @@ module Glyph
|
|
77
76
|
end
|
78
77
|
|
79
78
|
def escaping_attribute(current)
|
80
|
-
if @input.scan(/@[
|
79
|
+
if @input.scan(/@[^:\[\]\|\\\s]+\[\=/) then
|
81
80
|
error "Attributes cannot be nested" if @current_attribute
|
82
|
-
name = @input.matched[1..@input.matched.
|
81
|
+
name = @input.matched[1..@input.matched.bytesize-3]
|
83
82
|
node = create_node(AttributeNode, {
|
84
83
|
:escape => true,
|
85
84
|
:name => name.to_sym
|
@@ -99,18 +98,15 @@ module Glyph
|
|
99
98
|
if @input.scan(/[^\[\]\|\\\s]+\[/) then
|
100
99
|
name = @input.matched
|
101
100
|
name.chop!
|
102
|
-
error "#{name}[...] - A macro cannot start with
|
103
|
-
node =
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
})
|
109
|
-
while contents = parse_contents(node) do
|
110
|
-
node << contents unless contents.is_a?(AttributeNode)
|
101
|
+
error "#{name}[...] - A macro cannot start with a digit or contain '@'" if (name.match(/^[0-1]/) || name.match(/@/)) && !name.match(/^@:?$/)
|
102
|
+
node = macro_node_for name
|
103
|
+
leaf = node
|
104
|
+
node.descend { |n, level| leaf = n }
|
105
|
+
while contents = parse_contents(leaf) do
|
106
|
+
leaf << contents unless contents.is_a?(AttributeNode)
|
111
107
|
end
|
112
108
|
@input.scan(/\]/) or error "Macro '#{name}' not closed"
|
113
|
-
organize_children_for
|
109
|
+
organize_children_for leaf
|
114
110
|
node
|
115
111
|
else
|
116
112
|
nil
|
@@ -118,9 +114,9 @@ module Glyph
|
|
118
114
|
end
|
119
115
|
|
120
116
|
def attribute(current)
|
121
|
-
if @input.scan(/@[
|
117
|
+
if @input.scan(/@[^:\[\]\|\\\s]+\[/) then
|
122
118
|
error "Attributes cannot be nested" if current.is_a?(AttributeNode)
|
123
|
-
name = @input.matched[1..@input.matched.
|
119
|
+
name = @input.matched[1..@input.matched.bytesize-2]
|
124
120
|
node = create_node(AttributeNode, {
|
125
121
|
:escape => false,
|
126
122
|
:name => name.to_sym
|
@@ -139,12 +135,12 @@ module Glyph
|
|
139
135
|
def text(current)
|
140
136
|
start_p = @input.pos
|
141
137
|
res = @input.scan_until /(\\.)|(\A(\]|\|)|[^\\](\]|\|)|[^\[\]\|\\\s]+\[|\Z)/
|
142
|
-
|
138
|
+
offset = @input.matched.match(/^[^\\](\]|\|)$/) ? 1 : @input.matched.bytesize
|
143
139
|
@input.pos = @input.pos - offset rescue @input.pos
|
144
140
|
return nil if @input.pos == start_p
|
145
|
-
match =
|
141
|
+
match = extract_string(start_p..@input.pos-1)
|
146
142
|
illegal_macro_delimiter? start_p, match
|
147
|
-
if match.
|
143
|
+
if match.bytesize > 0 then
|
148
144
|
create_node TextNode, :value => match
|
149
145
|
else
|
150
146
|
nil
|
@@ -160,16 +156,16 @@ module Glyph
|
|
160
156
|
when @input.matched.match(/^[^\\]\|$/) then
|
161
157
|
offset = 1
|
162
158
|
else
|
163
|
-
offset = @input.matched.
|
159
|
+
offset = @input.matched.bytesize
|
164
160
|
end
|
165
161
|
@input.pos = @input.pos - offset rescue @input.pos
|
166
162
|
return nil if @input.pos == start_p
|
167
|
-
match =
|
163
|
+
match = extract_string(start_p..@input.pos-1)
|
168
164
|
illegal_nesting = match.match(/([^\[\]\|\\\s]+)\[\=/)[1] rescue nil
|
169
165
|
if illegal_nesting then
|
170
166
|
error "Cannot nest escaping macro '#{illegal_nesting}' within escaping macro '#{current[:name]}'"
|
171
167
|
end
|
172
|
-
if match.
|
168
|
+
if match.bytesize > 0 then
|
173
169
|
create_node TextNode, :value => match, :escaped => true
|
174
170
|
else
|
175
171
|
nil
|
@@ -197,6 +193,45 @@ module Glyph
|
|
197
193
|
|
198
194
|
private
|
199
195
|
|
196
|
+
def macro_node_for(ident, escape=false)
|
197
|
+
macro_names = ident.split(/\//).select{|e| !e.blank?}
|
198
|
+
nest_node = lambda do |parent, count|
|
199
|
+
node = create_node(MacroNode, {
|
200
|
+
:escape => false,
|
201
|
+
:name => macro_names[count].to_sym
|
202
|
+
})
|
203
|
+
parent ? (parent&0) << node : parent = node
|
204
|
+
if macro_names[count+1] then
|
205
|
+
node << create_node(ParameterNode, :name => :"0")
|
206
|
+
nest_node.call(node, count+1)
|
207
|
+
else
|
208
|
+
node[:parameters] = []
|
209
|
+
node[:attributes] = []
|
210
|
+
node[:escape] = escape
|
211
|
+
end
|
212
|
+
node
|
213
|
+
end
|
214
|
+
nest_node.call(nil, 0)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Thanks Thomas Leitner
|
218
|
+
# http://redmine.ruby-lang.org/issues/show/2645
|
219
|
+
def extract_string(range)
|
220
|
+
result = nil
|
221
|
+
if @ruby19 then
|
222
|
+
begin
|
223
|
+
enc = @input.string.encoding
|
224
|
+
@input.string.force_encoding('ASCII-8BIT')
|
225
|
+
result = @input.string[range].force_encoding(enc)
|
226
|
+
ensure
|
227
|
+
@input.string.force_encoding(enc)
|
228
|
+
end
|
229
|
+
else
|
230
|
+
result = @input.string[range]
|
231
|
+
end
|
232
|
+
result
|
233
|
+
end
|
234
|
+
|
200
235
|
def aggregate_parameters_for(node)
|
201
236
|
indices = []
|
202
237
|
count = 0
|
@@ -216,7 +251,7 @@ module Glyph
|
|
216
251
|
total_parameters = 0
|
217
252
|
save_parameter = lambda do |max_index|
|
218
253
|
parameter = create_node ParameterNode, :name => "#{total_parameters}".to_sym
|
219
|
-
|
254
|
+
total_parameters +=1
|
220
255
|
current_index.upto(max_index) do |index|
|
221
256
|
parameter << (node & index)
|
222
257
|
end
|
data/lib/glyph/reporter.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Glyph
|
2
4
|
|
3
5
|
# This class is used to display statistics collected by a Glyph::Analyzer.
|
@@ -92,7 +94,7 @@ module Glyph
|
|
92
94
|
section "Snippet '#{s[:param]}'"
|
93
95
|
info "Definition:"
|
94
96
|
puts "-------------------"
|
95
|
-
puts
|
97
|
+
puts @stats[:snippets][:values][s[:param]]
|
96
98
|
puts "-------------------"
|
97
99
|
total :used_instances, s[:stats][:total]
|
98
100
|
occurrences s[:stats][:files], "Usage Details:" if @detailed
|
data/lib/glyph/syntax_node.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Glyph
|
2
4
|
|
3
5
|
# A subclass of Glyph::SyntaxNode is instantiated by Glyph::Parser whenever a known
|
@@ -59,7 +61,13 @@ module Glyph
|
|
59
61
|
# @since 0.3.0
|
60
62
|
def to_s
|
61
63
|
e = self[:escape] ? "=" : ""
|
62
|
-
"#{self[:name]}["+e+
|
64
|
+
"#{self[:name]}["+e+contents+e+"]"
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [String] a textual representation of the macro parameters.
|
68
|
+
# @since 0.3.0
|
69
|
+
def contents
|
70
|
+
attributes.join+parameters.join("|")
|
63
71
|
end
|
64
72
|
|
65
73
|
# Expands the macro
|
@@ -123,11 +131,18 @@ module Glyph
|
|
123
131
|
# @return [String] the value of the macro
|
124
132
|
# @since 0.3.0
|
125
133
|
def expand(context)
|
126
|
-
xml_element(context)
|
127
134
|
self[:source] = context[:source]
|
128
135
|
self[:document] = context[:document]
|
129
136
|
self[:info] = context[:info]
|
130
137
|
self[:value] = ""
|
138
|
+
dispatched = parent_macro.dispatch(self) if parent_macro
|
139
|
+
return dispatched if dispatched
|
140
|
+
if Glyph['options.macro_set'] == "xml" || Glyph::MACROS[self[:name]].blank? && Glyph['options.xml_fallback'] then
|
141
|
+
m = Glyph::MacroNode.new
|
142
|
+
m[:name] = :xml
|
143
|
+
Glyph::Macro.new(m).expand
|
144
|
+
return m[:dispatch].call self
|
145
|
+
end
|
131
146
|
Glyph::Macro.new(self).expand
|
132
147
|
end
|
133
148
|
|
@@ -139,33 +154,13 @@ module Glyph
|
|
139
154
|
s
|
140
155
|
end
|
141
156
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
# Force tag name override if macro starts with a '='
|
149
|
-
name.gsub! /^=(.+)/, '\1'
|
150
|
-
end
|
151
|
-
case
|
152
|
-
# Use XML syntax
|
153
|
-
when Glyph['options.macro_set'] == 'xml' then
|
154
|
-
self[:element] = name
|
155
|
-
self[:name] = :"|xml|"
|
156
|
-
# Fallback to XML syntax
|
157
|
-
when Glyph["options.xml_fallback"] then
|
158
|
-
unless known_macro then
|
159
|
-
self[:element] = name
|
160
|
-
self[:fallback] = true
|
161
|
-
self[:name] = :"|xml|"
|
162
|
-
end
|
163
|
-
else
|
164
|
-
# Unknown macro
|
165
|
-
raise RuntimeError, "Undefined macro '#{name}'\n -> source: #{context[:source][:name]}" unless known_macro
|
166
|
-
end
|
157
|
+
# @since 0.5.0
|
158
|
+
# Calls the ruby block stored in the :dispatch key, if present,
|
159
|
+
# in the context of node
|
160
|
+
def dispatch(node)
|
161
|
+
return self[:dispatch].call node if self[:dispatch]
|
162
|
+
false
|
167
163
|
end
|
168
|
-
|
169
164
|
end
|
170
165
|
|
171
166
|
# A piece of text in Glyph Abstract Syntax Tree
|