glyph 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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