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/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)