glyph 0.4.2 → 0.5.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.
- 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
|