erbook 9.2.0 → 9.2.1

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