glyph 0.1.0 → 0.2.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.
Files changed (97) hide show
  1. data/AUTHORS.textile +8 -0
  2. data/CHANGELOG.textile +260 -0
  3. data/LICENSE.textile +26 -0
  4. data/README.textile +49 -21
  5. data/Rakefile +17 -7
  6. data/VERSION +1 -1
  7. data/book/config.yml +11 -5
  8. data/book/document.glyph +24 -13
  9. data/book/lib/macros/reference.rb +41 -14
  10. data/book/output/html/glyph.html +2298 -687
  11. data/book/output/pdf/glyph.pdf +6218 -2698
  12. data/book/script/authors +1 -0
  13. data/book/script/changelog +1 -0
  14. data/book/script/compile.rb +8 -0
  15. data/book/script/license +1 -0
  16. data/book/script/prof +1 -0
  17. data/book/script/prof_results.htm +21079 -0
  18. data/book/script/readme +1 -0
  19. data/book/snippets.yml +3 -4
  20. data/book/text/acknowledgement.glyph +8 -0
  21. data/book/text/authoring.glyph +548 -0
  22. data/book/text/changelog.glyph +76 -0
  23. data/book/text/extending.glyph +224 -0
  24. data/book/text/{getting_started.textile → getting_started.glyph} +30 -24
  25. data/book/text/{introduction.textile → introduction.glyph} +22 -12
  26. data/book/text/license.glyph +21 -0
  27. data/book/text/{ref_commands.textile → ref_commands.glyph} +30 -8
  28. data/book/text/ref_config.glyph +108 -0
  29. data/book/text/ref_macros.glyph +378 -0
  30. data/book/text/troubleshooting.glyph +179 -0
  31. data/config.yml +16 -4
  32. data/glyph.gemspec +83 -22
  33. data/lib/glyph.rb +164 -31
  34. data/lib/glyph/commands.rb +98 -23
  35. data/lib/glyph/document.rb +13 -7
  36. data/lib/glyph/glyph_language.rb +9 -1
  37. data/lib/glyph/glyph_language.treetop +1 -1
  38. data/lib/glyph/interpreter.rb +19 -9
  39. data/lib/glyph/macro.rb +88 -11
  40. data/lib/glyph/macro_validators.rb +48 -0
  41. data/lib/glyph/node.rb +13 -1
  42. data/lib/glyph/system_extensions.rb +0 -28
  43. data/macros/common.rb +125 -31
  44. data/macros/filters.rb +19 -13
  45. data/macros/html/block.rb +119 -68
  46. data/macros/html/inline.rb +29 -3
  47. data/macros/html/structure.rb +40 -40
  48. data/spec/files/article.glyph +5 -0
  49. data/spec/lib/commands_spec.rb +98 -3
  50. data/spec/lib/document_spec.rb +15 -2
  51. data/spec/lib/glyph_spec.rb +39 -10
  52. data/spec/lib/interpreter_spec.rb +8 -2
  53. data/spec/lib/macro_spec.rb +54 -6
  54. data/spec/lib/macro_validators_spec.rb +33 -0
  55. data/spec/lib/node_spec.rb +11 -3
  56. data/spec/macros/filters_spec.rb +5 -5
  57. data/spec/macros/macros_spec.rb +185 -8
  58. data/spec/macros/textile_spec.rb +217 -0
  59. data/spec/spec_helper.rb +25 -15
  60. data/spec/tasks/generate_spec.rb +3 -3
  61. data/spec/tasks/load_spec.rb +11 -1
  62. data/spec/tasks/project_spec.rb +0 -3
  63. data/styles/coderay.css +121 -0
  64. data/styles/default.css +54 -20
  65. data/{book/styles/css3.css → styles/pagination.css} +35 -7
  66. data/styles/ultraviolet/active4d.css +114 -0
  67. data/styles/ultraviolet/all_hallows_eve.css +72 -0
  68. data/styles/ultraviolet/amy.css +147 -0
  69. data/styles/ultraviolet/blackboard.css +88 -0
  70. data/styles/ultraviolet/brilliance_black.css +605 -0
  71. data/styles/ultraviolet/brilliance_dull.css +599 -0
  72. data/styles/ultraviolet/cobalt.css +149 -0
  73. data/styles/ultraviolet/dawn.css +121 -0
  74. data/styles/ultraviolet/eiffel.css +121 -0
  75. data/styles/ultraviolet/espresso_libre.css +109 -0
  76. data/styles/ultraviolet/idle.css +62 -0
  77. data/styles/ultraviolet/iplastic.css +80 -0
  78. data/styles/ultraviolet/lazy.css +73 -0
  79. data/styles/ultraviolet/mac_classic.css +123 -0
  80. data/styles/ultraviolet/magicwb_amiga.css +104 -0
  81. data/styles/ultraviolet/pastels_on_dark.css +188 -0
  82. data/styles/ultraviolet/slush_poppies.css +85 -0
  83. data/styles/ultraviolet/spacecadet.css +51 -0
  84. data/styles/ultraviolet/sunburst.css +180 -0
  85. data/styles/ultraviolet/twilight.css +137 -0
  86. data/styles/ultraviolet/zenburnesque.css +91 -0
  87. data/tasks/generate.rake +45 -26
  88. data/tasks/load.rake +21 -18
  89. data/tasks/project.rake +3 -1
  90. metadata +210 -41
  91. data/book/styles/default.css +0 -190
  92. data/book/text/authoring.textile +0 -351
  93. data/book/text/extending.textile +0 -148
  94. data/book/text/ref_config.textile +0 -0
  95. data/book/text/ref_macros.textile +0 -256
  96. data/book/text/troubleshooting.textile +0 -118
  97. data/styles/css3.css +0 -220
@@ -0,0 +1,48 @@
1
+ module Glyph
2
+ class Macro
3
+
4
+ module Validators
5
+
6
+ # Validates the macro according to the specified block
7
+ # @param [String] message the message to display if the validation fails.
8
+ # @param [Hash] options a hash containing validation options (for now the only option is :level)
9
+ # @example
10
+ # validate("Invalid macro value", :level => :error) {@value == 'valid'} # Raises an error in case of failure
11
+ # validate("Invalid macro value", :level => :warning) {@value == 'valid'} # Displays a warning in case of failure
12
+ def validate(message, options={:level => :error}, &block)
13
+ unless instance_eval(&block) then
14
+ send("macro_#{options[:level]}".to_sym, message)
15
+ end
16
+ end
17
+
18
+ # Ensures that the macro receives up to _n_ parameters.
19
+ # @param [Integer] n the maximum number of parameters allowed for the macro.
20
+ # @param [Hash] options a hash containing validation options (for now the only option is :level)
21
+ def max_parameters(n, options={:level=>:error})
22
+ validate("Macro '#{@name}' takes up to #{n} parameter(s) (#{params.length} given)", options) { params.length <= n }
23
+ end
24
+
25
+ # Ensures that the macro receives at least _n_ parameters.
26
+ # @param [Integer] n the minimum number of parameters allowed for the macro.
27
+ # @param [Hash] options a hash containing validation options (for now the only option is :level)
28
+ def min_parameters(n, options={:level=>:error})
29
+ validate("Macro '#{@name}' takes at least #{n} parameter(s) (#{params.length} given)", options) { params.length >= n }
30
+ end
31
+
32
+ # Ensures that the macro receives exactly _n_ parameters.
33
+ # @param [Integer] n the number of parameters allowed for the macro.
34
+ # @param [Hash] options a hash containing validation options (for now the only option is :level)
35
+ def exact_parameters(n, options={:level=>:error})
36
+ validate("Macro '#{@name}' takes exactly #{n} parameter(s) (#{params.length} given)", options) { params.length == n }
37
+ end
38
+
39
+ # Ensures that the macro receives no parameters.
40
+ # @param [Hash] options a hash containing validation options (for now the only option is :level)
41
+ def no_parameters(options={:level=>:error})
42
+ validate("Macro '#{@name}' takes no parameters (#{params.length} given)", options) { params.length == 0 }
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
data/lib/glyph/node.rb CHANGED
@@ -55,6 +55,15 @@ class Node < Hash
55
55
  @children << ht
56
56
  end
57
57
 
58
+ # Removes a child node from self
59
+ # @param [node] node the child node to remove
60
+ # @raise [ArgumentError] unless an existing child node is passed as parameter
61
+ def >>(node)
62
+ raise ArgumentError, "Unknown child node" unless @children.include? node
63
+ node.parent = nil
64
+ @children.delete node
65
+ end
66
+
58
67
  # Returns a child by its index
59
68
  # @return [Node] the child node or nil
60
69
  # @param [Integer] index the child index
@@ -62,7 +71,10 @@ class Node < Hash
62
71
  @children[index]
63
72
  end
64
73
 
65
- alias >> child
74
+ # See Node#child.
75
+ def &(index)
76
+ @children[index]
77
+ end
66
78
 
67
79
  # Iterates through children
68
80
  # @yieldparam [Node] c the child node
@@ -1,22 +1,5 @@
1
1
  module Kernel
2
2
 
3
- # Prints a message
4
- # @param [#to_s] message the message to print
5
- def info(message)
6
- puts "#{message}" unless cfg :quiet
7
- end
8
-
9
- # Prints a warning
10
- # @param [#to_s] message the message to print
11
- def warning(message)
12
- puts "warning: #{message}" unless cfg :quiet
13
- end
14
-
15
- # @see Glyph::Config#get
16
- def cfg(setting)
17
- Glyph::CONFIG.get(setting)
18
- end
19
-
20
3
  # Dumps and serialize an object to a YAML file
21
4
  # @param [#to_s] file the file to write to
22
5
  # @param [Object] obj the object to serialize
@@ -64,14 +47,3 @@ module Kernel
64
47
  end
65
48
 
66
49
  end
67
-
68
- class MacroError < RuntimeError
69
- attr_reader :node
70
- def initialize(node, msg)
71
- @node = node
72
- source = @node[:source] || "--"
73
- macros = []
74
- @node.ascend {|n| macros << n[:macro].to_s if n[:macro] }
75
- super("#{msg}\n -> source: #{source}\n -> path: #{macros.reverse.join('/')}")
76
- end
77
- end
data/macros/common.rb CHANGED
@@ -1,66 +1,160 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
-
4
- macro :comment do
5
- ""
3
+ macro :snippet do
4
+ ident = @value.to_sym
5
+ if Glyph::SNIPPETS.has_key? ident then
6
+ begin
7
+ interpret Glyph::SNIPPETS[ident]
8
+ rescue Exception => e
9
+ raise if e.is_a? Glyph::MutualInclusionError
10
+ Glyph.warning e.message
11
+ macro_todo "Correct errors in snippet '#{@value}'"
12
+ end
13
+ else
14
+ macro_warning "Snippet '#{ident}' does not exist"
15
+ "[SNIPPET '#{@value}' NOT PROCESSED]"
16
+ end
6
17
  end
7
18
 
8
- macro :todo do
9
- todo = "[#{@source}] -- #{@value}"
10
- Glyph::TODOS << todo unless Glyph::TODOS.include? todo
19
+ macro "snippet:" do
20
+ exact_parameters 2
21
+ ident, text = params
22
+ Glyph::SNIPPETS[ident.to_sym] = text
11
23
  ""
12
24
  end
13
25
 
14
- macro :snippet do
15
- begin
16
- ident = @params[0].to_sym
17
- macro_error "Snippet '#{ident}' does not exist" unless Glyph::SNIPPETS.has_key? ident
18
- interpret Glyph::SNIPPETS[ident]
19
- rescue Exception => e
20
- warning e.message
21
- "[SNIPPET '#{@value}' NOT PROCESSED]"
26
+ macro "macro:" do
27
+ exact_parameters 2
28
+ ident, code = params
29
+ Glyph.macro(ident) do
30
+ instance_eval code
22
31
  end
32
+ ""
23
33
  end
24
34
 
25
35
  macro :include do
26
- begin
27
- file = nil
28
- (Glyph::PROJECT/"text").find do |f|
29
- file = f if f.to_s.match /\/#{@value}$/
30
- end
31
- macro_error "File '#{@value}' no found." unless file
36
+ macro_error "Macro not available when compiling a single file." if Glyph.lite?
37
+ file = nil
38
+ (Glyph::PROJECT/"text").find do |f|
39
+ file = f if f.to_s.match /\/#{@value}$/
40
+ end
41
+ if file then
32
42
  contents = file_load file
33
- if cfg("filters.by_file_extension") then
34
- begin
35
- ext = @value.match(/\.(.*)$/)[1]
36
- macro_error "Filter macro '#{ext}' not found" unless Glyph::MACROS.include?(ext.to_sym)
43
+ ext = @value.match(/\.(.*)$/)[1]
44
+ if Glyph["filters.by_file_extension"] && ext != 'glyph' then
45
+ if Glyph::MACROS.include?(ext.to_sym) then
37
46
  contents = "#{ext}[#{contents}]"
38
- rescue MacroError => e
39
- warning e.message
47
+ else
48
+ macro_warning "Filter macro '#{ext}' not available"
40
49
  end
41
50
  end
42
- interpret contents
43
- rescue MacroError => e
44
- warning e
51
+ begin
52
+ interpret contents
53
+ rescue Exception => e
54
+ raise if e.is_a? Glyph::MutualInclusionError
55
+ Glyph.warning e.message
56
+ macro_todo "Correct errors in file '#{@value}'"
57
+ end
58
+ else
59
+ macro_warning "File '#{@value}' no found."
45
60
  "[FILE '#{@value}' NOT FOUND]"
46
61
  end
47
62
  end
48
63
 
49
64
  macro :ruby do
50
- Kernel.instance_eval(@value)
65
+ res = Glyph.instance_eval(@value.gsub(/\\*([\[\]\|])/){$1})
66
+ res.is_a?(Proc) ? "" : res
51
67
  end
52
68
 
53
69
  macro :config do
54
- cfg @value
70
+ Glyph[@value]
71
+ end
72
+
73
+ macro "config:" do
74
+ exact_parameters 2
75
+ setting,value = params
76
+ Glyph[setting] = value
77
+ nil
78
+ end
79
+
80
+ macro :comment do
81
+ ""
55
82
  end
56
83
 
57
84
  macro :escape do
58
85
  @value
59
86
  end
60
87
 
88
+ macro :encode do
89
+ encode @value
90
+ end
91
+
92
+ macro :decode do
93
+ decode @value
94
+ end
95
+
96
+ macro :condition do
97
+ min_parameters 1
98
+ max_parameters 2
99
+ cond, actual_value = params
100
+ res = interpret(cond)
101
+ if res.blank? || res == "false" then
102
+ ""
103
+ else
104
+ interpret(decode(actual_value))
105
+ end
106
+ end
107
+
108
+
109
+ macro :eq do
110
+ min_parameters 1
111
+ max_parameters 2
112
+ a, b = params
113
+ res_a = interpret(a.to_s)
114
+ res_b = interpret(b.to_s)
115
+ (res_a == res_b) ? true : nil
116
+ end
117
+
118
+ macro :not do
119
+ max_parameters 1
120
+ v = interpret(@value)
121
+ (v.blank? || v == "false") ? true : nil
122
+ end
123
+
124
+ macro :and do
125
+ min_parameters 1
126
+ max_parameters 2
127
+ a, b = params
128
+ res_a = !interpret(a.to_s).blank?
129
+ res_b = !interpret(b.to_s).blank?
130
+ (res_a && res_b) ? true : nil
131
+ end
132
+
133
+ macro :or do
134
+ min_parameters 1
135
+ max_parameters 2
136
+ a, b = params
137
+ res_a = !interpret(a.to_s).blank?
138
+ res_b = !interpret(b.to_s).blank?
139
+ (res_a || res_b) ? true : nil
140
+ end
141
+
142
+ macro :match do
143
+ exact_parameters 2
144
+ val, regexp = params
145
+ macro_error "Invalid regular expression: #{regexp}" unless regexp.match /^\/.*\/[a-z]?$/
146
+ (interpret(val).match(instance_eval(regexp))) ? true : nil
147
+ end
148
+
61
149
  macro_alias '--' => :comment
150
+ macro_alias '*' => :encode
151
+ macro_alias '**' => :decode
62
152
  macro_alias '&' => :snippet
153
+ macro_alias '&:' => 'snippet:'
154
+ macro_alias '%:' => 'macro:'
63
155
  macro_alias '@' => :include
64
156
  macro_alias '%' => :ruby
65
157
  macro_alias '$' => :config
158
+ macro_alias '$:' => 'config:'
66
159
  macro_alias '.' => :escape
160
+ macro_alias '?' => :condition
data/macros/filters.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  macro :textile do
4
+ exact_parameters 1, :level => :warning
4
5
  rc = nil
5
6
  begin
6
7
  require 'RedCloth'
@@ -8,7 +9,7 @@ macro :textile do
8
9
  rescue Exception
9
10
  macro_error "RedCloth gem not installed. Please run: gem insall RedCloth"
10
11
  end
11
- target = cfg "filters.target"
12
+ target = Glyph["filters.target"]
12
13
  case target.to_sym
13
14
  when :html
14
15
  rc.to_html.gsub /<p><\/p>/, ''
@@ -20,45 +21,50 @@ macro :textile do
20
21
  end
21
22
 
22
23
  macro :markdown do
24
+ exact_parameters 1, :level => :warning
23
25
  md = nil
24
- markdown_converter = cfg "filters.markdown_converter"
26
+ markdown_converter = Glyph["filters.markdown_converter"].to_sym rescue nil
25
27
  if !markdown_converter then
26
28
  begin
27
29
  require 'bluecloth'
28
- markdown_converter = :BlueCloth
30
+ markdown_converter = :bluecloth
29
31
  rescue LoadError
30
32
  begin
31
33
  require 'rdiscount'
32
- markdown_converter = :RDiscount
34
+ markdown_converter = :rdiscount
33
35
  rescue LoadError
34
36
  begin
35
37
  require 'maruku'
36
- markdown_converter = :Maruku
38
+ markdown_converter = :maruku
37
39
  rescue LoadError
38
40
  begin
39
41
  require 'kramdown'
40
- markdown_converter = :Kramdown
42
+ markdown_converter = :kramdown
41
43
  rescue LoadError
42
- macro_error "No MarkDown converter installed. Please run: gem insall bluecloth"
44
+ macro_error "No MarkDown converter installed. Please run: gem install bluecloth"
43
45
  end
44
46
  end
45
47
  end
46
48
  end
47
- Glyph.config_override "filters.markdown_converter", markdown_converter
49
+ Glyph["filters.markdown_converter"] = markdown_converter
48
50
  end
49
51
  case markdown_converter
50
- when :BlueCloth
52
+ when :bluecloth
53
+ require 'bluecloth'
51
54
  md = BlueCloth.new @value
52
- when :RDiscount
55
+ when :rdiscount
56
+ require 'rdiscount'
53
57
  md = RDiscount.new @value
54
- when :Maruku
58
+ when :maruku
59
+ require 'maruku'
55
60
  md = Maruku.new @value
56
- when :Kramdown
61
+ when :kramdown
62
+ require 'kramdown'
57
63
  md = Kramdown::Document.new @value
58
64
  else
59
65
  macro_error "No MarkDown converter installed. Please run: gem insall bluecloth"
60
66
  end
61
- target = cfg "filters.target"
67
+ target = Glyph["filters.target"]
62
68
  if target.to_sym == :html then
63
69
  md.to_html
64
70
  else
data/macros/html/block.rb CHANGED
@@ -1,117 +1,168 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  macro :note do
4
- %{<div class="#{@name}"><span class="note-title">#{@name.to_s.capitalize}</span>#{@value}
4
+ %{<div class="#{@name}">
5
+ <span class="note-title">#{@name.to_s.capitalize}</span>#{@value}
5
6
 
6
- </div>}
7
+ </div>}
7
8
  end
8
9
 
9
10
  macro :box do
10
- %{<div class="box"><span class="box-title">#{@params[0]}</span>
11
- #{@params[1]}
11
+ exact_parameters 2, :level => :warning
12
+ %{<div class="box">
13
+ <div class="box-title">#{params[0]}</div>
14
+ #{params[1]}
12
15
 
13
- </div>}
16
+ </div>}
14
17
  end
15
18
 
16
19
  macro :code do
17
- %{<div class="code"><pre><code>
18
- #{@value.gsub('>', '&gt;').gsub('<', '&lt;')}
19
- </code></pre></div>}
20
+ min_parameters 1
21
+ %{
22
+ <div class="code">
23
+ <pre>
24
+ <code>
25
+ #{@value}
26
+ </code>
27
+ </pre>
28
+ </div>}
29
+ end
30
+
31
+ macro :highlight do
32
+ min_parameters 2
33
+ lang = params[0]
34
+ text = raw_params[1..raw_params.length-1].join '\\|'
35
+ text.gsub!(/\\(.)/){$1}
36
+ highlighter = Glyph["highlighters.current"].to_sym rescue nil
37
+ if !highlighter then
38
+ begin
39
+ require 'coderay'
40
+ highlighter = :coderay
41
+ rescue LoadError
42
+ begin
43
+ require 'uv'
44
+ highlighter = :ultraviolet
45
+ rescue LoadError
46
+ macro_error "No highlighter installed. Please run: gem install coderay"
47
+ end
48
+ end
49
+ Glyph["highlighter.current"] = highlighter
50
+ end
51
+ target = Glyph["highlighters.target"]
52
+ result = ""
53
+ case highlighter.to_sym
54
+ when :coderay
55
+ begin
56
+ require 'coderay'
57
+ result = CodeRay.scan(text, lang).div(Glyph["highlighters.coderay"])
58
+ rescue LoadError
59
+ macro_error "CodeRay highlighter not installed. Please run: gem install coderay"
60
+ rescue Exception => e
61
+ macro_error e.message
62
+ end
63
+ when :ultraviolet
64
+ begin
65
+ require 'uv'
66
+ target = 'xhtml' if target == 'html'
67
+ result = Uv.parse(text.to_s, target.to_s, lang.to_s,
68
+ Glyph["highlighters.ultraviolet.line_numbers"],
69
+ Glyph["highlighters.ultraviolet.theme"].to_s)
70
+ rescue LoadError
71
+ macro_error "UltraViolet highlighter not installed. Please run: gem install ultraviolet"
72
+ rescue Exception => e
73
+ puts e.backtrace
74
+ macro_error e.message
75
+ end
76
+ else
77
+ macro_error "No highlighter installed. Please run: gem install coderay"
78
+ end
79
+ result
20
80
  end
21
81
 
22
82
  macro :title do
23
- %{
24
- <h1>
25
- #{cfg("document.title")}
26
- </h1>
27
- }
83
+ no_parameters
84
+ %{<h1>
85
+ #{Glyph["document.title"]}
86
+ </h1>}
28
87
  end
29
88
 
30
89
  macro :img do
31
- image = @params[0]
32
- width = @params[1]
90
+ min_parameters 1
91
+ max_parameters 3
92
+ image = params[0]
93
+ width = params[1]
94
+ source_file = Glyph.lite? ? image : Glyph::PROJECT/"images/#{image}"
95
+ dest_file = Glyph.lite? ? image : "images/#{image}"
33
96
  w = (width) ? "width=\"#{width}\"" : ''
34
- height = @params[2]
97
+ height = params[2]
35
98
  h = (height) ? "height=\"#{height}\"" : ''
36
- if (Glyph::PROJECT/"images/#{image}").exist? then
37
- %{
38
- <img src="images/#{image}" #{w} #{h} alt="-"/>
39
- }
40
- else
41
- warning "Image '#{image}' not found"
42
- ""
43
- end
99
+ Glyph.warning "Image '#{image}' not found" unless Pathname.new(dest_file).exist?
100
+ %{<img src="#{dest_file}" #{w} #{h} alt="-"/>}
44
101
  end
45
102
 
46
103
  macro :fig do
47
- image = @params[0]
48
- caption = @params[1]
104
+ min_parameters 1
105
+ max_parameters 2
106
+ image = params[0]
107
+ caption = params[1]
49
108
  caption ||= nil
50
109
  caption = %{<div class="caption">#{caption}</div>} if caption
51
- if (Glyph::PROJECT/"images/#{image}").exist? then
52
- %{
53
- <div class="figure">
54
- <img src="images/#{image}" alt="-"/>
55
- #{caption}
56
- </div>
57
- }
58
- else
59
- warning "Figure '#{image}' not found"
60
- ""
61
- end
110
+ source_file = Glyph.lite? ? image : Glyph::PROJECT/"images/#{image}"
111
+ dest_file = Glyph.lite? ? image : "images/#{image}"
112
+ Glyph.warning "Figure '#{image}' not found" unless Pathname.new(dest_file).exist?
113
+ %{<div class="figure">
114
+ <img src="#{dest_file}" alt="-"/>
115
+ #{caption}
116
+ </div>}
62
117
  end
63
118
 
64
119
 
65
120
  macro :subtitle do
66
- %{
67
- <h2>
68
- #{cfg("document.subtitle")}
69
- </h2>
70
- }
121
+ no_parameters
122
+ %{<h2>
123
+ #{Glyph["document.subtitle"]}
124
+ </h2>}
71
125
  end
72
126
 
73
127
  macro :author do
74
- %{
75
- <div class="author">
76
- by <em>#{cfg("document.author")}</em>
77
- </div>
78
- }
128
+ no_parameters
129
+ %{<div class="author">
130
+ by <em>#{Glyph["document.author"]}</em>
131
+ </div>}
79
132
  end
80
133
 
81
134
  macro :pubdate do
82
- %{
83
- <div class="pubdate">
84
- #{Time.now.strftime("%B %Y")}
85
- </div>
86
- }
135
+ no_parameters
136
+ %{<div class="pubdate">
137
+ #{Time.now.strftime("%B %Y")}
138
+ </div>}
87
139
  end
88
140
 
89
141
  macro :table do
90
- %{
91
- <table>#{@value}
92
- </table>
93
- }
142
+ exact_parameters 1
143
+ %{<table>
144
+ #{@value}
145
+ </table>}
94
146
  end
95
147
 
96
148
  macro :tr do
97
- %{
98
- <tr>#{@value}
99
- </tr>
100
- }
149
+ exact_parameters 1, :level => :warning
150
+ %{<tr>
151
+ #{@value}
152
+ </tr>}
101
153
  end
102
154
 
103
155
  macro :td do
104
- %{
105
- <td>#{@value}
106
- </td>
107
- }
156
+ exact_parameters 1, :level => :warning
157
+ %{<td>
158
+ #{@value}
159
+
160
+ </td>}
108
161
  end
109
162
 
110
163
  macro :th do
111
- %{
112
- <th>#{@value}
113
- </th>
114
- }
164
+ exact_parameters 1, :level => :warning
165
+ %{<th>#{@value}</th>}
115
166
  end
116
167
 
117
168
  macro_alias :important => :note