erbook 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  Copyright 2006 Suraj N. Kurapati <sunaku@gmail.com>
2
2
 
3
- Permission to use, copy, modify, and distribute this software for any
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
4
  purpose with or without fee is hereby granted, provided that the above
5
5
  copyright notice and this permission notice appear in all copies.
6
6
 
data/Rakefile CHANGED
@@ -1,80 +1,7 @@
1
- require 'rake/clean'
1
+ require 'rubygems'
2
+ require 'inochi'
2
3
 
3
- # documentation
4
- desc "Build the documentation."
5
- task :doc
6
-
7
- # user manual
8
- src = 'doc/manual.erb'
9
- dst = 'doc/index.xhtml'
10
-
11
- task :manual => dst
12
- task :doc => :manual
13
-
14
- file dst => src do
15
- sh "ruby bin/erbook -u xhtml #{src} > #{dst}"
16
- end
17
-
18
- CLOBBER.include dst
19
-
20
- # API reference
21
- require 'rake/rdoctask'
22
-
23
- Rake::RDocTask.new 'doc/api' do |t|
24
- t.rdoc_dir = t.name
25
- t.rdoc_files.exclude('pkg').include('**/*.rb')
26
- end
27
-
28
- task :doc => 'doc/api'
29
-
30
- # packaging
31
- require 'rake/gempackagetask'
32
- require 'lib/erbook' # project info
33
-
34
- spec = Gem::Specification.new do |s|
35
- s.rubyforge_project = 'sunaku'
36
- s.author, s.email = File.read('LICENSE').
37
- scan(/Copyright \d+ (.*) <(.*?)>/).first
38
-
39
- s.name = ERBook::PROJECT
40
- s.version = ERBook::VERSION
41
- s.summary = ERBook::SUMMARY
42
- s.description = s.summary
43
- s.homepage = ERBook::WEBSITE
44
- s.files = FileList['**/*']
45
- s.executables = s.name
46
- s.has_rdoc = true
47
-
48
- # gems needed by the main program executable
49
- s.add_dependency 'trollop', '~> 1.10'
50
-
51
- # gems needed by the default 'xhtml' format
52
- s.add_dependency 'maruku', '~> 0.5'
53
- s.add_dependency 'coderay', '>= 0.7'
54
- end
55
-
56
- Rake::GemPackageTask.new(spec) do |pkg|
57
- pkg.need_tar = true
58
- pkg.need_zip = true
59
- end
60
-
61
- desc 'Build release packages.'
62
- task :pack => [:clobber, :doc] do
63
- sh $0, 'package'
64
- end
65
-
66
- # releasing
67
- desc 'Upload to project website.'
68
- task :website => :doc do
69
- sh "rsync -av doc/ ~/www/lib/#{spec.name}"
70
- sh "rsync -av doc/api/ ~/www/lib/#{spec.name}/api/ --delete"
71
- end
72
-
73
- desc 'Publish release packages.'
74
- task :publish => :pack do
75
- sh 'rubyforge', 'login'
76
-
77
- Dir['pkg/*.[a-z]*'].each do |pkg|
78
- sh 'rubyforge', 'add_release', '--release_date', ERBook::RELEASE, spec.rubyforge_project, spec.name, spec.version.to_s, pkg
79
- end
80
- end
4
+ Inochi.rake :ERBook,
5
+ :rubyforge_project => 'sunaku',
6
+ :upload_target => File.expand_path('~/www/lib/erbook/'),
7
+ :upload_delete => true
data/bin/erbook CHANGED
@@ -1,7 +1,5 @@
1
1
  #!/usr/bin/ruby -w
2
2
  #
3
- # erbook is an extensible document processor based on eRuby.
4
- #
5
3
  # * The standard input stream will be read if an input file is not specified.
6
4
  #
7
5
  # * The final output document will be written to the standard output stream.
@@ -15,329 +13,37 @@
15
13
  # erbook [Option...] FormatFile [InputFile]
16
14
  #
17
15
 
18
- $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
19
- require 'erbook'
20
-
21
- module ERBook
22
- # Prints the given message and raises the given error.
23
- def ERBook.error aMessage, aError = $!
24
- STDERR.printf "%s:\n\n", aMessage
25
- raise aError
26
- end
27
-
28
- require 'digest/sha1'
29
- # Returns a digest of this string that's not altered by String#to_html.
30
- def ERBook.digest aInput
31
- # XXX: surround all digits with alphabets so
32
- # Maruku doesn't change them into HTML
33
- Digest::SHA1.hexdigest(aInput.to_s).gsub(/\d/, 'z\&z')
34
- end
35
-
36
- require 'erb'
37
- class Template < ERB
38
- # The result of template evaluation thus far.
39
- attr_reader :buffer
40
-
41
- # aSource:: String that replaces the ambiguous '(erb)'
42
- # identifier in stack traces, so that the user
43
- # can better determine the source of an error.
44
- #
45
- # aInput:: String containing eRuby directives. This
46
- # string will be modified by this method!
47
- #
48
- # aSafeLevel:: See safe_level in ERB::new().
49
- #
50
- def initialize aSource, aInput, aUnindent = false, aSafeLevel = nil
51
- # convert "% at beginning of line" usage into <% normal %> usage
52
- aInput.gsub! %r{^([ \t]*)(%[=# \t].*)$}, '\1<\2 %>'
53
- aInput.gsub! %r{^([ \t]*)%%}, '\1%'
54
-
55
- # silence the code-only <% ... %> directive, just like PHP does
56
- aInput.gsub! %r{^[ \t]*(<%[^%=]((?!<%).)*?[^%]%>)[ \t]*\r?\n}m, '\1'
16
+ require 'rubygems'
17
+ require 'inochi'
57
18
 
58
- # unindent node content hierarchically
59
- if aUnindent
60
- tags = aInput.scan(/<%(?:.(?!<%))*?%>/m)
61
- margins = []
62
- result = []
63
-
64
- buffer = aInput
65
- tags.each do |tag|
66
- chunk, buffer = buffer.split(tag, 2)
67
- chunk << tag
68
-
69
- # perform unindentation
70
- result << chunk.gsub(/^#{margins.last}/, '')
71
-
72
- # prepare for next unindentation
73
- case tag
74
- when /<%[^%=].*?\bdo\b.*?%>/m
75
- margins.push buffer[/^[ \t]*(?=\S)/]
76
-
77
- when /<%\s*end\s*%>/m
78
- margins.pop
79
- end
80
- end
81
- result << buffer
82
-
83
- aInput = result.join
84
- end
85
-
86
- # use @buffer to store the result of the ERB template
87
- super aInput, aSafeLevel, nil, :@buffer
88
-
89
- self.filename = aSource
90
- end
19
+ # command line
20
+ options = Inochi.main :ERBook do
21
+ # show list of available formats
22
+ text 'FormatName:'
91
23
 
92
- # Renders this template within a fresh object that
93
- # is populated with the given instance variables.
94
- def render_with aInstVars = {}
95
- context = Object.new.instance_eval do
96
- aInstVars.each_pair do |var, val|
97
- instance_variable_set var, val
98
- end
99
-
100
- binding
101
- end
102
-
103
- result(context)
24
+ require 'yaml'
25
+ ERBook::FORMAT_FILES.each do |file|
26
+ name = File.basename(file, '.yaml')
27
+ desc = YAML.load_file(file)['desc'] rescue nil
28
+ banner '%16s: %s' % [name, desc]
104
29
  end
105
30
 
106
- private
107
-
108
- # Returns the content that the given block wants to append to
109
- # the buffer. If the given block does not want to append to the
110
- # buffer, then returns the result of invoking the given block.
111
- def content_from_block *aBlockArgs
112
- raise ArgumentError, 'block must be given' unless block_given?
113
-
114
- head = @buffer.length
115
- body = yield(*aBlockArgs) # this will do: @buffer << content
116
- tail = @buffer.length
117
-
118
- if tail > head
119
- @buffer.slice! head..tail
120
- else
121
- body
122
- end.to_s
123
- end
124
- end
31
+ text ''
125
32
 
126
- require 'ostruct'
127
- class Node < OpenStruct
128
- # deprecated in Ruby 1.8; removed in Ruby 1.9
129
- undef id if respond_to? :id
130
- undef type if respond_to? :type
33
+ # show list of command-line options
34
+ text 'Option:'
35
+ opt :unindent, 'Unindent node content hierarchically'
131
36
  end
132
37
 
133
- # XXX: the basename() is for being launched by a RubyGems executable
134
- if __FILE__ == $0 or File.basename(__FILE__) == File.basename($0)
135
- require 'yaml'
136
-
137
- # parse command-line options
138
- begin require 'rubygems' rescue LoadError end
139
- require 'trollop'
140
-
141
- opts = Trollop::options do
142
- # show program description located at the top of this file
143
- banner File.read(__FILE__)[/\A.*?^$\n/m].
144
- gsub(/^# ?/, '').sub(/\A.*?\n/, '')
145
- banner ''
146
-
147
- # show list of available formats
148
- banner 'FormatName:'
149
- ERBook::FORMAT_FILES.each do |file|
150
- name = File.basename(file, '.yaml')
151
- desc = YAML.load_file(file)['desc'] rescue nil
152
- banner '%16s: %s' % [name, desc]
153
- end
154
- banner ''
155
-
156
- # show list of command-line options
157
- banner 'Option:'
158
- opt :unindent, 'Unindent node content hierarchically'
159
-
160
- # show program version information
161
- version [
162
- "project: #{ERBook::PROJECT}",
163
- "version: #{ERBook::VERSION}",
164
- "release: #{ERBook::RELEASE}",
165
- "website: #{ERBook::WEBSITE}",
166
- "install: #{ERBook::INSTALL_DIR}",
167
- ].join("\n")
168
- end
169
-
170
- # load format specification file
171
- spec_file = ARGV.shift or
172
- raise ArgumentError, "Format was not specified. Run `#{$0} -h` for help."
38
+ # program body
39
+ format = ARGV.shift or
40
+ raise ArgumentError, "Format was not specified. Run `#{$0} -h` for help."
173
41
 
174
- File.file? spec_file or
175
- spec_file = File.join(ERBook::FORMATS_DIR, spec_file + '.yaml')
176
-
177
- begin
178
- spec_data = YAML.load_file(spec_file)
179
- spec_data[:file] = File.expand_path(spec_file)
180
- spec_data[:name] = File.basename(spec_file).sub(/\..*?$/, '')
181
-
182
- if spec_data.key? 'code'
183
- eval spec_data['code'].to_s, TOPLEVEL_BINDING, "#{spec_file}:code"
184
- end
185
-
186
- rescue Exception
187
- error "Error when loading the format specification file (#{spec_file.inspect})"
188
- end
189
-
190
- # load input document
191
- if input_file = ARGV.shift
192
- input = File.read input_file
193
- else
194
- input_file, input = 'STDIN', STDIN.read
195
- end
196
-
197
- begin
198
- # expand all "include" directives in the input
199
- begin end while input.gsub! %r{<%#\s*include\s+(.+?)\s*#%>} do
200
- file, line = $1, $`.count("\n").next
201
-
202
- # provide more accurate stack trace for
203
- # errors originating from included files.
204
- #
205
- # NOTE: eRuby does NOT seem to provide line numbers for trace
206
- # entries that are deeper than the input document itself
207
- #
208
- "<%
209
- begin
210
- %>#{File.read file}<%
211
- rescue Exception => err
212
- bak = err.backtrace
213
-
214
- # set the input document's originating line number to
215
- # where this file was included in the input document
216
- top = bak.find {|t| t =~ /#{/#{input_file}/}:\\d+$/ }
217
- top.sub! %r/\\d+$/, '#{line}'
218
-
219
- # add a stack trace entry mentioning this included file
220
- ins = bak.index top
221
- bak.insert ins, #{file.inspect}
222
-
223
- raise err
224
- end
225
- %>"
226
- end
227
-
228
- # create sandbox for input evaluation
229
- template = Template.new(input_file, input, opts[:unindent])
230
-
231
- template_vars = {
232
- :@spec => spec_data,
233
- :@roots => roots = [], # root nodes of all trees
234
- :@nodes => nodes = [], # all nodes in the forest
235
- :@types => types = Hash.new {|h,k| h[k] = []}, # nodes by type
236
- }.each_pair {|k,v| template.instance_variable_set(k, v) }
237
-
238
- node_defs = spec_data['nodes'].each_pair do |type, defn|
239
- template.instance_eval %{
240
- #
241
- # XXX: using a string because define_method()
242
- # does not accept a block until Ruby 1.9
243
- #
244
- def #{type} *aArgs, &aBlock
245
- node = Node.new(
246
- :type => #{type.inspect},
247
- :args => aArgs,
248
- :trace => caller,
249
- :children => []
250
- )
251
- @nodes << node
252
- @types[node.type] << node
253
-
254
- # calculate occurrence number for this node
255
- if #{defn['number']}
256
- @count ||= Hash.new {|h,k| h[k] = []}
257
- node.number = (@count[node.type] << node).length
258
- end
259
-
260
- @stack ||= []
261
-
262
- # assign node family
263
- if parent = @stack.last
264
- parent.children << node
265
- node.parent = parent
266
- node.depth = parent.depth.next
267
-
268
- # calculate latex-style index number for this node
269
- if #{defn['index']}
270
- branches = parent.children.select {|n| n.index}
271
- node.index = [parent.index, branches.length.next].join('.')
272
- end
273
- else
274
- @roots << node
275
- node.parent = nil
276
- node.depth = 0
277
-
278
- # calculate latex-style index number for this node
279
- if #{defn['index']}
280
- branches = @roots.select {|n| n.index}
281
- node.index = branches.length.next.to_s
282
- end
283
- end
284
-
285
- # assign node content
286
- if block_given?
287
- @stack.push node
288
- content = content_from_block(node, &aBlock)
289
- @stack.pop
290
-
291
- digest = ERBook.digest(content)
292
- self.buffer << digest
293
- else
294
- content = nil
295
- digest = ERBook.digest(node.object_id)
296
- end
297
-
298
- node.content = content
299
- node.digest = digest
300
-
301
- digest
302
- end
303
- }, __FILE__, Kernel.caller.first[/\d+/].to_i.next
304
- end
305
-
306
- # build the document tree
307
- document = template.instance_eval { result(binding) }
308
-
309
- # replace nodes with output
310
- expander = lambda do |n, buf|
311
- # calculate node output
312
- source = "#{spec_file}:nodes:#{n.type}:output"
313
- n.output = Template.new(
314
- source, node_defs[n.type]['output'].to_s.chomp).
315
- render_with(template_vars.merge(:@node => n))
316
-
317
- # replace node with output
318
- if node_defs[n.type]['silent']
319
- buf[n.digest] = ''
320
- buf = n.output
321
- else
322
- buf[n.digest] = n.output
323
- end
324
-
325
- # repeat for all child nodes
326
- n.children.each {|c| expander[c, buf] }
327
- end
328
-
329
- roots.each {|n| expander[n, document] }
330
-
331
- rescue Exception => e
332
- # omit erbook internals from the stack trace
333
- e.backtrace.reject! {|t| t =~ /^#{$0}:\d+/ } unless $DEBUG
334
-
335
- puts input # so the user can debug the line numbers in the stack trace
336
- error "Error when processing the input document (#{input_file})"
337
- end
338
-
339
- # emit output document
340
- puts Template.new("#{spec_file}:output", spec_data['output'].to_s).
341
- render_with(template_vars.merge(:@content => document))
42
+ if input_file = ARGV.shift
43
+ input_text = File.read(input_file)
44
+ else
45
+ input_file = 'STDIN'
46
+ input_text = STDIN.read
342
47
  end
343
- end
48
+
49
+ puts ERBook::Document.new(format, input_text, input_file, options)