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.
Files changed (132) hide show
  1. data/Rakefile +19 -40
  2. data/benchmark.rb +1 -2
  3. data/book/config.yml +8 -8
  4. data/book/document.glyph +18 -19
  5. data/book/images/glyph/commands_tasks.png +0 -0
  6. data/book/lib/layouts/bookindex.glyph +113 -111
  7. data/book/lib/layouts/bookpage.glyph +112 -108
  8. data/book/lib/macros/reference.rb +2 -2
  9. data/book/lib/tasks/tasks.rake +1 -1
  10. data/book/text/acknowledgements.glyph +1 -0
  11. data/book/text/changelog.glyph +140 -112
  12. data/book/text/compiling/compiling.glyph +36 -24
  13. data/book/text/compiling/lite_mode.glyph +11 -11
  14. data/book/text/compiling/programmatic_usage.glyph +57 -57
  15. data/book/text/config/document.glyph +7 -1
  16. data/book/text/config/options.glyph +5 -3
  17. data/book/text/config/output.glyph +41 -8
  18. data/book/text/extending/bookmarks_headers.glyph +13 -11
  19. data/book/text/extending/command.glyph +1 -1
  20. data/book/text/extending/commands_tasks.glyph +2 -2
  21. data/book/text/extending/internals.glyph +29 -29
  22. data/book/text/extending/interpreting.glyph +48 -9
  23. data/book/text/extending/macro_def.glyph +80 -32
  24. data/book/text/extending/output_format.glyph +2 -2
  25. data/book/text/extending/placeholders.glyph +27 -15
  26. data/book/text/extending/validators.glyph +1 -1
  27. data/book/text/getting_started/configuration.glyph +1 -1
  28. data/book/text/getting_started/create_project.glyph +4 -5
  29. data/book/text/getting_started/structure.glyph +2 -2
  30. data/book/text/macros/macros_core.glyph +341 -199
  31. data/book/text/macros/macros_filters.glyph +1 -1
  32. data/book/text/macros/macros_inline.glyph +3 -3
  33. data/book/text/macros/macros_structure.glyph +1 -1
  34. data/book/text/ref_commands.glyph +98 -93
  35. data/book/text/snippets.glyph +18 -0
  36. data/book/text/stats/bookmarks.glyph +16 -16
  37. data/book/text/stats/links.glyph +23 -23
  38. data/book/text/stats/macros.glyph +14 -14
  39. data/book/text/stats/snippets.glyph +26 -26
  40. data/book/text/stats/stats.glyph +14 -15
  41. data/book/text/text_editing/attribute_intro.glyph +8 -8
  42. data/book/text/text_editing/code.glyph +16 -16
  43. data/book/text/text_editing/conditionals.glyph +12 -13
  44. data/book/text/text_editing/esc_quot.glyph +3 -3
  45. data/book/text/text_editing/evaluation.glyph +57 -3
  46. data/book/text/text_editing/inclusions.glyph +34 -25
  47. data/book/text/text_editing/macro_composition.glyph +28 -0
  48. data/book/text/text_editing/macro_intro.glyph +4 -4
  49. data/book/text/text_editing/section_aliases.glyph +23 -23
  50. data/book/text/text_editing/sections.glyph +22 -22
  51. data/book/text/text_editing/stylesheets.glyph +33 -33
  52. data/book/text/text_editing/topics.glyph +6 -6
  53. data/book/text/text_editing/xml_fallback.glyph +1 -1
  54. data/book/text/troubleshooting/errors_command.glyph +4 -4
  55. data/book/text/troubleshooting/errors_generic.glyph +16 -10
  56. data/book/text/troubleshooting/errors_macro.glyph +18 -21
  57. data/book/text/troubleshooting/errors_parser.glyph +7 -7
  58. data/config.yml +51 -29
  59. data/document.glyph +18 -18
  60. data/glyph.gemspec +39 -287
  61. data/layouts/web5/topic.glyph +1 -1
  62. data/lib/glyph.rb +42 -10
  63. data/lib/glyph/analyzer.rb +5 -2
  64. data/lib/glyph/bookmark.rb +3 -1
  65. data/lib/glyph/commands.rb +11 -9
  66. data/lib/glyph/commands/add.rb +3 -1
  67. data/lib/glyph/commands/compile.rb +10 -7
  68. data/lib/glyph/commands/config.rb +7 -5
  69. data/lib/glyph/commands/init.rb +2 -0
  70. data/lib/glyph/commands/outline.rb +2 -0
  71. data/lib/glyph/commands/stats.rb +3 -0
  72. data/lib/glyph/commands/todo.rb +2 -0
  73. data/lib/glyph/config.rb +2 -0
  74. data/lib/glyph/document.rb +34 -9
  75. data/lib/glyph/interpreter.rb +2 -0
  76. data/lib/glyph/macro.rb +97 -25
  77. data/lib/glyph/macro_validators.rb +9 -6
  78. data/lib/glyph/node.rb +3 -1
  79. data/lib/glyph/parser.rb +68 -33
  80. data/lib/glyph/reporter.rb +3 -1
  81. data/lib/glyph/syntax_node.rb +23 -28
  82. data/lib/glyph/system_extensions.rb +21 -0
  83. data/lib/glyph/utils.rb +24 -4
  84. data/macros/block.rb +111 -0
  85. data/macros/core.rb +163 -33
  86. data/macros/filters.rb +3 -2
  87. data/macros/inline.rb +97 -0
  88. data/macros/reps/html.rb +180 -0
  89. data/macros/reps/html5.rb +100 -0
  90. data/macros/reps/web.rb +4 -0
  91. data/macros/reps/web5.rb +4 -0
  92. data/macros/structure.rb +229 -0
  93. data/macros/xml.rb +29 -24
  94. data/spec/config.yml +7 -0
  95. data/spec/files/article.glyph +2 -2
  96. data/spec/files/web_doc.glyph +9 -5
  97. data/spec/lib/commands_spec.rb +13 -9
  98. data/spec/lib/config_spec.rb +2 -2
  99. data/spec/lib/document_spec.rb +10 -0
  100. data/spec/lib/glyph_spec.rb +30 -8
  101. data/spec/lib/macro_spec.rb +39 -4
  102. data/spec/lib/macro_validators_spec.rb +3 -4
  103. data/spec/lib/parser_spec.rb +7 -0
  104. data/spec/lib/reporter_spec.rb +1 -0
  105. data/spec/lib/syntax_node_spec.rb +40 -6
  106. data/spec/macros/core_spec.rb +154 -21
  107. data/spec/macros/filters_spec.rb +1 -1
  108. data/spec/macros/html5_spec.rb +4 -5
  109. data/spec/macros/macros_spec.rb +6 -7
  110. data/spec/macros/web5_spec.rb +3 -3
  111. data/spec/macros/web_spec.rb +10 -7
  112. data/spec/macros/xml_spec.rb +11 -2
  113. data/spec/spec_helper.rb +11 -5
  114. data/spec/tasks/generate_spec.rb +40 -5
  115. data/spec/tasks/load_spec.rb +1 -13
  116. data/styles/coderay.css +147 -38
  117. data/styles/default.css +19 -22
  118. data/styles/pagination.css +30 -30
  119. data/tasks/generate.rake +54 -18
  120. data/tasks/load.rake +9 -24
  121. data/tasks/project.rake +0 -2
  122. metadata +208 -207
  123. data/.gitignore +0 -7
  124. data/VERSION +0 -1
  125. data/book/snippets.yml +0 -18
  126. data/lib/glyph/macro_helpers.rb +0 -282
  127. data/macros/html/block.rb +0 -124
  128. data/macros/html/inline.rb +0 -42
  129. data/macros/html/structure.rb +0 -191
  130. data/macros/html5/block.rb +0 -69
  131. data/macros/html5/inline.rb +0 -24
  132. data/macros/html5/structure.rb +0 -140
data/macros/filters.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # encoding: utf-8
2
3
 
3
4
  macro :textile do
4
5
  exact_parameters 1
@@ -70,7 +71,7 @@ macro :markdown do
70
71
  end
71
72
  end
72
73
 
73
- rewrite "textile_section",
74
+ define "textile_section",
74
75
  %{section[
75
76
  @src[{{src}}]
76
77
  @id[{{id}}]
@@ -81,7 +82,7 @@ rewrite "textile_section",
81
82
  ]
82
83
  ]}
83
84
 
84
- rewrite "markdown_section",
85
+ define "markdown_section",
85
86
  %{section[
86
87
  @src[{{src}}]
87
88
  @id[{{id}}]
data/macros/inline.rb ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ macro :anchor do
5
+ min_parameters 1
6
+ max_parameters 2
7
+ bookmark :id => param(0), :title => param(1), :file => @source_file
8
+ @data[:id] = param 0
9
+ @data[:title] = param 1
10
+ render
11
+ end
12
+
13
+ macro :link do
14
+ min_parameters 1
15
+ max_parameters 2
16
+ target = param 0
17
+ title = param 1
18
+ if target.match /^#/ then
19
+ @node[:document].links << target
20
+ anchor = target.gsub /^#/, ''
21
+ bmk = bookmark? anchor
22
+ if !bmk then
23
+ placeholder do |document|
24
+ bmk = document.bookmark?(anchor)
25
+ macro_error "Bookmark '#{anchor}' does not exist" unless bmk
26
+ bmk_title = title
27
+ bmk_title = bmk.title if bmk_title.blank?
28
+ @data[:target] = bmk.link(@source_file)
29
+ @data[:title] = bmk_title
30
+ render
31
+ end
32
+ else
33
+ bmk_title = title
34
+ bmk_title = bmk.title if bmk_title.blank?
35
+ @data[:target] = bmk.link(@source_file)
36
+ @data[:title] = bmk_title
37
+ render
38
+ end
39
+ else
40
+ if Glyph['options.url_validation'] && !@node[:document].links.include?(target) then
41
+ begin
42
+ url = URI.parse(target.gsub(/\\\./, ''))
43
+ rescue Exception => e
44
+ macro_warning "Invalid URL: #{url||target}", e
45
+ end
46
+ response = Net::HTTP.get_response(url)
47
+ debug "Checking link URL: #{url} (#{response.code})"
48
+ if response.code.to_i > 302 then
49
+ macro_warning "Linked URL '#{url}' returned status #{response.code} (#{response.message})"
50
+ end
51
+ end
52
+ @node[:document].links << target
53
+ title ||= target
54
+ @data[:target] = target
55
+ @data[:title] = title
56
+ render
57
+ end
58
+ end
59
+
60
+ macro :fmi do
61
+ exact_parameters 2, :level => :warning
62
+ topic = param 0
63
+ href = param 1
64
+ link = placeholder do |document|
65
+ interpret "link[#{href}]"
66
+ end
67
+ @data[:topic] = topic
68
+ @data[:link] = link
69
+ render
70
+ end
71
+
72
+ macro :draftcomment do
73
+ if Glyph['document.draft'] then
74
+ @data[:comment] = value
75
+ render
76
+ else
77
+ ""
78
+ end
79
+ end
80
+
81
+ macro :todo do
82
+ exact_parameters 1
83
+ todo = {:source => @source_name, :text => value}
84
+ @node[:document].todos << todo unless @node[:document].todos.include? todo
85
+ if Glyph['document.draft'] then
86
+ @data[:todo] = value
87
+ render
88
+ else
89
+ ""
90
+ end
91
+ end
92
+
93
+ macro_alias :bookmark => :anchor
94
+ macro_alias '#' => :anchor
95
+ macro_alias '=>' => :link
96
+ macro_alias '!' => :todo
97
+ macro_alias :dc => :draftcomment
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # Inline
5
+
6
+ rep :link do |data|
7
+ %{<a href="#{data[:target]}">#{data[:title]}</a>}
8
+ end
9
+
10
+ rep :anchor do |data|
11
+ %{<a id="#{data[:id]}">#{data[:title]}</a>}
12
+ end
13
+
14
+ rep :fmi do |data|
15
+ %{<span class="fmi">for more information on #{data[:topic]}, see #{data[:link]}</span>}
16
+ end
17
+
18
+ rep :draftcomment do |data|
19
+ %{<span class="comment"><span class="comment-pre"><strong>Comment:</strong> </span>#{data[:comment]}</span>}
20
+ end
21
+
22
+ rep :todo do |data|
23
+ %{<span class="todo"><span class="todo-pre"><strong>TODO:</strong> </span>#{data[:todo]}</span>}
24
+ end
25
+
26
+ # Block
27
+
28
+ rep :note do |data|
29
+ css_class = data[:name].to_s.match(/[a-z0-9_-]/i) ? data[:name] : "note"
30
+ %{<div class="#{css_class}">
31
+ <span class="note-title">#{data[:name].to_s.capitalize}</span>#{data[:text]}
32
+
33
+ </div>}
34
+ end
35
+
36
+ rep :box do |data|
37
+ %{<div class="box">
38
+ <div class="box-title">#{data[:title]}</div>
39
+ #{data[:text]}
40
+
41
+ </div>}
42
+ end
43
+
44
+ rep :codeblock do |data|
45
+ %{
46
+ <div class="code">
47
+ <pre>
48
+ <code>
49
+ #{data[:text]}
50
+ </code>
51
+ </pre>
52
+ </div>}
53
+ end
54
+
55
+ rep :image do |data|
56
+ interpret "img[@src[#{data[:src]}]#{data[:attrs].join}]"
57
+ end
58
+
59
+ rep :figure do |data|
60
+ interpret %{div[@class[figure]#{data[:attrs].join}\\/img[@src[#{data[:src]}]]div[@class[caption]#{data[:caption]}]]}
61
+ end
62
+
63
+ rep :title do |data|
64
+ %{<h1>
65
+ #{Glyph["document.title"]}
66
+ </h1>}
67
+ end
68
+
69
+ rep :subtitle do |data|
70
+ %{<h2>
71
+ #{Glyph["document.subtitle"]}
72
+ </h2>}
73
+ end
74
+
75
+ rep :author do |data|
76
+ %{<div class="author">
77
+ by <em>#{Glyph["document.author"]}</em>
78
+ </div>}
79
+ end
80
+
81
+ rep :pubdate do |data|
82
+ %{<div class="pubdate">
83
+ #{data[:date]}
84
+ </div>}
85
+ end
86
+
87
+ rep :revision do |data|
88
+ %{<div class="revision">#{Glyph['document.revision']}</div>}
89
+ end
90
+
91
+ rep :navigation do |data|
92
+ %{<div class="navigation">#{data[:previous]} | #{data[:contents]} | #{data[:next]}</div>}
93
+ end
94
+
95
+ # Structure
96
+
97
+ rep :document do |data|
98
+ %{<?xml version="1.0" encoding="utf-8"?>
99
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
100
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
101
+ #{data[:content]}
102
+
103
+ </html>}
104
+ end
105
+
106
+ rep :meta do |data|
107
+ %{<meta name="#{data[:name]}" content="#{data[:content]}" />}
108
+ end
109
+
110
+ rep :head do |data|
111
+ %{<head>
112
+ <title>#{Glyph["document.title"]}</title>
113
+ #{data[:author]}
114
+ #{data[:copyright]}
115
+ <meta name="generator" content="Glyph v#{Glyph::VERSION} (http://www.h3rald.com/glyph)" />
116
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
117
+ #{data[:content]}
118
+ </head>
119
+ }
120
+ end
121
+
122
+ rep :style do |data|
123
+ file = data[:file]
124
+ case Glyph['document.styles'].to_s
125
+ when 'embed' then
126
+ style = ""
127
+ case file.extname
128
+ when ".css" then
129
+ style = file_load file
130
+ when ".sass", ".scss" then
131
+ begin
132
+ require 'sass'
133
+ style = Sass::Engine.new(file_load(file), :syntax => file.extname.gsub(/^\./, '').to_sym).render
134
+ rescue LoadError
135
+ macro_error "Sass is not installed. Please run: gem install sass"
136
+ rescue Exception
137
+ raise
138
+ end
139
+ else
140
+ macro_error "Extension '#{file.extname}' not supported."
141
+ end
142
+ %{<style type="text/css">
143
+ #{style}
144
+ </style>}
145
+ when 'import' then
146
+ %{<style type="text/css">
147
+ @import url("#{Glyph["output.#{Glyph['document.output']}.base"]}styles/#{value.gsub(/\..+$/, '.css')}");
148
+ </style>}
149
+ when 'link' then
150
+ %{<link href="#{Glyph["output.#{Glyph['document.output']}.base"]}styles/#{value.gsub(/\..+$/, '.css')}" rel="stylesheet" type="text/css" />}
151
+ else
152
+ macro_error "Value '#{Glyph['document.styles']}' not allowed for 'document.styles' setting"
153
+ end
154
+ end
155
+
156
+ rep :toc do |data|
157
+ %{<div class="contents">
158
+ <h2 class="toc-header" id="#{data[:toc_id]}">#{data[:title]}</h2>
159
+ <ol class="toc">
160
+ #{data[:descend_section].call(data[:document].structure, nil)}
161
+ </ol>
162
+ </div>}
163
+ end
164
+
165
+ rep :toc_item do |data|
166
+ "<li class=\"#{data[:classes].join(" ").strip}\">#{data[:title]}</li>"
167
+ end
168
+
169
+ rep :toc_sublist do |data|
170
+ "<li><ol>#{data[:contents]}</ol></li>\n"
171
+ end
172
+
173
+ rep :section do |data|
174
+ css_class = data[:name].to_s.match(/[a-z0-9_-]/i) ? data[:name] : "section"
175
+ title = data[:title] ? %{<h#{data[:level]} id="#{data[:id]}">#{data[:title]}</h#{data[:level]}>\n} : ""
176
+ %{<div class="#{css_class}">
177
+ #{title}#{data[:content]}
178
+
179
+ </div>}
180
+ end
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ reps_for :html
5
+
6
+ # Inline
7
+
8
+ rep :fmi do |data|
9
+ %{<span class="fmi">for more information on <mark>#{data[:topic]}</mark>, see #{data[:link]}</span>}
10
+ end
11
+
12
+ rep :draftcomment do |data|
13
+ %{<aside class="comment"><span class="comment-pre"><strong>Comment:</strong> </span>#{data[:comment]}</aside>}
14
+ end
15
+
16
+ rep :todo do |data|
17
+ %{<aside class="todo"><span class="todo-pre"><strong>TODO:</strong> </span>#{data[:todo]}</aside>}
18
+ end
19
+
20
+ # Block
21
+
22
+ rep :note do |data|
23
+ css_class = data[:name].to_s.match(/[a-z0-9_-]/i) ? data[:name] : "note"
24
+ %{<aside class="#{css_class}">
25
+ <span class="note-title">#{data[:name].to_s.capitalize}</span>#{data[:text]}
26
+
27
+ </aside>}
28
+ end
29
+
30
+ rep :box do |data|
31
+ %{<aside class="box">
32
+ <div class="box-title">#{data[:title]}</div>
33
+ #{data[:text]}
34
+
35
+ </aside>}
36
+ end
37
+
38
+ rep :figure do |data|
39
+ interpret %{xml/figure[#{data[:attrs].join}\\/xml/img[@src[#{data[:src]}]]xml/figcaption[#{data[:caption]}]]}
40
+ end
41
+
42
+ rep :title do |data|
43
+ %{<h1>
44
+ #{Glyph["document.title"]}
45
+ </h1>}
46
+ end
47
+
48
+ rep :subtitle do |data|
49
+ %{<h2>
50
+ #{Glyph["document.subtitle"]}
51
+ </h2>}
52
+ end
53
+
54
+ rep :author do |data|
55
+ %{<div class="author">
56
+ by <em>#{Glyph["document.author"]}</em>
57
+ </div>}
58
+ end
59
+
60
+ rep :pubdate do |data|
61
+ %{<time class="pubdate" datetime="#{Time.now.strftime("%Y-%m-%d")}">
62
+ #{data[:date]}
63
+ </time>}
64
+ end
65
+
66
+ rep :revision do |data|
67
+ %{<div class="revision">#{Glyph['document.revision']}</div>}
68
+ end
69
+
70
+ rep :navigation do |data|
71
+ %{<nav class="navigation">#{data[:previous]} | #{data[:contents]} | #{data[:next]}</nav>}
72
+ end
73
+
74
+ # Structure
75
+
76
+ rep :document do |data|
77
+ %{<!DOCTYPE html>
78
+ <html lang="en">
79
+ #{data[:content]}
80
+
81
+ </html>}
82
+ end
83
+
84
+ rep :toc do |data|
85
+ %{<nav class="contents">
86
+ <h1 class="toc-header" id="#{data[:toc_id]}">#{data[:title]}</h1>
87
+ <ol class="toc">
88
+ #{data[:descend_section].call(data[:document].structure, nil)}
89
+ </ol>
90
+ </nav>}
91
+ end
92
+
93
+ rep :section do |data|
94
+ css_class = data[:name].to_s.match(/[a-z0-9_-]/i) ? data[:name] : "section"
95
+ title = data[:title] ? %{<header><h1 id="#{data[:id]}">#{data[:title]}</h1></header>\n} : ""
96
+ %{<section class="#{css_class}">
97
+ #{title}#{data[:content]}
98
+
99
+ </section>}
100
+ end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ reps_for :html
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ reps_for :html5
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ macro :section do
5
+ max_parameters 1
6
+ if raw_attribute(:src) && Glyph.multiple_output_files? then
7
+ required_attribute :title
8
+ end
9
+ @data[:name] = @name
10
+ h = ""
11
+ if attr(:title) then
12
+ level = 1
13
+ @node.ascend do |n|
14
+ break if n.respond_to?(:attribute) && n.attribute(:class) && n.attribute(:class).children.join.strip == "topic"
15
+ #if n.is_a?(Glyph::MacroNode) && Glyph["system.structure.headers"].include?(n[:name]) then
16
+ if n.is_a?(Glyph::MacroNode) && n[:name].in?(Glyph.titled_sections) then
17
+ level+=1
18
+ end
19
+ end
20
+ ident = (attr(:id) || "h_#{@node[:document].headers.length+1}").to_sym
21
+ # The bookmark is added when the section is first processed; therefore it will exist already when a topic layout is processed
22
+ bmk = @node[:document].bookmark?(ident)
23
+ bmk ||= header :title => attr(:title),
24
+ :level => level,
25
+ :id => ident,
26
+ :toc => !attr(:notoc),
27
+ :definition => @source_file,
28
+ :file => (attr(:src) || @source_file)
29
+ @node[:header] = bmk
30
+ @data[:title] = attr :title
31
+ @data[:level] = level
32
+ @data[:id] = bmk.code
33
+ end
34
+ if attr(:src) then
35
+ # Create topic
36
+ if Glyph.multiple_output_files?
37
+ topic_id = (attr(:id) || "t_#{@node[:document].topics.length}").to_sym
38
+ layout = attr(:layout) || Glyph["output.#{Glyph['document.output']}.layouts.topic"] || :topic
39
+ layout_name = "layout/#{layout}".to_sym
40
+ macro_error "Layout '#{layout}' not found" unless Glyph::MACROS[layout_name]
41
+ result = interpret %{#{layout_name}[
42
+ @title[#{attr(:title)}]
43
+ @id[#{topic_id}]
44
+ @contents[include[@topic[true]#{attr(:src)}]]
45
+ ]}
46
+ bmk = @node[:document].bookmark? topic_id
47
+ if bmk then
48
+ # Fix file for topic bookmark
49
+ @node[:document].bookmark?(topic_id).file = attr(:src)
50
+ else
51
+ bookmark :title => attr(:title), :id => topic_id, :file => attr(:src), :definition => @source_file
52
+ end
53
+ topic_src = attr(:src)
54
+ topic_src += ".glyph" unless topic_src.match /\..+$/
55
+ @node[:document].topics << {:src => topic_src, :title => attr(:title), :id => topic_id, :contents => result}
56
+ # Process section contents
57
+ @data[:content] = value
58
+ else
59
+ v = raw_value
60
+ @node.children.delete_if{|c| !c.is_a?(Glyph::AttributeNode)}
61
+ body = interpret "include[#{attr(:src)}]#{v}"
62
+ @data[:content] = body
63
+ end
64
+ else
65
+ @data[:content] = value
66
+ end
67
+ render
68
+ end
69
+
70
+ macro :article do
71
+ exact_parameters 1
72
+ head = raw_attr(:head)
73
+ head ||= %{style[default.css]}
74
+ pre_title = raw_attr(:"pre-title")
75
+ post_title = raw_attr(:"post-title")
76
+ pubdate = @node.attr(:pubdate) ? "pubdate[#{@node.attr(:pubdate).contents}]" : "pubdate[]"
77
+ halftitlepage = raw_attr(:halftitlepage)
78
+ halftitlepage ||= %{
79
+ #{pre_title}
80
+ title[]
81
+ subtitle[]
82
+ author[]
83
+ #{pubdate}
84
+ #{post_title}
85
+ }
86
+ interpret %{document[
87
+ head[#{head}]
88
+ body[
89
+ halftitlepage[
90
+ #{halftitlepage}
91
+ ]
92
+ #{@node.value}
93
+ ]
94
+ ]}
95
+ end
96
+
97
+ macro :book do
98
+ no_parameters
99
+ head = raw_attr(:head)
100
+ head ||= %{style[default.css]}
101
+ pre_title = raw_attr(:"pre-title")
102
+ post_title = raw_attr(:"post-title")
103
+ titlepage = raw_attr(:titlepage)
104
+ pubdate = @node.attr(:pubdate) ? "pubdate[#{@node.attr(:pubdate).contents}]" : "pubdate[]"
105
+ titlepage ||= %{
106
+ #{pre_title}
107
+ title[]
108
+ subtitle[]
109
+ revision[]
110
+ author[]
111
+ #{pubdate}
112
+ #{post_title}
113
+ }
114
+ frontmatter = raw_attr(:frontmatter)
115
+ bodymatter = raw_attr(:bodymatter)
116
+ backmatter = raw_attr(:backmatter)
117
+ frontmatter = "frontmatter[\n#{frontmatter}\n]" if frontmatter
118
+ bodymatter = "bodymatter[\n#{bodymatter}\n]" if bodymatter
119
+ backmatter = "backmatter[\n#{backmatter}\n]" if backmatter
120
+ interpret %{document[
121
+ head[#{head}]
122
+ body[
123
+ titlepage[
124
+ #{titlepage}
125
+ ]
126
+ #{frontmatter}
127
+ #{bodymatter}
128
+ #{backmatter}
129
+ ]
130
+ ]}
131
+ end
132
+
133
+
134
+ macro :document do
135
+ exact_parameters 1
136
+ @data[:content] = value
137
+ render
138
+ end
139
+
140
+ macro :head do
141
+ exact_parameters 1
142
+ @data[:author] = Glyph['document.author'].blank? ? "" : render(:meta, :name => "author", :content => Glyph['document.author'])
143
+ @data[:copyright] = Glyph['document.author'].blank? ? "" : render(:meta, :name => "copyright", :content => Glyph['document.author'])
144
+ @data[:content] = value
145
+ render
146
+ end
147
+
148
+ macro :style do
149
+ within :head
150
+ exact_parameters 1
151
+ file = Glyph.lite? ? Pathname.new(value) : Glyph::PROJECT/"styles/#{value}"
152
+ file = Pathname.new Glyph::HOME/'styles'/value unless file.exist?
153
+ macro_error "Stylesheet '#{value}' not found" unless file.exist?
154
+ @node[:document].style file
155
+ @data[:file] = file
156
+ render
157
+ end
158
+
159
+ macro :toc do
160
+ if @node[:document].toc[:contents] then
161
+ @node[:document].toc[:contents]
162
+ else
163
+ max_parameters 1
164
+ depth = param(0)
165
+ toc = placeholder do |document|
166
+ descend_section = lambda do |n1, added_headers|
167
+ list = ""
168
+ added_headers ||= []
169
+ n1.descend do |n2, level|
170
+ if n2.is_a?(Glyph::MacroNode) && n2[:name].in?(Glyph.titled_sections) then
171
+ if Glyph.multiple_output_files? then
172
+ # Only consider topics/booklets when building TOC for web/web5
173
+ next if !n2.attribute(:src) && n2.child_macros.select{|child| child.attribute(:src)}.blank?
174
+ end
175
+ next if n2.find_parent{|node| Glyph['system.structure.special'].include? node[:name] }
176
+ header_obj = n2[:header]
177
+ next if depth && header_obj && (header_obj.level-1 > depth.to_i) || header_obj && !header_obj.toc?
178
+ next if added_headers.include? header_obj
179
+ added_headers << header_obj
180
+ # Check if part of frontmatter, bodymatter or backmatter
181
+ container = n2.find_parent do |node|
182
+ node.is_a?(Glyph::MacroNode) &&
183
+ node[:name].in?([:frontmatter, :bodymatter, :appendix, :backmatter])
184
+ end[:name] rescue nil
185
+ if header_obj then
186
+ if (!Glyph.multiple_output_files? || (header_obj.definition != header_obj.file)) then
187
+ link_header = render(:link, :title => header_obj.title, :target => header_obj.link(@source_file))
188
+ else
189
+ link_header = header_obj.title
190
+ end
191
+ list << render(:toc_item, :classes => [container, n2[:name]], :title => link_header)
192
+ end
193
+ child_list = ""
194
+ n2.children.each do |c|
195
+ child_list << descend_section.call(c, added_headers)
196
+ end
197
+ list << render(:toc_sublist, :contents => child_list) unless child_list.blank?
198
+ end
199
+ end
200
+ list
201
+ end
202
+ title ||= "Table of Contents"
203
+ bmk = @node[:document].bookmark?(:toc) || bookmark(:id => :toc, :file => @source_file, :title => title)
204
+ @data[:toc_id] = bmk.to_s
205
+ @data[:title] = bmk.title
206
+ @data[:document] = document
207
+ @data[:descend_section] = descend_section
208
+ render
209
+ end
210
+ @node[:document].toc[:contents] = toc.to_s
211
+ toc
212
+ end
213
+ end
214
+
215
+ # See:
216
+ # http://microformats.org/wiki/book-brainstorming
217
+ # http://en.wikipedia.org/wiki/Book_design
218
+
219
+ (Glyph['system.structure.frontmatter'] + Glyph['system.structure.bodymatter'] + Glyph['system.structure.backmatter']).
220
+ each {|s| macro_alias s => :section }
221
+
222
+ macro_alias "§" => :section
223
+ macro_alias :frontcover => :section
224
+ macro_alias :titlepage => :section
225
+ macro_alias :halftitlepage => :section
226
+ macro_alias :frontmatter => :section
227
+ macro_alias :bodymatter => :section
228
+ macro_alias :backmatter => :section
229
+ macro_alias :backcover => :section