erbook 5.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/LICENSE +1 -1
  2. data/Rakefile +6 -79
  3. data/bin/erbook +25 -319
  4. data/doc/HelloWorld.spec +23 -21
  5. data/doc/README +4 -3
  6. data/doc/api/ERBook.html +35 -0
  7. data/doc/api/ERBook/Document.html +673 -0
  8. data/doc/api/ERBook/Document/Node.html +102 -0
  9. data/doc/api/ERBook/Template.html +670 -0
  10. data/doc/api/RDoc.html +23 -0
  11. data/doc/api/RDoc/AnyMethod.html +302 -0
  12. data/doc/api/RDoc/DummyMarkup.html +73 -0
  13. data/doc/api/RDoc/DummyMixin.html +23 -0
  14. data/doc/api/RDoc/DummyOptions.html +140 -0
  15. data/doc/api/RDoc/TopLevel.html +465 -0
  16. data/doc/api/String.html +372 -0
  17. data/doc/api/all-methods.html +253 -0
  18. data/doc/api/all-namespaces.html +42 -0
  19. data/doc/api/app.js +18 -0
  20. data/doc/api/index.html +16 -22
  21. data/doc/api/jquery.js +11 -0
  22. data/doc/api/readme.html +35 -0
  23. data/doc/api/style.css +68 -0
  24. data/doc/api/syntax_highlight.css +21 -0
  25. data/doc/erbook.png +0 -0
  26. data/doc/erbook.svg +150 -88
  27. data/doc/formats.erb +387 -0
  28. data/doc/history.erb +62 -0
  29. data/doc/index.erb +8 -0
  30. data/doc/index.xhtml +846 -654
  31. data/doc/intro.erb +97 -0
  32. data/doc/setup.erb +62 -0
  33. data/doc/theory.erb +187 -0
  34. data/doc/usage.erb +39 -0
  35. data/fmt/xhtml.yaml +497 -372
  36. data/lib/erbook.rb +18 -10
  37. data/lib/erbook/document.rb +233 -0
  38. data/lib/erbook/template.rb +210 -0
  39. data/lib/erbook/to_xhtml.rb +25 -17
  40. metadata +39 -45
  41. data/README +0 -14
  42. data/doc/api/classes/ERBook.html +0 -164
  43. data/doc/api/classes/RDoc.html +0 -112
  44. data/doc/api/classes/RDoc/AnyMethod.html +0 -195
  45. data/doc/api/classes/RDoc/AnyMethod.src/M000003.html +0 -18
  46. data/doc/api/classes/RDoc/AnyMethod.src/M000004.html +0 -23
  47. data/doc/api/classes/RDoc/AnyMethod.src/M000005.html +0 -18
  48. data/doc/api/classes/RDoc/AnyMethod.src/M000006.html +0 -22
  49. data/doc/api/classes/RDoc/TopLevel.html +0 -250
  50. data/doc/api/classes/RDoc/TopLevel.src/M000007.html +0 -18
  51. data/doc/api/classes/RDoc/TopLevel.src/M000008.html +0 -18
  52. data/doc/api/classes/RDoc/TopLevel.src/M000009.html +0 -18
  53. data/doc/api/classes/RDoc/TopLevel.src/M000010.html +0 -29
  54. data/doc/api/classes/RDoc/TopLevel.src/M000011.html +0 -25
  55. data/doc/api/classes/RDoc/TopLevel.src/M000012.html +0 -18
  56. data/doc/api/classes/String.html +0 -196
  57. data/doc/api/classes/String.src/M000001.html +0 -18
  58. data/doc/api/classes/String.src/M000002.html +0 -31
  59. data/doc/api/created.rid +0 -1
  60. data/doc/api/files/lib/erbook/rdoc_rb.html +0 -116
  61. data/doc/api/files/lib/erbook/to_xhtml_rb.html +0 -125
  62. data/doc/api/files/lib/erbook_rb.html +0 -107
  63. data/doc/api/fr_class_index.html +0 -31
  64. data/doc/api/fr_file_index.html +0 -29
  65. data/doc/api/fr_method_index.html +0 -38
  66. data/doc/api/rdoc-style.css +0 -208
  67. data/doc/feed-icon-28x28.png +0 -0
  68. data/doc/manual.erb +0 -812
data/doc/intro.erb ADDED
@@ -0,0 +1,97 @@
1
+ <% chapter "Introduction" do %>
2
+ <% eruby_url = "http://en.wikipedia.org/wiki/ERuby" %>
3
+
4
+ <% project_summary do %>
5
+ **<%= $project %>** is an extensible document processor that emits <%= xref "HelloWorld", "any document you can imagine" %> from [eRuby templates](<%= eruby_url %>) that allow scripting and dynamic content generation.
6
+
7
+ A working <%= xref "xhtml", "XHTML (web page)" %> format is provided, while <%= xref "latex", "LaTeX (PDF)" %>, <%= xref "man", "UNIX manual page" %>, and <%= xref "text", "plain text" %> formats are planned... <%= xref "License", "patches are welcome" %>!
8
+ <% end %>
9
+
10
+ **<%= $project %>** is exciting because:
11
+ * Its documents are scriptable [eRuby templates](<%= eruby_url %>).
12
+ * It lets you <%= xref "HelloWorld", "define your own document formats" %>.
13
+ * Its core contains less than 300 lines of code.
14
+
15
+ These features distinguish **<%= $project %>** from the competition, which offers neither scriptable documents nor definable document formats:
16
+ * [DocBook](http://www.docbook.org)
17
+ * [Deplate](http://deplate.sourceforge.net)
18
+ * [SiSU](http://www.jus.uio.no/sisu/SiSU/)
19
+ * [AsciiDoc](http://www.methods.co.nz/asciidoc/)
20
+ * [txt2tags](http://txt2tags.sourceforge.net)
21
+ * [Grutatxt](http://www.triptico.com/software/grutatxt.html)
22
+
23
+ <% section "Logistics" do %>
24
+ * <%= xref "history", "Release notes" %> --- history of project releases.
25
+ * [Source code](http://github.com/sunaku/<%= $program %>) --- obtain via [Git](http://git.or.cz) or browse online.
26
+ * [API reference](api/index.html) --- documentation for source code.
27
+
28
+ To get help or provide feedback, simply
29
+ <%= xref "License", "contact the authors" %>.
30
+
31
+ <% paragraph "Version numbers" do %>
32
+ **<%= $project %>** releases are numbered in *major.minor.patch*
33
+ form according to the [RubyGems rational versioning
34
+ policy](http://www.rubygems.org/read/chapter/7), which
35
+ can be summarized thus:
36
+
37
+ <table markdown="1">
38
+ <thead>
39
+ <tr>
40
+ <td rowspan="2">What increased in the version number?</td>
41
+ <td colspan="3">The increase indicates that the release:</td>
42
+ </tr>
43
+ <tr>
44
+ <th>Is backward compatible?</th>
45
+ <th>Has new features?</th>
46
+ <th>Has bug fixes?</th>
47
+ </tr>
48
+ </thead>
49
+ <tbody>
50
+ <tr>
51
+ <th>major</th>
52
+ <td style="background-color: #FFE4E1;">No</td>
53
+ <td>Yes</td>
54
+ <td>Yes</td>
55
+ </tr>
56
+ <tr>
57
+ <th>minor</th>
58
+ <td>Yes</td>
59
+ <td>Yes</td>
60
+ <td>Yes</td>
61
+ </tr>
62
+ <tr>
63
+ <th>patch</th>
64
+ <td>Yes</td>
65
+ <td style="background-color: #FFE4E1;">No</td>
66
+ <td>Yes</td>
67
+ </tr>
68
+ </tbody>
69
+ </table>
70
+ <% end %>
71
+ <% end %>
72
+
73
+ <% section "License" do %>
74
+ <%# include ../LICENSE #%>
75
+ <% end %>
76
+
77
+ <% section "Credits" do %>
78
+ <%= $logo = "![#{$project} logo](#{$program}.png)".to_inline_xhtml %>
79
+ <%# include README #%>
80
+ <% end %>
81
+
82
+ <% section "Reviews" do %>
83
+ Vitor Peres in [ruby-talk](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/283052):
84
+
85
+ > I actually felt like printing \[this manual], because it's just so well-thought typographically... Even if \[**<%= $project %>**] weren't great by itself, I'd feel good just looking at the manual.
86
+
87
+
88
+ Ara T. Howard in [ruby-talk](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/282949):
89
+
90
+ > \[this manual is] a insanely complete and nice looking bit of documentation \[... **<%= $project %>**] looks like a great project
91
+
92
+
93
+ Martin DeMello in [ruby-talk](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/283304):
94
+
95
+ > Very nice work indeed!
96
+ <% end %>
97
+ <% end %>
data/doc/setup.erb ADDED
@@ -0,0 +1,62 @@
1
+ <% chapter "Setup" do %>
2
+ <% section "Requirements" do %>
3
+ Your system needs the following software to run **<%= $project %>**.
4
+
5
+ | Software | Description | Notes |
6
+ | -------- | ----------- | ----- |
7
+ | [Ruby](http://ruby-lang.org) | Ruby language interpreter | Version 1.8.7 or newer is required. |
8
+ | [RubyGems](http://rubygems.org) | Ruby packaging system | Version 1.0.0 or newer is required. |
9
+ <% end %>
10
+
11
+ <% section "Installation" do %>
12
+ You can install **<%= $project %>** by running this command:
13
+
14
+ gem install <%= $program %>
15
+
16
+ To check whether the installation was sucessful, run this command:
17
+
18
+ <%= $program %> -v
19
+
20
+ If the installation was successful, you will see output like this:
21
+
22
+ <pre><%= verbatim `ruby bin/#{$program} -v` %></pre>
23
+
24
+ Otherwise, you can <%= xref "License", "contact the author" %> for help.
25
+ <% end %>
26
+
27
+ <% section "Manifest" do %>
28
+ You will see the following items inside **<%= $project %>**'s installation directory, whose path you can determine by running this command:
29
+
30
+ <%= $program %> -v
31
+
32
+ * <tt>bin/</tt>
33
+
34
+ * <tt><%= $program %></tt> --- the main **<%= $project %>** executable.
35
+
36
+ * <tt>fmt/</tt> --- contains the predefined set of <%= xref "SpecFile", "format specification files" %>. If you ever need to install your custom format specification file globally, then put it inside this directory.
37
+
38
+ <% ERBook::FORMAT_FILES.each do |file| %>
39
+ * <tt><%= File.basename(file) %></tt> --- <%= YAML.load_file(file)['desc'] %>
40
+ <% end %>
41
+
42
+ * <tt>lib/</tt>
43
+
44
+ * <tt><%= $program %>.rb</tt> --- the main **<%= $project %>** library.
45
+
46
+ * <tt><%= $program %>/</tt>
47
+
48
+ * <tt>to_xhtml.rb</tt> --- provides methods (see <%= xref "Text to XHTML conversion" %>) for the <%= xref "xhtml" %> format.
49
+
50
+ * <tt>rdoc.rb</tt> --- provides RDoc parse trees to Ruby code.
51
+
52
+ * <tt>doc/</tt> --- contains this manual and other documentation.
53
+
54
+ * <tt><%= $program %>.svg</tt> --- source file of the **<%= $project %>** logo.
55
+
56
+ * <tt>index.erb</tt> --- source file of this manual.
57
+
58
+ * <tt>api/</tt> --- API reference documentation.
59
+
60
+ * <tt>LICENSE</tt> --- project license and copyright notice.
61
+ <% end %>
62
+ <% end %>
data/doc/theory.erb ADDED
@@ -0,0 +1,187 @@
1
+ <% chapter "Theory of operation" do %>
2
+ When you run <%= $project %>, it does the following:
3
+
4
+ 1. Loads the <%= xref "SpecFile", "format specification file" %>.
5
+
6
+ 2. Creates an **input document** by:
7
+
8
+ * Reading the input (the content of either the input file or the standard input stream) into memory.
9
+
10
+ * Evaluating <%= xref "include", "include directives" %> in the input.
11
+
12
+ 3. Transforms the input document into a **processed document** by:
13
+
14
+ * Building a **document tree** data structure from <%= xref "Nodes", "nodes" %> present in the input document.
15
+
16
+ * Replacing every node in the input document with the result of its <%= xref "SpecFile.nodes.output", "node output template" %>.
17
+
18
+ 4. Transforms the processed document into an **output document** according to the <%= xref "SpecFile.output", "document output template" %>.
19
+
20
+ 5. Prints the output document to the standard output stream.
21
+
22
+ Although there is only one document being processed here, we refer to it using three distinct terms: **input**, **processed**, and **output**; because the content of the document changes radically with every transformation.
23
+
24
+ <% section "Nodes" do %>
25
+ A node is a block of text that appears like this:
26
+
27
+ <%% node_type node_argument1, node_argument2, ... do |node_object| %>
28
+ node_content
29
+ <%% end %>
30
+
31
+ Or like this:
32
+
33
+ <%% node_type node_argument1, node_argument2, ... do %>
34
+ node_content
35
+ <%% end %>
36
+
37
+ Or like this:
38
+
39
+ <%%= node_type node_argument1, node_argument2, ... %>
40
+
41
+ Alternatively, you may omit the leading "<" and trailing "%>" characters from an eRuby directive if the directive spans an _entire_ line. So, the above examples become:
42
+
43
+ %% node_type node_argument1, node_argument2, ... do |node_object|
44
+ node_content
45
+ %% end
46
+
47
+ And:
48
+
49
+ %% node_type node_argument1, node_argument2, ... do
50
+ node_content
51
+ %% end
52
+
53
+ And:
54
+
55
+ %%= node_type node_argument1, node_argument2, ...
56
+
57
+ Technically, nodes are Ruby method invocations composed of the following:
58
+
59
+ | Component | Description |
60
+ | --------- | ----------- |
61
+ | `node_type` | name of the method being invoked |
62
+ | `node_argument1, node_argument2, ...` | arguments for the method invocation |
63
+ | `node_content` | a block argument being passed to the method invocation |
64
+ | `node_object` | a `ERBook::Document::Node` object (see <%= xref "Node.class" %>) representing this method invocation |
65
+
66
+ A <%= xref "SpecFile", "format specification file" %> defines what types of nodes an input document may use.
67
+
68
+ <% section "The `ERBook::Document::Node` class", "Node.class" do %>
69
+ When <%= $project %> builds a document tree from the nodes in an input document, it stores information about these nodes into `ERBook::Document::Node` objects. A `ERBook::Document::Node` object has the following properties (methods):
70
+
71
+ | Property | Type | Description |
72
+ | -------- | ---- | ----------- |
73
+ | type | `String` | Name of the type of this node. |
74
+ | args | `Array` | Arguments passed to this node. |
75
+ | content | `String` | The block of text passed to this node. |
76
+ | output | `String` | Result of the node output template for the content of this node. |
77
+ | digest | `String` | A unique identifier for the content of this node. |
78
+ | trace | `Array` | A stack trace describing the location of this node in the input document. |
79
+ | index | `String` | A LaTeX-style section number for this node. This property is only present if the **index** parameter is enabled in the definition of this type of node. |
80
+ | number | `Integer` | An order-of-occurrence number for this node. This property is only present if the **number** parameter is enabled in the definition of this type of node. |
81
+ | depth | `Integer` | Distance from the root of the document tree to this node. |
82
+ | parent | `ERBook::Document::Node` | The `ERBook::Document::Node` object which contains this node. The value of this property will be `nil` if this node is a root of the document tree. |
83
+ | children | `Array` of `ERBook::Document::Node` | List of child nodes from the document tree. |
84
+
85
+ Furthermore, the `ERBook::Document::Node` class is derived from [Ruby's `OpenStruct` class](http://www.ruby-doc.org/stdlib/libdoc/ostruct/rdoc/classes/OpenStruct.html), so you can define new properties for `ERBook::Document::Node` objects dynamically.
86
+ <% end %>
87
+ <% end %>
88
+
89
+ <% section "Format specification file", "SpecFile" do %>
90
+ A format specification file is a plain-text file marked up in [YAML syntax](http://yaml4r.sourceforge.net/cookbook/). Through the following parameters, it defines (1) what types of nodes an input document may contain, (2) how the content of those nodes is transformed into output, and (3) how the processed document is transformed into the output document.
91
+
92
+ | Parameter | Type | Description |
93
+ | --------- | ---- | ----------- |
94
+ | desc | `String` | A short description of the output format. |
95
+ | code | `String` | Ruby code that will be loaded before the input document is processed. This source code will be evaluated inside the main <%= $project %> executable, so any file-system or path-dependent portions of this source code should take appropriate precautions. |
96
+ | nodes | Hash | A listing of <%= xref "SpecFile.nodes", "node definitions" %>. |
97
+ | output | `String` | An eRuby template for the final output document. See <%= xref "SpecFile.output" %>. |
98
+
99
+ <%
100
+ # XXX: "declare" this local variable here (in the parent
101
+ # scope) because it is initialized and used in two
102
+ # different child scopes that exist at different depths
103
+ common_template_vars = nil
104
+ %>
105
+
106
+ <% section "Node definition", "SpecFile.nodes" do %>
107
+ A node definition is a mapping from a name (the "node type") to the following set of parameters:
108
+
109
+ | Parameter | Type | Description |
110
+ | --------- | ---- | ----------- |
111
+ | index | Boolean | Assign a LaTeX-style section number to this node? |
112
+ | number | Boolean | Assign an order-of-occurrence number to this node? |
113
+ | silent | Boolean | Suppress the output of this node? |
114
+ | output | `String` | An eRuby template for the content of this node. See <%= xref "SpecFile.nodes.output" %>. |
115
+ | inline | Boolean | Is node's output an in-line string of text that can be embedded anywhere in the document? |
116
+
117
+ You may define additional parameters in a node definition if you want.
118
+
119
+ <% section "Node output template", "SpecFile.nodes.output" do %>
120
+ A node output template (the **output** parameter in a node definition) is an eRuby template that transforms a node's content into output. During the processing stage, <%= $project %> replaces all nodes in the input document with the result of this template _unless_ the **silent** parameter is enabled in this node's definition.
121
+
122
+ The following variables are available for use in this template:
123
+
124
+ | Variable | Type | Description |
125
+ | -------- | ---- | ----------- |
126
+ | `@node` | `ERBook::Document::Node` | The node for which this template is being evaluated. |
127
+ <%= common_template_vars = %{
128
+ | `@roots` | `Array` of `ERBook::Document::Node` | All root nodes in the document tree. |
129
+ | `@nodes` | `Array` of `ERBook::Document::Node` | All nodes in the document tree. |
130
+ | `@nodes_by_type` | `Hash` | Mapping from node type (`String`) to array of `ERBook::Document::Node` objects having that type. |
131
+ | `@format` | `Hash` | Data from the format specification file. |
132
+
133
+ #{PROJECT} also provides the following mappings inside the `@format` variable:
134
+
135
+ | Expression | Type | Description |
136
+ | ---------- | ---- | ----------- |
137
+ | `@format[:name]` | `String` | Short-hand name of the current format. |
138
+ | `@format[:file]` | `String` | Path of the current format specification file. |
139
+ }.lstrip.gsub(/^ +/, '')
140
+ %>
141
+ <% end %>
142
+ <% end %>
143
+
144
+ <% section "Document output template", "SpecFile.output" do %>
145
+ A document output template (the **output** parameter in a format specification file) is an eRuby template that transforms a processed document into the final output document.
146
+
147
+ The following variables are available for use in this template:
148
+
149
+ | Variable | Type | Description |
150
+ | -------- | ---- | ----------- |
151
+ | `@content` | `String` | Content of the processed document. |
152
+ <%= common_template_vars %>
153
+ <% end %>
154
+
155
+ <% section "Creating your own document format", "HelloWorld" do %>
156
+ Here is a working example to help you digest all that you've learned so far about format specification files. A few things to notice in this example are:
157
+
158
+ * We define a `generate_name()` method in <%= xref "HelloWorld.spec" %> and make use of it in the <%= xref "HelloWorld.input" %>. This shows how to provide format-specific functionality to an input document.
159
+
160
+ * We define a `$style` variable in <%= xref "HelloWorld.input" %> and make use of it in <%= xref "HelloWorld.spec" %>. This shows how to pass parameters from an input document to your format specification file.
161
+
162
+ To run this example:
163
+
164
+ 1. Save the code shown in <%= xref "HelloWorld.spec" %> to a file named <tt>HelloWorld.spec</tt>
165
+
166
+ 2. Save the text shown in <%= xref "HelloWorld.input" %> to a file named <tt>HelloWorld.input</tt>
167
+
168
+ 3. Run this command:
169
+
170
+ <%= $program %> HelloWorld.spec HelloWorld.input > HelloWorld.output
171
+
172
+ 4. Examine the <tt>HelloWorld.output</tt> file to your satisfaction!
173
+
174
+ <% example "HelloWorld format specification file", "HelloWorld.spec" do %>
175
+ <code lang="rhtml"><%= verbatim File.read('doc/HelloWorld.spec') %></code>
176
+ <% end %>
177
+
178
+ <% example "Input document for HelloWorld format", "HelloWorld.input" do %>
179
+ <code lang="rhtml"><%= verbatim File.read('doc/HelloWorld.input') %></code>
180
+ <% end %>
181
+
182
+ <% example "Output of HelloWorld format", "HelloWorld.output" do %>
183
+ <%= `ruby bin/#{PROGRAM} -u doc/HelloWorld.spec doc/HelloWorld.input` %>
184
+ <% end %>
185
+ <% end %>
186
+ <% end %>
187
+ <% end %>
data/doc/usage.erb ADDED
@@ -0,0 +1,39 @@
1
+ <% chapter "Usage" do %>
2
+ <% section "Command-line interface" do %>
3
+ <pre><%= `ruby bin/erbook -h` %></pre>
4
+
5
+ The first command-line argument to erbook is either the name of a predefined format (FormatName) or the path to a <%= xref "SpecFile", "format specification file" %> (FormatFile).
6
+
7
+ Predefined formats are simply short-hand names of format specification files located in the <tt>fmt/</tt> subdirectory of the erbook installation directory (see <%= xref "Manifest" %>).
8
+
9
+ <% section "Saving the output to a file" do %>
10
+ Simply redirect the standard ouput stream (STDOUT) to a file like this:
11
+
12
+ erbook > YOUR_PATH_HERE
13
+
14
+ In the above example, **YOUR\_PATH\_HERE** is the path of the file in which the output should be saved.
15
+
16
+ <% important "Save XHTML output as <tt>.xhtml</tt>" do %>
17
+ When you use the XHTML format, ensure that the file extension of your saved output document is either <tt>.xhtml</tt> or <tt>.xml</tt>. Alternatively, ensure that your saved output document is served to web browsers under the <tt>application/xhtml+xml</tt> mime type.
18
+
19
+ Otherwise, most web browsers _will not display_ the icons and graphics embedded in the saved XHTML output document because they will treat it as HTML instead of as XML. See [this QuirksMode.org bug report](http://www.quirksmode.org/bugreports/archives/2005/02/custom_dtds_int_1.html) for details.
20
+ <% end %>
21
+ <% end %>
22
+ <% end %>
23
+
24
+ <% section "Including external documents", "include" do %>
25
+ The **include** directive allows you to insert the content of an arbitrary file at a certain place in the input document. It is written like this:
26
+
27
+ <%%# include YOUR_PATH_HERE #%>
28
+
29
+ In the above example, **YOUR\_PATH\_HERE** is the path of the file whose content you wish to insert into the input document.
30
+
31
+ You can divide a large document into separate files for easier editing and stitch them together, dynamically, into a single document using the **include** directive.
32
+ <% end %>
33
+
34
+ <% section "Unindenting nodes hierarchically" do %>
35
+ When writing erbook documents, I prefer to indent the content of nodes according to their depth because my [text editor of choice](http://jedit.org) automatically folds blocks of text based on indentation.
36
+
37
+ If you also prefer to write documents in this way, be sure to pass the <tt>--unindent</tt> option to **erbook** so that the indentation will not affect the resulting output.
38
+ <% end %>
39
+ <% end %>
data/fmt/xhtml.yaml CHANGED
@@ -41,40 +41,40 @@ code: |
41
41
  module ERBook
42
42
  class Template
43
43
  # Protects the given content from the text-to-XHTML conversion process.
44
- def verbatim aContent
45
- ERB::Util.html_escape aContent
44
+ def verbatim content
45
+ ERB::Util.html_escape content
46
46
  end
47
47
 
48
48
  # Returns XHTML for a hyperlink to the given
49
49
  # URL of the given label and mouse-hover title.
50
- def hyperlink aUrl, aLabel = aUrl, aTitle = nil
51
- %{<a href="#{aUrl}"#{%{ title="#{aTitle}"} if aTitle}>#{aLabel}</a>}
50
+ def hyperlink url, label = url, title = nil
51
+ %{<a href="#{url}"#{%{ title="#{title}"} if title}>#{label}</a>}
52
52
  end
53
53
 
54
54
  # Returns an <img/> tag that embeds the given image file.
55
55
  #
56
- # aPath:: path to the image file
57
- # aFormat:: format of the image file (e.g. PNG, JPEG, GIF, etc.)
58
- # aAtts:: additional attributes for the <img> tag
56
+ # path:: path to the image file
57
+ # format:: format of the image file (e.g. PNG, JPEG, GIF, etc.)
58
+ # atts:: additional attributes for the <img> tag
59
59
  #
60
- def embed_image_file aPath, aFormat = aPath[/\w+/], aAtts = {}
61
- data = ERBook.base_64_encode File.read(aPath)
62
- embed_image_data data, aFormat, aAtts
60
+ def embed_image_file path, format = path[/\w+/], atts = {}
61
+ data = ERBook.base_64_encode File.read(path)
62
+ embed_image_data data, format, atts
63
63
  end
64
64
 
65
65
  # Returns an <img/> tag that embeds the given raw image data.
66
66
  #
67
- # aData:: raw image data
68
- # aFormat:: format of the image file (e.g. PNG, JPEG, GIF, etc.)
69
- # aAtts:: additional attributes for the <img> tag
67
+ # data:: raw image data
68
+ # format:: format of the image file (e.g. PNG, JPEG, GIF, etc.)
69
+ # atts:: additional attributes for the <img> tag
70
70
  #
71
- def embed_image_data aData, aFormat, aAtts = {}
72
- aAtts[:src] = ERBook.base_64_embed_image_data(aData, aFormat)
73
- "<img#{aAtts.to_xml_atts}/>"
71
+ def embed_image_data data, format, atts = {}
72
+ atts[:src] = ERBook.base_64_embed_image_data(data, format)
73
+ "<img#{atts.to_xml_atts}/>"
74
74
  end
75
75
  end
76
76
 
77
- class Node
77
+ class Document::Node
78
78
  # Returns the user-defined title for this node's content.
79
79
  def title
80
80
  @title ||= args[0]
@@ -85,7 +85,6 @@ code: |
85
85
  @id ||= args[1]
86
86
  end
87
87
 
88
-
89
88
  ##
90
89
  # utility methods
91
90
  #
@@ -94,11 +93,6 @@ code: |
94
93
  type.to_s.capitalize
95
94
  end
96
95
 
97
- def type_label_here_link #:nodoc:
98
- s = type_label
99
- here_link s, s
100
- end
101
-
102
96
  # Returns the title of this node as XHTML.
103
97
  def title_xhtml
104
98
  title.to_s.to_inline_xhtml
@@ -115,19 +109,19 @@ code: |
115
109
  end
116
110
 
117
111
  # Returns a hyperlink to this node containing its title.
118
- def title_link aTitle = nil
119
- here_link here_frag, aTitle || title_xhtml
112
+ def title_link title = nil
113
+ title || title_xhtml
120
114
  end
121
115
 
122
116
  # Returns a hyperlink to this node
123
117
  # containing its LaTeX-style index number.
124
118
  def index_link
125
- list_link here_frag, list_frag, index
119
+ index
126
120
  end
127
121
 
128
122
  # Returns a hyperlink to this node containing its occurrence number.
129
123
  def number_link
130
- list_link here_frag, list_frag, [type_label, number].compact.join(' ')
124
+ [type_label, number].compact.join(' ')
131
125
  end
132
126
 
133
127
  # Returns a hyperlink to this node containing
@@ -142,6 +136,65 @@ code: |
142
136
  "#{index_link}&nbsp;&nbsp;#{title_link}"
143
137
  end
144
138
 
139
+ # Returns a navigation menu relative to this node.
140
+ def navigation
141
+ self.class.navigation(
142
+ here_frag,
143
+ (list_frag if defn['toc'] || defn['lof']),
144
+ (prev_node.here_frag if prev_node),
145
+ (next_node.here_frag if next_node)
146
+ )
147
+ end
148
+
149
+ LIST_SIGN = '&equiv;' # identical to
150
+ HERE_SIGN = '&#x25CE;' # bullseye
151
+ PREV_SIGN = '&#x25B3;' # white up-pointing triangle
152
+ NEXT_SIGN = '&#x25BD;' # white down-pointing triangle
153
+
154
+ # Calculates a local navigation menu containing links
155
+ # to the given URI fragments (which can be nil).
156
+ def self.navigation here_frag, list_frag, prev_frag, next_frag
157
+ list_link = list_frag ? %{<a title="Reverse jump to listing" href="##{list_frag}">#{LIST_SIGN}</a>} : LIST_SIGN
158
+
159
+ here_link = here_frag ? %{<a title="Jump to this segment" href="##{here_frag}">#{HERE_SIGN}</a>} : HERE_SIGN
160
+
161
+ prev_link = prev_frag ? %{<a title="Jump to previous segment" href="##{prev_frag}">#{PREV_SIGN}</a>} : PREV_SIGN
162
+
163
+ next_link = next_frag ? %{<a title="Jump to next segment" href="##{next_frag}">#{NEXT_SIGN}</a>} : NEXT_SIGN
164
+
165
+ %{<a name="#{here_frag}"/><div class="nav" id="#{here_frag}">#{list_link}#{prev_link}#{next_link}#{here_link}</div>}
166
+ end
167
+
168
+ # Returns a hyperlink to this node.
169
+ #
170
+ # @param [String] label
171
+ # Optional label (may contain XHTML) for the hyperlink.
172
+ #
173
+ # If not specified, the title and designation of
174
+ # this node will be used as the label instead.
175
+ #
176
+ def xref_link label = nil
177
+ prefix = [type_label, index || number].compact.join(' ')
178
+
179
+ title_text =
180
+ if type == 'reference'
181
+ prefix
182
+ else
183
+ [prefix, title].compact.join('. ')
184
+ end
185
+
186
+ title_xhtml =
187
+ if label
188
+ label
189
+ else
190
+ title_text
191
+ end.to_s.to_inline_xhtml
192
+
193
+ %{<a class="xref" href="##{here_frag}"#{
194
+ %( title="#{ERB::Util.h title_text}") if label
195
+ }>#{title_xhtml}</a>}
196
+ end
197
+
145
198
 
146
199
  ##
147
200
  # URI fragments
@@ -172,37 +225,28 @@ code: |
172
225
  def list_frag #:nodoc:
173
226
  @list_frag ||= "rev:#{here_frag}"
174
227
  end
175
-
176
-
177
- private
178
-
179
- def here_link aHereFrag, aLabel #:nodoc:
180
- %{<a class="here" title="Permanent link to this section" href="##{aHereFrag}">#{aLabel}</a>}
181
- end
182
-
183
- def list_link aHereFrag, aListFrag, aLabel #:nodoc:
184
- %{<a class="list" title="Return to table of contents" id="#{aHereFrag}" href="##{aListFrag}">#{aLabel}</a>}
185
- end
186
228
  end
187
229
 
188
230
  # Encodes the given input in base64 format.
189
- def ERBook.base_64_encode aInput #:nodoc:
190
- [aInput].pack('m')
231
+ def ERBook.base_64_encode input #:nodoc:
232
+ [input].pack('m')
191
233
  end
192
234
 
193
235
  # Returns a string denoting embedded, base64 encoded data.
194
- def ERBook.base_64_embed aData, aFormat #:nodoc:
195
- "data:#{aFormat.to_s.downcase};base64,#{aData.tr("\n", '')}"
236
+ def ERBook.base_64_embed data, format #:nodoc:
237
+ "data:#{format.to_s.downcase};base64,#{data.tr("\n", '')}"
196
238
  end
197
239
 
198
240
  # Returns a string denoting embedded, base64 encoded image data.
199
- # aFormat:: format of the image data (e.g. PNG, JPEG, GIF, etc.)
200
- def ERBook.base_64_embed_image_data aData, aFormat #:nodoc:
201
- base_64_embed aData, "image/#{aFormat}"
241
+ #
242
+ # format:: format of the image data (e.g. PNG, JPEG, GIF, etc.)
243
+ #
244
+ def ERBook.base_64_embed_image_data data, format #:nodoc:
245
+ base_64_embed data, "image/#{format}"
202
246
  end
203
247
 
204
248
  ##
205
- # load admonition icons
249
+ # admonition icons
206
250
  #
207
251
 
208
252
  ICONS_DIR = File.join(ERBook::FORMATS_DIR, 'xhtml.icons')
@@ -234,11 +278,11 @@ code: |
234
278
 
235
279
  # Returns an <img/> tag that renders the image
236
280
  # data embedded as an ENTITY in the html DOCTYPE.
237
- def to_xhtml aAtts = {}
238
- aAtts[:alt] ||= name
239
- aAtts[:src] = entity_xml
240
- aAtts[:class] = :icon
241
- "<img#{aAtts.to_xml_atts}/>"
281
+ def to_xhtml atts = {}
282
+ atts[:alt] ||= name
283
+ atts[:src] = entity_xml
284
+ atts[:class] = :icon
285
+ "<img#{atts.to_xml_atts}/>"
242
286
  end
243
287
  end
244
288
 
@@ -259,249 +303,253 @@ code: |
259
303
 
260
304
 
261
305
  nodes:
262
- ##
263
- # Structure
264
- #
265
-
266
- header: &header
267
- toc: false
268
- lof: false
269
- index: false
270
- number: false
271
- silent: true
272
- output: <%= @node.content_xhtml %>
273
-
274
- header_outside_above: &header_insert
275
- toc: false
276
- lof: false
277
- index: false
278
- number: false
279
- silent: true
280
- output: <div class="<%= @node.type %>"><%= @node.content_xhtml %></div>
281
-
282
- header_inside_above: *header_insert
283
- header_inside_below: *header_insert
284
- header_outside_below: *header_insert
285
-
286
- footer: *header
287
- footer_outside_above: *header_insert
288
- footer_inside_above: *header_insert
289
- footer_inside_below: *header_insert
290
- footer_outside_below: *header_insert
291
-
292
- abstract:
293
- toc: false
294
- lof: false
295
- index: false
296
- number: false
297
- silent: true
298
- output: |
299
- <div id="<%= @node.type_label %>">
300
- <h1 class="title"><%= @node.type_label_here_link %></h1>
301
- <%= @node.content_xhtml_div %>
302
- </div>
306
+ # object model
307
+ node:
308
+ toc: false
309
+ lof: false
310
+ depth: false
311
+ index: false
312
+ number: false
313
+ silent: false
314
+ inline: true
315
+ output: <%= @node.content_xhtml %>
303
316
 
317
+ # Structure
318
+ header: &header
319
+ toc: false
320
+ lof: false
321
+ depth: false
322
+ index: false
323
+ number: false
324
+ silent: true
325
+ inline: true
326
+ output: <%= @node.content_xhtml %>
327
+
328
+ header_outside_above: &header_insert
329
+ toc: false
330
+ lof: false
331
+ depth: false
332
+ index: false
333
+ number: false
334
+ silent: true
335
+ inline: true
336
+ output: <div class="<%= @node.type %>"><%= @node.content_xhtml %></div>
337
+
338
+ header_inside_above: *header_insert
339
+ header_inside_below: *header_insert
340
+ header_outside_below: *header_insert
341
+
342
+ footer: *header
343
+ footer_outside_above: *header_insert
344
+ footer_inside_above: *header_insert
345
+ footer_inside_below: *header_insert
346
+ footer_outside_below: *header_insert
347
+
348
+ abstract:
349
+ toc: false
350
+ lof: false
351
+ depth: false
352
+ index: false
353
+ number: false
354
+ silent: true
355
+ output: |
356
+ <div id="<%= @node.type_label %>">
357
+ <%= @node.navigation %>
358
+ <h1 class="title"><%= @node.type_label %></h1>
359
+ <%= @node.content_xhtml_div %>
360
+ </div>
304
361
 
305
- ##
306
362
  # Organization
307
- #
308
-
309
- part: &latex
310
- toc: true
311
- lof: false
312
- index: true
313
- number: true
314
- output: |
315
- <div class="<%= @node.type %>">
316
- <h1 class="title">
317
- <%= @node.type_label %>&nbsp;<%= @node.index_link %>
318
- <br/>
319
- <big><%= @node.title_link %></big>
320
- </h1>
321
- <%= @node.content_xhtml_div %>
322
- </div>
323
-
324
- chapter: *latex
325
-
326
- section:
327
- toc: true
328
- lof: false
329
- index: true
330
- number: true
331
- output: |
332
- <% depth = [6, @node.depth + 1].min %>
333
- <div class="<%= @node.type %>">
334
- <h<%= depth %> class="title">
335
- <%= @node.index_and_title_link %>
336
- </h<%= depth %>>
337
- <%= @node.content_xhtml_div %>
338
- </div>
363
+ part: &latex
364
+ toc: true
365
+ lof: false
366
+ depth: true
367
+ index: true
368
+ number: true
369
+ silent: false
370
+ output: |
371
+ <div class="<%= @node.type %>">
372
+ <%= @node.navigation %>
373
+ <h1 class="title">
374
+ <%= @node.type_label %>&nbsp;<%= @node.index_link %>
375
+ <br/>
376
+ <big><%= @node.title_link %></big>
377
+ </h1>
378
+ <%= @node.content_xhtml_div %>
379
+ </div>
339
380
 
340
- paragraph:
341
- toc: false
342
- lof: false
343
- index: false
344
- number: false
345
- output: |
346
- <div class="<%= @node.type %>">
347
- <p class="title"><%= @node.title_link %></p>
348
- <%= @node.content_xhtml_div %>
349
- </div>
381
+ chapter: *latex
382
+
383
+ section:
384
+ toc: true
385
+ lof: false
386
+ depth: true
387
+ index: true
388
+ number: true
389
+ silent: false
390
+ output: |
391
+ <% depth = [6, @node.depth + 1].min %>
392
+ <div class="<%= @node.type %>">
393
+ <%= @node.navigation %>
394
+ <h<%= depth %> class="title">
395
+ <%= @node.index_and_title_link %>
396
+ </h<%= depth %>>
397
+ <%= @node.content_xhtml_div %>
398
+ </div>
350
399
 
400
+ paragraph:
401
+ toc: true
402
+ lof: false
403
+ depth: false
404
+ index: false
405
+ number: false
406
+ silent: false
407
+ output: |
408
+ <div class="<%= @node.type %>">
409
+ <%= @node.navigation %>
410
+ <p class="title"><%= @node.title_link %></p>
411
+ <%= @node.content_xhtml_div %>
412
+ </div>
351
413
 
352
- ##
353
414
  # Admonitions
354
- #
355
-
356
- tip: &admonition
357
- toc: false
358
- lof: true
359
- index: false
360
- number: true
361
- output: |
362
- <div class="<%= @node.type %>">
363
- <p class="title"><%= @node.number_and_title_link %></p>
364
- <div class="content"><%= ICON_BY_NAME[@node.type].to_xhtml %><%= @node.content_xhtml %></div>
365
- </div>
366
-
367
- note: *admonition
368
- caution: *admonition
369
- warning: *admonition
370
- important: *admonition
415
+ tip: &admonition
416
+ toc: false
417
+ lof: true
418
+ depth: true
419
+ index: false
420
+ number: true
421
+ silent: false
422
+ output: |
423
+ <div class="<%= @node.type %>">
424
+ <%= @node.navigation %>
425
+ <p class="title"><%= @node.number_and_title_link %></p>
426
+ <div class="content">
427
+ <%= ICON_BY_NAME[@node.type].to_xhtml %>
428
+ <%= @node.content_xhtml %>
429
+ </div>
430
+ </div>
371
431
 
432
+ note: *admonition
433
+ caution: *admonition
434
+ warning: *admonition
435
+ important: *admonition
372
436
 
373
- ##
374
437
  # Auxilary materials (formal blocks)
375
438
  # see http://www.sagehill.net/docbookxsl/FormalTitles.html
376
- #
377
-
378
- figure: &formal
379
- toc: false
380
- lof: true
381
- index: false
382
- number: true
383
- output: |
384
- <div class="<%= @node.type %>">
385
- <p class="title"><%= @node.number_and_title_link %></p>
386
- <%= @node.content_xhtml_div %>
387
- </div>
388
-
389
- table: *formal
390
- example: *formal
391
- equation: *formal
392
- procedure: *formal
439
+ figure: &formal
440
+ toc: false
441
+ lof: true
442
+ depth: true
443
+ index: false
444
+ number: true
445
+ silent: false
446
+ output: |
447
+ <div class="<%= @node.type %>">
448
+ <%= @node.navigation %>
449
+ <p class="title"><%= @node.number_and_title_link %></p>
450
+ <%= @node.content_xhtml_div %>
451
+ </div>
393
452
 
453
+ table: *formal
454
+ example: *formal
455
+ equation: *formal
456
+ procedure: *formal
394
457
 
395
- ##
396
458
  # cross-references
397
- #
398
-
399
- xref:
400
- toc: false
401
- lof: false
402
- index: false
403
- number: false
404
- output: |
405
- <%=
406
- scope = @nodes.select {|n| n.content}
407
-
408
- target = scope.find {|n| n.id == @node.args[0]} || # id has 1st priority
409
- scope.find {|n| n.title == @node.args[0]}
410
-
411
- if target
412
- prefix = "#{target.type_label} #{target.index || target.number}"
413
-
414
- title_text =
415
- if target.type == 'reference'
416
- prefix
417
- else
418
- [prefix, target.title].compact.join('. ')
419
- end
420
-
421
- title_auto = @node.args.length < 2
422
-
423
- title_xhtml =
424
- if title_auto
425
- title_text
426
- else
427
- @node.args[1].to_s
428
- end.to_inline_xhtml
429
-
430
- %{<a class="#{@node.type}" href="##{target.here_frag}"#{
431
- %( title="#{title_text}") unless title_auto
432
- }>#{title_xhtml}</a>}
433
- else
434
- raise ArgumentError, "invalid cross-reference to #{@node.title.inspect}", @node.trace
435
- end
436
- %>
459
+ xref:
460
+ toc: false
461
+ lof: false
462
+ depth: true
463
+ index: false
464
+ number: false
465
+ silent: false
466
+ inline: true
467
+ output: |
468
+ <%=
469
+ query, label = @node.args
470
+
471
+ scope = @nodes.select {|n| n.content }
472
+ target = scope.find {|n| n.id == query } || # id has 1st priority
473
+ scope.find {|n| n.title == query }
437
474
 
475
+ if target
476
+ target.xref_link label
477
+ else
478
+ raise ArgumentError, "invalid cross-reference to #{@node.title.inspect}", @node.trace
479
+ end
480
+ %>
438
481
 
439
- ##
440
482
  # Bibliography
441
- #
442
-
443
- reference:
444
- toc: false
445
- lof: false
446
- index: false
447
- number: true
448
- silent: true
449
-
450
- cite:
451
- toc: false
452
- lof: false
453
- index: false
454
- number: false
455
- output: |
456
- <%=
457
- target = @types['reference'].find {|n| n.title == @node.args[0]}
458
-
459
- if target
460
- '<sup>[%s]</sup>' % [
461
-
462
- '<a class="%s" href="#%s">%s</a>' % [
463
- @node.type,
464
- target.here_frag,
465
- target.number
466
- ],
467
-
468
- *@node.args[1..-1]
469
-
470
- ].join(', ')
471
- else
472
- raise ArgumentError, "invalid citation for #{@node.title.inspect}", @node.trace
473
- end
474
- %>
483
+ reference:
484
+ toc: false
485
+ lof: false
486
+ depth: false
487
+ index: false
488
+ number: true
489
+ silent: true
490
+ inline: true
491
+
492
+ cite:
493
+ toc: false
494
+ lof: false
495
+ depth: false
496
+ index: false
497
+ number: false
498
+ silent: false
499
+ inline: true
500
+ output: |
501
+ <%=
502
+ target = @nodes_by_type['reference'].find {|n| n.title == @node.args[0]}
503
+
504
+ if target
505
+ '<sup>[%s]</sup>' % [
506
+
507
+ '<a class="%s" href="#%s">%s</a>' % [
508
+ @node.type,
509
+ target.here_frag,
510
+ target.number
511
+ ],
512
+
513
+ *@node.args[1..-1]
514
+
515
+ ].join(', ')
516
+ else
517
+ raise ArgumentError, "invalid citation for #{@node.title.inspect}", @node.trace
518
+ end
519
+ %>
475
520
 
476
521
  output: |
477
522
  <%
478
523
  # set default parameter values
479
- $title = '$title' unless defined? $title
480
- $authors = {'$authors' => nil} unless defined? $authors
481
- $date = Time.now.strftime("%d %B %Y") unless defined? $date
524
+ $title = '$title' unless defined? $title
525
+ $subtitle = '$subtitle' unless defined? $subtitle
526
+ $authors = {'$authors' => nil} unless defined? $authors
527
+ $date = Time.now.strftime("%d %B %Y") unless defined? $date
482
528
 
483
- abstract = @types['abstract'].first
529
+ abstract = @nodes_by_type['abstract'].first
484
530
 
485
- references = @types['reference']
531
+ references = @nodes_by_type['reference']
486
532
  if references.empty?
487
533
  references = nil
488
534
  end
489
535
 
490
536
  # compute table of contents
491
537
  toc_builder = lambda do |n|
492
- if @spec['nodes'][n.type]['toc']
538
+ nested = n.children.inject('') {|s,c| s << toc_builder[c] }
539
+ nested = nil if nested.empty?
540
+
541
+ if n.defn['toc']
493
542
  entry = '%s<a id="%s" href="#%s">%s</a>' % [
494
543
  (n.index.to_s + '&nbsp;&nbsp;' if n.index),
495
544
  n.list_frag,
496
545
  n.here_frag,
497
546
  n.title.to_s.to_inline_xhtml
498
547
  ]
499
- nested = n.children.inject('') {|s,c| s << toc_builder[c] }
500
548
 
501
- %{<li>#{entry}#{ "<ul>#{nested}</ul>" unless nested.empty? }</li>}
549
+ %{<li>#{entry}#{"<ul>#{nested}</ul>" if nested}</li>}
502
550
  else
503
- ''
504
- end
551
+ nested
552
+ end.to_s
505
553
  end
506
554
 
507
555
  toc = @roots.inject('') {|s,n| s << toc_builder[n] }
@@ -509,16 +557,16 @@ output: |
509
557
  # compute list of figures
510
558
  lof_enums = {} # type => nodes
511
559
 
512
- @spec['nodes'].each_pair do |name, info|
560
+ @format['nodes'].each_pair do |name, info|
513
561
  if info['lof']
514
- nodes = @types[name]
562
+ nodes = @nodes_by_type[name]
515
563
  lof_enums[name] = nodes unless nodes.empty?
516
564
  end
517
565
  end
518
566
 
519
567
  lof_sections = []
520
568
 
521
- lof = lof_enums.sort.map do |(type, nodes)|
569
+ lof = lof_enums.sort.map do |type, nodes|
522
570
  nested = nodes.map do |n|
523
571
  %{<li><a id="#{n.list_frag}" href="##{n.here_frag}">#{n.title.to_s.to_inline_xhtml}</a></li>}
524
572
  end
@@ -526,7 +574,7 @@ output: |
526
574
  label = type.capitalize << 's' # TODO: pluralize this properly
527
575
  lof_sections << label
528
576
 
529
- %{<h2 id="#{label}" class="title"><a class="here" href="##{label}">#{label}</a></h2> <ol>#{nested}</ol>}
577
+ %{#{ERBook::Document::Node.navigation label, "rev:#{label}", nil, nil}<h2 class="title">#{label}</h2> <ol>#{nested}</ol>}
530
578
  end
531
579
  %>
532
580
  <?xml version="1.0" encoding="utf-8"?>
@@ -539,10 +587,19 @@ output: |
539
587
  <html xmlns="http://www.w3.org/1999/xhtml">
540
588
  <head>
541
589
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
542
- <meta name="date" content="<%= $date %>"/>
543
- <meta name="author" content="<%= $authors.keys.join(', ') %>"/>
544
590
  <meta name="generator" content="<%= ERBook::DISPLAY %>"/>
545
- <title><%= $title.to_s.to_inline_xhtml %></title>
591
+
592
+ <% if $title %>
593
+ <title><%= $title.to_s.to_inline_xhtml %></title>
594
+ <% end %>
595
+
596
+ <% if $authors %>
597
+ <meta name="author" content="<%= $authors.keys.join(', ') %>"/>
598
+ <% end %>
599
+
600
+ <% if $date %>
601
+ <meta name="date" content="<%= $date %>"/>
602
+ <% end %>
546
603
 
547
604
  <% if $feeds %>
548
605
  <% $feeds.each_pair do |url, fmt| %>
@@ -550,18 +607,19 @@ output: |
550
607
  <% end %>
551
608
  <% end %>
552
609
 
553
- <% @spec['styles'].each_pair do |media, style| %>
554
- <style type="text/css" media="<%= media %>">
555
- <![CDATA[<%= style %>]]>
556
- </style>
610
+ <% @format['styles'].each do |style| %>
611
+ <% style.each_pair do |media, code| %>
612
+ <style type="text/css" media="<%= media %>">
613
+ <![CDATA[<%= ERB.new(code).result(binding) %>]]>
614
+ </style>
615
+ <% end %>
557
616
  <% end %>
558
617
 
559
618
  <style type="text/css" media="screen">
560
619
  <![CDATA[
561
620
  /* decorate external hyperlinks with a visual indicator */
562
- a:not([href^="#"])
621
+ a[href]:not([href^="#"])
563
622
  {
564
- color : #3366BB;
565
623
  background : <%= ICON_BY_NAME['link'].data_css %>;
566
624
  background-position : center right;
567
625
  background-repeat : no-repeat;
@@ -581,6 +639,7 @@ output: |
581
639
  </style>
582
640
  </head>
583
641
  <body>
642
+ <div id="body">
584
643
  <%
585
644
  # menu of links to link sections
586
645
  nav = [
@@ -592,41 +651,54 @@ output: |
592
651
 
593
652
  if nav.length > 1
594
653
  %>
595
- <div id="nav">
596
- <%=
597
- nav.map do |section|
598
- %{<a href="##{section}">#{section}</a>}
599
- end.join(' &middot; ')
600
- %>
601
- </div>
654
+ <ul id="nav" class="nav">
655
+ <% nav.each do |section| %>
656
+ <li><a id="rev:<%= section %>" href="#<%= section %>"><%= section %></a></li>
657
+ <% end %>
658
+ </ul>
602
659
  <% end %>
603
660
 
604
661
  <br style="display: none"/>
605
662
  <hr style="display: none"/>
606
663
  <br style="display: none"/>
607
664
 
608
- <%= node = @types['header_outside_above'].first and node.output %>
665
+ <%= node = @nodes_by_type['header_outside_above'].first and node.output %>
609
666
  <div id="header">
610
- <%= node = @types['header_inside_above'].first and node.output %>
611
- <% if header = @types['header'].first %>
667
+ <%= node = @nodes_by_type['header_inside_above'].first and node.output %>
668
+ <% if header = @nodes_by_type['header'].first %>
612
669
  <%= header.output %>
613
670
  <% else %>
614
- <%= $logo if defined? $logo %>
615
- <h1 class="title"><%= $title.to_s.to_inline_xhtml %></h1>
616
- <h2 class="authors"><%=
617
- $authors.map do |(name, url)|
618
- if url
619
- %{<a href="#{url}">#{name}</a>}
620
- else
621
- name
622
- end
623
- end.join(', ')
624
- %></h2>
625
- <h3 class="date"><%= $date %></h3>
671
+ <% if $logo %>
672
+ <div class="logo"><%= $logo %></div>
673
+ <% end %>
674
+
675
+ <% if $title %>
676
+ <h1 class="title"><%= $title.to_s.to_inline_xhtml %></h1>
677
+ <% end %>
678
+
679
+ <% if $subtitle %>
680
+ <h2 class="subtitle"><%= $subtitle.to_s.to_inline_xhtml %></h2>
681
+ <% end %>
682
+
683
+ <% if $authors %>
684
+ <h3 class="authors"><%=
685
+ $authors.map do |name, url|
686
+ if url
687
+ %{<a href="#{url}">#{name}</a>}
688
+ else
689
+ name
690
+ end
691
+ end.join(', ')
692
+ %></h3>
693
+ <% end %>
694
+
695
+ <% if $date %>
696
+ <h3 class="date"><%= $date %></h3>
697
+ <% end %>
626
698
  <% end %>
627
- <%= node = @types['header_inside_below'].first and node.output %>
699
+ <%= node = @nodes_by_type['header_inside_below'].first and node.output %>
628
700
  </div>
629
- <%= node = @types['header_outside_below'].first and node.output %>
701
+ <%= node = @nodes_by_type['header_outside_below'].first and node.output %>
630
702
 
631
703
  <%= abstract.output if abstract %>
632
704
 
@@ -636,12 +708,13 @@ output: |
636
708
 
637
709
  <% unless toc.empty? %>
638
710
  <div id="toc">
639
- <h1 class="title" id="Contents"><a class="here" href="#Contents">Contents</a></h1>
711
+ <%= ERBook::Document::Node.navigation "Contents", "rev:Contents", nil, nil %>
712
+ <h1 class="title">Contents</h1>
640
713
  <ul>
641
714
  <%= toc %>
642
715
 
643
716
  <% if references %>
644
- <li><a href="#References">References</a></li>
717
+ <li><a id="rev:References" href="#References">References</a></li>
645
718
  <% end %>
646
719
  </ul>
647
720
  </div>
@@ -659,7 +732,8 @@ output: |
659
732
 
660
733
  <% if references %>
661
734
  <div id="bib">
662
- <h1 class="title" id="References"><a class="here" href="#References">References</a></h1>
735
+ <%= ERBook::Document::Node.navigation "References", "rev:References", nil, nil %>
736
+ <h1 class="title" >References</h1>
663
737
  <ol>
664
738
  <% references.each do |n| %>
665
739
  <li id="<%= n.here_frag %>"><%= n.content_xhtml %></li>
@@ -672,10 +746,10 @@ output: |
672
746
  <hr style="display: none"/>
673
747
  <br style="display: none"/>
674
748
 
675
- <%= node = @types['footer_outside_above'].first and node.output %>
749
+ <%= node = @nodes_by_type['footer_outside_above'].first and node.output %>
676
750
  <div id="footer">
677
- <%= node = @types['footer_inside_above'].first and node.output %>
678
- <% if footer = @types['footer'].first %>
751
+ <%= node = @nodes_by_type['footer_inside_above'].first and node.output %>
752
+ <% if footer = @nodes_by_type['footer'].first %>
679
753
  <%= footer.content.to_s.to_xhtml %>
680
754
  <% else %>
681
755
  Generated by <a href="<%= ERBook::WEBSITE %>"><%= ERBook::DISPLAY %></a> on <%= Time.now %>.
@@ -702,24 +776,31 @@ output: |
702
776
  The icons shown above are &copy; 2007 <a href="https://www.ohloh.net/projects/mediawiki/contributors">MediaWiki contributors</a>. They are part of the <a href="http://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a> software, which is distributed under the <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, version 2</a>.
703
777
  </p>
704
778
  </div>
705
- <%= node = @types['footer_inside_below'].first and node.output %>
779
+ <%= node = @nodes_by_type['footer_inside_below'].first and node.output %>
706
780
  </div>
707
- <%= node = @types['footer_outside_below'].first and node.output %>
781
+ <%= node = @nodes_by_type['footer_outside_below'].first and node.output %>
782
+ </div>
708
783
  </body>
709
784
  </html>
710
785
 
786
+ # definition of font families for use in the CSS styles
787
+ fonts:
788
+ serif: Constantia, "Book Antiqua", "URW Bookman L", serif
789
+ sans-serif: Calibri, Verdana, sans-serif
790
+ monospace: Monaco, Consolas, "Lucida Console", monospace
791
+
711
792
  styles:
712
- all: |
713
- body
714
- {
715
- color : #000000;
716
- background-color : #FFFFFF;
717
- line-height : 1.5em;
718
- font-family : Calibri, Verdana, sans-serif;
719
- }
793
+ - all: |
794
+ /* general */
795
+ body
796
+ {
797
+ color : #000000;
798
+ background-color : #FFFFFF;
799
+ line-height : 1.5em;
800
+ font-family : <%= @format['fonts']['sans-serif'] %>;
801
+ }
720
802
 
721
803
  /* emphasis */
722
-
723
804
  blockquote
724
805
  {
725
806
  color : #333;
@@ -728,6 +809,8 @@ styles:
728
809
 
729
810
  em
730
811
  {
812
+ font-family : <%= @format['fonts']['serif'] %>;
813
+ font-size : 105%;
731
814
  }
732
815
 
733
816
  hr
@@ -738,17 +821,15 @@ styles:
738
821
  }
739
822
 
740
823
  /* source code */
741
-
742
824
  tt,
743
825
  code,
744
826
  pre
745
827
  {
746
- font-family : Monaco, Consolas, "Lucida Console", monospace;
828
+ font-family : <%= @format['fonts']['monospace'] %>;
747
829
  font-size : 100%; /* appears like "size: small" otherwise */
748
830
  }
749
831
 
750
832
  /* hyperlinks */
751
-
752
833
  a > img
753
834
  {
754
835
  border : none;
@@ -759,20 +840,7 @@ styles:
759
840
  _border : none; /* for IE6 */
760
841
  }
761
842
 
762
- /* lists */
763
-
764
- #content li:first-child
765
- {
766
- margin-top : 1em;
767
- }
768
-
769
- #content li
770
- {
771
- margin-bottom : 1em;
772
- }
773
-
774
843
  /* headings */
775
-
776
844
  h1,
777
845
  h2,
778
846
  h3,
@@ -782,7 +850,7 @@ styles:
782
850
  .title
783
851
  {
784
852
  font-weight : lighter;
785
- font-family : Constantia, "Book Antiqua", "URW Bookman L", serif;
853
+ font-family : <%= @format['fonts']['serif'] %>;
786
854
  }
787
855
 
788
856
  #lof h1,
@@ -837,7 +905,6 @@ styles:
837
905
  }
838
906
 
839
907
  /* tables */
840
-
841
908
  table
842
909
  {
843
910
  border-collapse : collapse; /* no spacing between cell borders */
@@ -851,7 +918,7 @@ styles:
851
918
  padding : 1em;
852
919
  border : 1px solid #bbb;
853
920
  vertical-align : top;
854
- background-color : inherit;
921
+ background-color : #FFFFFF;
855
922
  _background-color : #FFFFFF; /* for IE6 */
856
923
  }
857
924
 
@@ -861,18 +928,12 @@ styles:
861
928
  }
862
929
 
863
930
  /* document structure */
864
-
865
- #nav
866
- {
867
- text-align : center;
868
- margin-bottom : 4em;
869
- }
870
-
871
931
  #header
872
932
  {
873
933
  text-align : center;
874
934
  }
875
935
 
936
+ .logo,
876
937
  .header_outside_above,
877
938
  #header,
878
939
  .header_outside_below
@@ -945,7 +1006,6 @@ styles:
945
1006
  }
946
1007
 
947
1008
  /* document nodes */
948
-
949
1009
  .part > .title,
950
1010
  .chapter > .title
951
1011
  {
@@ -1014,6 +1074,20 @@ styles:
1014
1074
  margin : 3em;
1015
1075
  }
1016
1076
 
1077
+ .tip .nav,
1078
+ .note .nav,
1079
+ .caution .nav,
1080
+ .warning .nav,
1081
+ .important .nav,
1082
+ .figure .nav,
1083
+ .table .nav,
1084
+ .example .nav,
1085
+ .equation .nav,
1086
+ .procedure .nav
1087
+ {
1088
+ margin-left : -7.65em;
1089
+ }
1090
+
1017
1091
  .tip > .content,
1018
1092
  .note > .content,
1019
1093
  .caution > .content,
@@ -1069,16 +1143,30 @@ styles:
1069
1143
  _margin : auto; /* for IE6 */
1070
1144
  }
1071
1145
 
1072
- screen: |
1073
- body
1074
- {
1146
+ - screen: |
1147
+ /* general */
1148
+ body
1149
+ {
1150
+ margin : 0;
1151
+ padding : 0;
1152
+ padding-left : 10em; /* room for local navigation menus */
1153
+ padding-right : 10em; /* keep #body visually centered */
1154
+ background-color : #808080;
1155
+ }
1156
+
1157
+ /* the actual content of the <body> element */
1158
+ #body
1159
+ {
1075
1160
  margin : auto;
1076
- max-width : 36em;
1077
- padding : 0.5em;
1078
- }
1161
+ max-width : 38em;
1079
1162
 
1080
- /* source code */
1163
+ background-color : #FFFFFF;
1164
+ border-left : 0.35em solid #696969;
1165
+ border-right : 0.35em solid #696969;
1166
+ padding : 2em;
1167
+ }
1081
1168
 
1169
+ /* source code */
1082
1170
  tt
1083
1171
  {
1084
1172
  background-color : #F0F8FF;
@@ -1091,7 +1179,11 @@ styles:
1091
1179
  border : 1px solid #b1d827;
1092
1180
  background-color : #F5FFDF;
1093
1181
  padding : 1em;
1094
- overflow : auto;
1182
+
1183
+ /* fit container to content; no overflow! */
1184
+ display : inline-block;
1185
+ margin : 0;
1186
+ min-width : 92.5%;
1095
1187
  }
1096
1188
 
1097
1189
  /* output of the syntax coloring library */
@@ -1102,7 +1194,6 @@ styles:
1102
1194
  }
1103
1195
 
1104
1196
  /* hyperlinks */
1105
-
1106
1197
  a
1107
1198
  {
1108
1199
  text-decoration : none;
@@ -1115,39 +1206,77 @@ styles:
1115
1206
 
1116
1207
  a:link
1117
1208
  {
1118
- color : #002BB8;
1209
+ color : #0038E1; /* maximum saturation of RoyalBlue */
1119
1210
  }
1120
1211
 
1121
1212
  a:visited
1122
1213
  {
1123
- color : #5A3696;
1214
+ color : #800080;
1124
1215
  }
1125
1216
 
1126
- a.here,
1127
- a.list
1217
+ #toc a:target:after,
1218
+ #lof a:target:after,
1219
+ #nav a:target:after
1128
1220
  {
1129
- color : #000000;
1221
+ content : "★"; /* &#x2605; */
1222
+ color : #FF0000;
1223
+ font-size : x-large;
1224
+ padding-left : 0.125em;
1130
1225
  }
1131
1226
 
1132
- a:target,
1133
- a:target *,
1134
- *:target a.list
1227
+ /* document structure */
1228
+ /* mini navigation menu beside every block node */
1229
+ .nav
1135
1230
  {
1136
- background-color : #FF4500 !important;
1137
- color : #FFFFFF !important;
1231
+ width : 4em;
1232
+ float : left; /* detach from main content */
1233
+ margin-left : -6.075em;
1234
+
1235
+ font-size : 1.9em;
1236
+ letter-spacing : 0.25em;
1237
+ text-align : center;
1238
+
1239
+ color : #696969; /* same colors to hide non-links */
1240
+ background-color : #696969;
1241
+ padding : 0.5em;
1242
+ margin-top : -0.5em;
1138
1243
  }
1139
1244
 
1140
- a:target,
1141
- *:target a.list
1245
+ .nav:target,
1246
+ .nav:hover
1142
1247
  {
1143
- padding : 0.1em;
1144
- font-weight : bolder;
1248
+ color : #333; /* same colors to hide non-links */
1249
+ background-color : #333;
1250
+ }
1251
+
1252
+ .nav a:link,
1253
+ .nav a:visited
1254
+ {
1255
+ color : #D3D3D3;
1256
+ }
1257
+
1258
+ .nav a:hover,
1259
+ #nav a:target:after {
1260
+ color : #9ACD32;
1145
1261
  text-decoration : none;
1146
1262
  }
1147
1263
 
1148
- print: |
1149
- /* source code */
1264
+ /* global navigation menu at the top of the page */
1265
+ #nav
1266
+ {
1267
+ font-size : 1em;
1268
+ letter-spacing : 0;
1269
+ width : 8.5em;
1270
+ margin-left : -11.5em;
1271
+ }
1272
+
1273
+ #nav li
1274
+ {
1275
+ list-style-type : none;
1276
+ }
1150
1277
 
1278
+ - print: |
1279
+ /* source code */
1151
1280
  tt
1152
1281
  {
1153
1282
  font-weight : normal;
@@ -1159,7 +1288,6 @@ styles:
1159
1288
  }
1160
1289
 
1161
1290
  /* headings */
1162
-
1163
1291
  h1,
1164
1292
  h2,
1165
1293
  h3,
@@ -1172,7 +1300,6 @@ styles:
1172
1300
  }
1173
1301
 
1174
1302
  /* hyperlinks */
1175
-
1176
1303
  /* blend all hyperlinks with normal text */
1177
1304
  a:link,
1178
1305
  a:visited
@@ -1182,8 +1309,8 @@ styles:
1182
1309
  }
1183
1310
 
1184
1311
  /* emphasize external and cross-reference hyperlinks */
1185
- a:not([href^="#"]):link,
1186
- a:not([href^="#"]):visited,
1312
+ a[href]:not([href^="#"]):link,
1313
+ a[href]:not([href^="#"]):visited,
1187
1314
  a.xref[title]:link,
1188
1315
  a.xref[title]:visited
1189
1316
  {
@@ -1193,10 +1320,10 @@ styles:
1193
1320
  }
1194
1321
 
1195
1322
  /* show URL of destination for external hyperlinks */
1196
- a:not([href^="#"]):after
1323
+ a[href]:not([href^="#"]):after
1197
1324
  {
1198
1325
  content : " " attr(href);
1199
- font-family : Monaco, Consolas, "Lucida Console", monospace;
1326
+ font-family : <%= @format['fonts']['monospace'] %>;
1200
1327
  }
1201
1328
 
1202
1329
  /* show name of destination for cross-references */
@@ -1212,8 +1339,8 @@ styles:
1212
1339
  }
1213
1340
 
1214
1341
  /* document structure */
1215
-
1216
1342
  #nav,
1343
+ .nav,
1217
1344
  #lof
1218
1345
  {
1219
1346
  display : none;
@@ -1228,7 +1355,6 @@ styles:
1228
1355
  }
1229
1356
 
1230
1357
  /* document nodes */
1231
-
1232
1358
  .part > .title > big,
1233
1359
  .chapter > .title > big
1234
1360
  {
@@ -1240,4 +1366,3 @@ styles:
1240
1366
  {
1241
1367
  _padding-bottom : 0.5em; /* for IE6 */
1242
1368
  }
1243
-