erbook 9.2.0 → 9.2.1

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.
@@ -131,7 +131,9 @@ code: |
131
131
  # Returns a temporary data URI that will be replaced
132
132
  # with the actual data URI at runtime by javascript.
133
133
  #
134
- alias embed_uri object_id
134
+ def embed_uri
135
+ "cid:#{object_id}"
136
+ end
135
137
 
136
138
  ##
137
139
  # Returns an image tag that renders an embedded data URI.
@@ -921,12 +923,12 @@ output: |
921
923
 
922
924
  <p class="validations">
923
925
  <a href="http://validator.w3.org/check?uri=referer"><img
924
- src="http://www.w3.org/Icons/valid-xhtml10-blue"
926
+ src="<%= ICON_BY_NAME['valid_html'].embed_uri %>"
925
927
  alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
926
928
 
927
929
  <a href="http://jigsaw.w3.org/css-validator/check/referer?profile=css3"><img
928
- src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
929
- alt="Valid CSS!" height="31" width="88" /></a>
930
+ src="<%= ICON_BY_NAME['valid_css'].embed_uri %>"
931
+ alt="Valid CSS 3!" height="31" width="88" /></a>
930
932
  </p>
931
933
  </div>
932
934
  </div>
@@ -1220,7 +1222,7 @@ javascript: |
1220
1222
  var query = search_box.val().replace(/^\s+|\s+$/g, '');
1221
1223
 
1222
1224
  // ignore empty queries
1223
- if (!query.match(/\S/)) {
1225
+ if (search_box.is('.initial') || !query.match(/\S/)) {
1224
1226
  return;
1225
1227
  }
1226
1228
 
@@ -1692,6 +1694,10 @@ styles: # these are SASS templates
1692
1694
  padding-left: 1em
1693
1695
 
1694
1696
 
1697
+ #_references > ol > li
1698
+ margin-bottom: 1em
1699
+
1700
+
1695
1701
  #_footer
1696
1702
  padding-top: 1em
1697
1703
  text-align: center
@@ -20,3 +20,7 @@ nav_here: tango-icon-theme-0.8.90/32x32/status/software-update-available.png
20
20
  nav_prev: tango-icon-theme-0.8.90/32x32/actions/go-previous.png
21
21
  nav_next: tango-icon-theme-0.8.90/32x32/actions/go-next.png
22
22
  nav_list: tango-icon-theme-0.8.90/32x32/places/start-here.png
23
+
24
+ # W3C validator badges
25
+ valid_html: w3.org/valid-xhtml10.png
26
+ valid_css: w3.org/vcss.gif
@@ -0,0 +1,2 @@
1
+ valid-xhtml10.png : http://www.w3.org/Icons/valid-xhtml10
2
+ vcss.gif : http://jigsaw.w3.org/css-validator/images/vcss
@@ -9,8 +9,8 @@ require 'inochi'
9
9
 
10
10
  Inochi.init :ERBook,
11
11
  :program => 'erbook',
12
- :version => '9.2.0',
13
- :release => '2009-11-06',
12
+ :version => '9.2.1',
13
+ :release => '2009-11-18',
14
14
  :website => 'http://snk.tuxfamily.org/lib/erbook/',
15
15
  :tagline => 'Write books, manuals, and documents in eRuby',
16
16
  :require => {
@@ -40,204 +40,13 @@ module ERBook
40
40
  # If true, all node content is unindented hierarchically.
41
41
  #
42
42
  def initialize format_name, input_text, input_file, options = {}
43
- # process format specification
44
- @format_file = format_name.to_s
43
+ load_format format_name
45
44
 
46
- File.file? @format_file or
47
- @format_file = File.join(ERBook::FORMATS_DIR, @format_file + '.yaml')
45
+ @input_text = input_text
46
+ @input_file = input_file
47
+ @options = options
48
48
 
49
- begin
50
- @format = YAML.load_file(@format_file)
51
- @format[:file] = File.expand_path(@format_file)
52
- @format[:name] = File.basename(@format_file).sub(/\..*?$/, '')
53
-
54
- if @format.key? 'code'
55
- eval @format['code'].to_s, TOPLEVEL_BINDING, "#{@format_file}:code"
56
- end
57
-
58
- rescue Exception
59
- error "Could not load format specification file #{@format_file.inspect}"
60
- end
61
-
62
- @node_defs = @format['nodes']
63
-
64
- # process input document
65
- begin
66
- # create sandbox for input evaluation
67
- template = Template.new(input_file, input_text, options[:unindent])
68
- sandbox = template.sandbox
69
-
70
- @template_vars = {
71
- :@format => @format,
72
- :@roots => @roots = [], # root nodes of all trees
73
- :@nodes => @nodes = [], # all nodes in the forest
74
- :@nodes_by_type => @nodes_by_type = Hash.new {|h,k| h[k] = [] },
75
- :@stack => [], # stack for all nodes
76
- }.each_pair {|k,v| sandbox.instance_variable_set(k, v) }
77
-
78
- #:stopdoc:
79
-
80
- ##
81
- # Handles the method call from a node
82
- # placeholder in the input document.
83
- #
84
- def sandbox.__node_handler__ node_type, *node_args, &node_content
85
- node = Node.new(
86
- :type => node_type,
87
- :definition => @format['nodes'][node_type],
88
- :arguments => node_args,
89
- :backtrace => caller,
90
- :parent => @stack.last,
91
- :children => []
92
- )
93
-
94
- Array(node.definition['params']).each do |param|
95
- break if node_args.empty?
96
- node.__send__ "#{param}=", node_args.shift
97
- end
98
-
99
- @nodes << node
100
- @nodes_by_type[node.type] << node
101
-
102
- # calculate ordinal number for this node
103
- if node.ordinal_number?
104
- @count_by_type ||= Hash.new {|h,k| h[k] = 0 }
105
- node.ordinal_number = (@count_by_type[node.type] += 1)
106
- end
107
-
108
- # assign node family
109
- if parent = node.parent
110
- parent.children << node
111
- node.parent = parent
112
- node.depth = parent.depth
113
- node.depth += 1 if node.anchor?
114
-
115
- # calculate section number for this node
116
- if node.section_number?
117
- ancestor = @stack.reverse.find {|n| n.section_number }
118
- branches = parent.children.select {|n| n.section_number }
119
-
120
- node.section_number = [
121
- ancestor.section_number,
122
- branches.length + 1
123
- ].join('.')
124
- end
125
- else
126
- @roots << node
127
- node.parent = nil
128
- node.depth = 0
129
-
130
- # calculate section number for this node
131
- if node.section_number?
132
- branches = @roots.select {|n| n.section_number }
133
- node.section_number = (branches.length + 1).to_s
134
- end
135
- end
136
-
137
- # assign node content
138
- if block_given?
139
- @stack.push node
140
- node.content = __block_content__(node, &node_content)
141
- @stack.pop
142
- end
143
-
144
- @buffer << node
145
-
146
- nil
147
- end
148
-
149
- #:startdoc:
150
-
151
- @node_defs.each_key do |type|
152
- # XXX: using a string because define_method()
153
- # does not accept a block until Ruby 1.9
154
- file, line = __FILE__, __LINE__; eval %{
155
- def sandbox.#{type} *node_args, &node_content
156
- __node_handler__ #{type.inspect}, *node_args, &node_content
157
- end
158
- }, binding, file, line
159
- end
160
-
161
- # evaluate the input & build the document tree
162
- template.render
163
- @processed_document = template.buffer
164
-
165
- # chain block-level nodes together for local navigation
166
- block_nodes = @nodes.select {|n| n.chain? }
167
-
168
- require 'enumerator'
169
- block_nodes.each_cons(2) do |a, b|
170
- a.next_node = b
171
- b.prev_node = a
172
- end
173
-
174
- # calculate output for all nodes
175
- actual_output_by_node = {}
176
-
177
- visitor = lambda do |n|
178
- #
179
- # allow child nodes to calculate their actual
180
- # output and to set their identifier as Node#output
181
- #
182
- # we do this nodes first because this node's
183
- # content contains the child nodes' output
184
- #
185
- n.children.each {|c| visitor.call c }
186
-
187
- # calculate the output for this node
188
- actual_output = Template.new(
189
- "#{@format_file}:nodes:#{n.type}:output",
190
- n.definition['output'].to_s.chomp
191
- ).render_with(@template_vars.merge(:@node => n))
192
-
193
- # reveal child nodes' actual output in this node's actual output
194
- n.children.each do |c|
195
- if c.silent?
196
- # this child's output is not meant to be revealed at this time
197
- next
198
-
199
- elsif c.inline?
200
- actual_output[c.output] = actual_output_by_node[c]
201
-
202
- else
203
- # remove <p> around block-level child (added by Markdown)
204
- actual_output.sub! %r{(<p>\s*)?#{
205
- Regexp.quote c.output
206
- }(\s*</p>)?} do
207
- actual_output_by_node[c] +
208
- if $1 and $2
209
- ''
210
- else
211
- [$1, $2].join
212
- end
213
- end
214
- end
215
- end
216
-
217
- actual_output_by_node[n] = actual_output
218
-
219
- #
220
- # allow the parent node to calculate its actual
221
- # output without interference from the output of
222
- # this node (Node#to_s is aliased to Node#output)
223
- #
224
- # this assumes that having this node's string
225
- # representation be a consecutive sequence of digits
226
- # will not interfere with the text-to-whatever
227
- # transformation defined by the format specification
228
- #
229
- n.output = Digest::SHA1.digest(n.object_id.to_s).unpack('I*').join
230
- end
231
-
232
- @roots.each {|n| visitor.call n }
233
-
234
- # replace the temporary identifier with each node's actual output
235
- @nodes.each {|n| n.output = actual_output_by_node[n] }
236
-
237
- rescue Exception
238
- puts input_text # so the user can debug line numbers in stack trace
239
- error "Could not process input document #{input_file.inspect}"
240
- end
49
+ process_input_document
241
50
  end
242
51
 
243
52
  ##
@@ -245,7 +54,7 @@ module ERBook
245
54
  #
246
55
  def to_s
247
56
  Template.new("#{@format_file}:output", @format['output'].to_s).
248
- render_with(@template_vars.merge(:@content => @processed_document.join))
57
+ render_with(@template_vars.merge(:@content => @evaluated_document.join))
249
58
  end
250
59
 
251
60
  require 'ostruct'
@@ -291,6 +100,216 @@ module ERBook
291
100
 
292
101
  private
293
102
 
103
+ def load_format format_name
104
+ @format_file = format_name.to_s
105
+
106
+ File.file? @format_file or
107
+ @format_file = File.join(ERBook::FORMATS_DIR, @format_file + '.yaml')
108
+
109
+ begin
110
+ @format = YAML.load_file(@format_file)
111
+ @format[:file] = File.expand_path(@format_file)
112
+ @format[:name] = File.basename(@format_file).sub(/\..*?$/, '')
113
+
114
+ if @format.key? 'code'
115
+ eval @format['code'].to_s, TOPLEVEL_BINDING, "#{@format_file}:code"
116
+ end
117
+
118
+ rescue Exception
119
+ error "Could not load format specification file #{@format_file.inspect}"
120
+ end
121
+
122
+ @node_defs = @format['nodes']
123
+ end
124
+
125
+ def process_input_document
126
+ evaluate_input_document
127
+ process_document_tree
128
+ calculate_node_outputs
129
+ rescue Exception
130
+ puts @input_text # so the user can debug line numbers in stack trace
131
+ error "Could not process input document #{@input_file.inspect}"
132
+ end
133
+
134
+ def evaluate_input_document
135
+ template = create_sandboxed_template
136
+ template.render
137
+ @evaluated_document = template.buffer
138
+ end
139
+
140
+ def process_document_tree
141
+ # chain block-level nodes together for local navigation
142
+ block_nodes = @nodes.select {|n| n.chain? }
143
+
144
+ require 'enumerator'
145
+ block_nodes.each_cons(2) do |a, b|
146
+ a.next_node = b
147
+ b.prev_node = a
148
+ end
149
+ end
150
+
151
+ def calculate_node_outputs
152
+ actual_output_by_node = {}
153
+
154
+ visitor = lambda do |n|
155
+ #
156
+ # allow child nodes to calculate their actual
157
+ # output and to set their identifier as Node#output
158
+ #
159
+ # we do this nodes first because this node's
160
+ # content contains the child nodes' output
161
+ #
162
+ n.children.each {|c| visitor.call c }
163
+
164
+ # calculate the output for this node
165
+ actual_output = Template.new(
166
+ "#{@format_file}:nodes:#{n.type}:output",
167
+ n.definition['output'].to_s.chomp
168
+ ).render_with(@template_vars.merge(:@node => n))
169
+
170
+ # reveal child nodes' actual output in this node's actual output
171
+ n.children.each do |c|
172
+ if c.silent?
173
+ # this child's output is not meant to be revealed at this time
174
+ next
175
+
176
+ elsif c.inline?
177
+ actual_output[c.output] = actual_output_by_node[c]
178
+
179
+ else
180
+ # remove <p> around block-level child (added by Markdown)
181
+ actual_output.sub! %r{(<p>\s*)?#{
182
+ Regexp.quote c.output
183
+ }(\s*</p>)?} do
184
+ actual_output_by_node[c] +
185
+ if $1 and $2
186
+ ''
187
+ else
188
+ [$1, $2].join
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ actual_output_by_node[n] = actual_output
195
+
196
+ #
197
+ # allow the parent node to calculate its actual
198
+ # output without interference from the output of
199
+ # this node (Node#to_s is aliased to Node#output)
200
+ #
201
+ # this assumes that having this node's string
202
+ # representation be a consecutive sequence of digits
203
+ # will not interfere with the text-to-whatever
204
+ # transformation defined by the format specification
205
+ #
206
+ n.output = Digest::SHA1.digest(n.object_id.to_s).unpack('I*').join
207
+ end
208
+
209
+ @roots.each {|n| visitor.call n }
210
+
211
+ # replace the temporary identifier with each node's actual output
212
+ @nodes.each {|n| n.output = actual_output_by_node[n] }
213
+ end
214
+
215
+ def create_sandboxed_template
216
+ template = Template.new(@input_file, @input_text, @options[:unindent])
217
+ sandbox = template.sandbox
218
+
219
+ @template_vars = {
220
+ :@format => @format,
221
+ :@roots => @roots = [], # root nodes of all trees
222
+ :@nodes => @nodes = [], # all nodes in the forest
223
+ :@nodes_by_type => @nodes_by_type = Hash.new {|h,k| h[k] = [] },
224
+ :@stack => [], # stack for all nodes
225
+ }.each_pair {|k,v| sandbox.instance_variable_set(k, v) }
226
+
227
+ #:stopdoc:
228
+
229
+ ##
230
+ # Handles the method call from a node
231
+ # placeholder in the input document.
232
+ #
233
+ def sandbox.__node_handler__ node_type, *node_args, &node_content
234
+ node = Node.new(
235
+ :type => node_type,
236
+ :definition => @format['nodes'][node_type],
237
+ :arguments => node_args,
238
+ :backtrace => caller,
239
+ :parent => @stack.last,
240
+ :children => []
241
+ )
242
+
243
+ Array(node.definition['params']).each do |param|
244
+ break if node_args.empty?
245
+ node.__send__ "#{param}=", node_args.shift
246
+ end
247
+
248
+ @nodes << node
249
+ @nodes_by_type[node.type] << node
250
+
251
+ # calculate ordinal number for this node
252
+ if node.ordinal_number?
253
+ @count_by_type ||= Hash.new {|h,k| h[k] = 0 }
254
+ node.ordinal_number = (@count_by_type[node.type] += 1)
255
+ end
256
+
257
+ # assign node family
258
+ if parent = node.parent
259
+ parent.children << node
260
+ node.parent = parent
261
+ node.depth = parent.depth
262
+ node.depth += 1 if node.anchor?
263
+
264
+ # calculate section number for this node
265
+ if node.section_number?
266
+ ancestor = @stack.reverse.find {|n| n.section_number }
267
+ branches = parent.children.select {|n| n.section_number }
268
+
269
+ node.section_number = [
270
+ ancestor.section_number,
271
+ branches.length + 1
272
+ ].join('.')
273
+ end
274
+ else
275
+ @roots << node
276
+ node.parent = nil
277
+ node.depth = 0
278
+
279
+ # calculate section number for this node
280
+ if node.section_number?
281
+ branches = @roots.select {|n| n.section_number }
282
+ node.section_number = (branches.length + 1).to_s
283
+ end
284
+ end
285
+
286
+ # assign node content
287
+ if block_given?
288
+ @stack.push node
289
+ node.content = __block_content__(node, &node_content)
290
+ @stack.pop
291
+ end
292
+
293
+ @buffer << node
294
+
295
+ nil
296
+ end
297
+
298
+ #:startdoc:
299
+
300
+ @node_defs.each_key do |type|
301
+ # XXX: using a string because define_method()
302
+ # does not accept a block until Ruby 1.9
303
+ file, line = __FILE__, __LINE__; eval %{
304
+ def sandbox.#{type} *node_args, &node_content
305
+ __node_handler__ #{type.inspect}, *node_args, &node_content
306
+ end
307
+ }, binding, file, line
308
+ end
309
+
310
+ template
311
+ end
312
+
294
313
  ##
295
314
  # Prints the given message and raises the given error.
296
315
  #