nandoc 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/README +5 -4
  2. data/Rakefile +1 -1
  3. data/bin/nandoc +2 -1
  4. data/doc/FAQ.md +3 -0
  5. data/doc/PROVISO.md +39 -0
  6. data/doc/commands/diff.md +49 -0
  7. data/doc/svg/less-fonts.svg +2 -2
  8. data/lib/nandoc/cli/README.md +6 -0
  9. data/lib/nandoc/cli/command-methods.rb +38 -0
  10. data/lib/nandoc/cli/option-methods/exclusive-options.rb +56 -0
  11. data/lib/nandoc/cli/option-methods/option-enum.rb +64 -0
  12. data/lib/nandoc/cli/option-methods.rb +35 -0
  13. data/lib/nandoc/cli.rb +3 -0
  14. data/lib/nandoc/commands/create-nandoc-site.rb +9 -12
  15. data/lib/nandoc/commands/diff.rb +14 -11
  16. data/lib/nandoc/commands.rb +9 -0
  17. data/lib/nandoc/{config.rb → core/config.rb} +18 -9
  18. data/lib/nandoc/core/project.rb +50 -0
  19. data/lib/nandoc/doc/hack-free-zone-defined.md +33 -0
  20. data/lib/nandoc/erb/agent.rb +5 -5
  21. data/lib/nandoc/{test/minitest-extlib.rb → extlib/minitest.rb} +1 -1
  22. data/lib/nandoc/filters/builtin-tags/fence/terminal.rb +24 -0
  23. data/lib/nandoc/filters/builtin-tags/fence-dispatcher.rb +43 -0
  24. data/lib/nandoc/filters/builtin-tags/fences.rb +4 -0
  25. data/lib/nandoc/filters/builtin-tags/see-test.rb +67 -0
  26. data/lib/nandoc/filters/builtin-tags.rb +11 -0
  27. data/lib/nandoc/filters/custom-tag.rb +43 -0
  28. data/lib/nandoc/filters/custom-tags.rb +19 -0
  29. data/lib/nandoc/filters/tag-parse-instance-methods.rb +11 -0
  30. data/lib/nandoc/filters/tag-parser.rb +206 -0
  31. data/lib/nandoc/filters.rb +11 -585
  32. data/lib/nandoc/{cri-hacks.rb → hacks/cri-hacks.rb} +4 -3
  33. data/lib/nandoc/{data-source.rb → hacks/data-source.rb} +5 -4
  34. data/lib/nandoc/{item-class-hacks.rb → hacks/item-class-hacks.rb} +3 -1
  35. data/lib/nandoc/hacks.rb +6 -0
  36. data/lib/nandoc/helpers/menu-bouncy.rb +1 -1
  37. data/lib/nandoc/helpers/site-map.rb +3 -0
  38. data/lib/nandoc/helpers.rb +1 -1
  39. data/lib/nandoc/html/tags.rb +65 -0
  40. data/lib/nandoc/html.rb +6 -0
  41. data/lib/nandoc/parse-readme.rb +4 -0
  42. data/lib/nandoc/spec-doc/agent-instance-methods.rb +24 -0
  43. data/lib/nandoc/spec-doc/code-snippet.rb +59 -0
  44. data/lib/nandoc/spec-doc/generic-agent.rb +40 -0
  45. data/lib/nandoc/spec-doc/mock-prompt.rb +3 -9
  46. data/lib/nandoc/spec-doc/parse-trace.rb +25 -0
  47. data/lib/nandoc/spec-doc/{mini-test/spec-instance-methods.rb → playback/html/foo-bar.rb} +0 -0
  48. data/lib/nandoc/spec-doc/playback/html.rb +2 -0
  49. data/lib/nandoc/spec-doc/playback/players/method.rb +64 -0
  50. data/lib/nandoc/spec-doc/playback/players/ruby.rb +158 -0
  51. data/lib/nandoc/spec-doc/playback/players/terminal.rb +93 -0
  52. data/lib/nandoc/spec-doc/playback/players.rb +4 -0
  53. data/lib/nandoc/spec-doc/playback/support/playback-methods.rb +44 -0
  54. data/lib/nandoc/spec-doc/playback/support/sexp-scanner.rb +61 -0
  55. data/lib/nandoc/spec-doc/playback/support.rb +3 -0
  56. data/lib/nandoc/spec-doc/playback/terminal/color-to-html.rb +100 -0
  57. data/lib/nandoc/spec-doc/playback.rb +3 -0
  58. data/lib/nandoc/spec-doc/recordings.rb +55 -0
  59. data/lib/nandoc/spec-doc/ruby2ruby-standin.rb +37 -0
  60. data/lib/nandoc/spec-doc/test-case-agent.rb +1 -1
  61. data/lib/nandoc/spec-doc/{mini-test.rb → test-framework/mini-test/proxy.rb} +9 -31
  62. data/lib/nandoc/spec-doc/{test-framework-proxy.rb → test-framework/proxy.rb} +27 -50
  63. data/lib/nandoc/spec-doc.rb +57 -13
  64. data/lib/nandoc/{test → support}/diff-to-string.rb +0 -0
  65. data/lib/nandoc/support/regexp-enhance.rb +6 -0
  66. data/lib/nandoc/support/regexp.rb +12 -0
  67. data/lib/nandoc/support/secret-parent.rb +21 -0
  68. data/lib/nandoc/support/shared-attr-reader.rb +32 -0
  69. data/lib/nandoc/support/site-merge.rb +1 -1
  70. data/lib/nandoc/support/site-methods.rb +4 -4
  71. data/lib/nandoc/support/stream-colorizer.rb +1 -1
  72. data/lib/nandoc/support/string-methods.rb +56 -0
  73. data/lib/nandoc.rb +12 -35
  74. data/proto/README.md +4 -2
  75. data/test/test.rb +1 -0
  76. metadata +58 -25
  77. data/doc/bar/baz.md +0 -4
  78. data/doc/bar/bliff.md +0 -8
  79. data/doc/foo.md +0 -5
  80. data/doc/getting-started.rb +0 -13
  81. data/lib/nandoc/spec-doc/support-modules.rb +0 -158
  82. data/lib/nandoc/spec-doc/test-framework-dispatcher.rb +0 -15
  83. data/lib/nandoc/support-modules.rb +0 -273
  84. data/lib/nandoc/treebis/NOGIT-DOCS/NEWS.md +0 -5
  85. data/lib/nandoc/treebis/NOGIT-README.md +0 -65
  86. data/lib/nandoc/treebis/nandoc.persistent.json +0 -3
@@ -1,13 +1,13 @@
1
- require File.dirname(__FILE__)+'/support/regexp-enhance.rb'
1
+ # registers self at bottom!
2
+ here = File.dirname(__FILE__)
3
+ require here+'/filters/custom-tags.rb'
4
+ require here+'/filters/tag-parse-instance-methods.rb'
5
+ require here+'/filters/builtin-tags.rb'
6
+ require here+'/spec-doc.rb'
7
+ require here+'/spec-doc/playback'
2
8
 
3
9
  module NanDoc::Filters
4
10
  class General < ::Nanoc3::Filter
5
- include Nanoc3::Helpers::HTMLEscape
6
- alias_method :h, :html_escape
7
-
8
- module TerminalColorToHtml; end
9
- include TerminalColorToHtml
10
-
11
11
  # Parses document contents for nanDoc enhancements to
12
12
  # markdown-like markup.
13
13
 
@@ -73,589 +73,15 @@ module NanDoc::Filters
73
73
  # as the fences.
74
74
  #
75
75
 
76
- include NanDoc::StringFormatting # oxford_comma
77
-
76
+ public
78
77
 
79
78
  # @param [String] content The content to filter
80
79
  # @param [Hash] params - not used
81
80
  # @return [String] The filtered content
82
81
  def run content, params={}
83
- content = filter_fence(content) if ReFenceFind =~ content
84
- content = filter_see_test(content) if ReSeeTest =~ content
85
- content
86
- end
87
-
88
- def unindent_generic str
89
- md = ReUnindent.match(str) or fail("no")
90
- reindent_content(md)
91
- end
92
- private
93
-
94
- RecognizedTags = ['ruby', 'from the command line']
95
- ReFenceFind = /^([[:space:]]*)[ a-z]+:[[:space:]]*\n\1~~~[[:space:]]*\n/m
96
- ReFenceCap = %r<
97
- ^((?:[ ]|\t)*)((?:[a-z]|[ ])+):(?:[ ]|\t)*\n
98
- \1~~~(?:[ ]|\t)*\n
99
- (.*?)\n
100
- \1~~~(?:[ ]|\t)*\n
101
- >mx
102
- NanDoc::RegexpEnhance.names(ReFenceCap, :indent, :tag_name, :content)
103
-
104
- ReSeeTest = /\(see: ((?:spec|test)[^\)]+)\)/
105
- NanDoc::RegexpEnhance.names(ReSeeTest, :content)
106
-
107
- ReSeeTestParse =
108
- /\A((?:spec|test).*\.rb) ?(?:--?|\/) ?['"]([^'"]+)['"](.+)?\Z/
109
- NanDoc::RegexpEnhance.names(ReSeeTestParse, :testfile, :testname, :xtra)
110
-
111
- ReUnindent = /\A([ \t]*)(.*)\Z/m
112
- NanDoc::RegexpEnhance.names(ReUnindent, :indent, :content)
113
-
114
- def initialize(*a)
115
- super(*a)
116
- @prompt_str = prompt_str_default
117
- end
118
-
119
- def advance_to_story sexp, md, idx
120
- story = md[:xtra] =~ /\A *(?:--?|\/) *['"](.+)['"]\Z/ && $1 or
121
- fail("couldn't parse out story name from #{md[:xtra].inspect}"<<
122
- "expecting for e.g \" - 'blah blah'\"")
123
- idx = sexp.index{|x| x.first == :story && x[1] == story } or
124
- fail("couldn't find story #{story.inspect}. Known stories are: ("<<
125
- sexp.select{|x| x.first == :story }.map{|x| "'#{x[1]}'"}.join(', ')<<
126
- ")")
127
- idx + 1
128
- end
129
-
130
- def converter_ruby
131
- @converter_ruby ||= begin
132
- require 'syntax/convertors/html'
133
- ::Syntax::Convertors::HTML.for_syntax 'ruby'
134
- end
135
- end
136
-
137
- def sexp_getter
138
- @sexp_getter ||= begin
139
- require File.dirname(__FILE__)+'/spec-doc.rb'
140
- NanDoc::SpecDoc::
141
- TestFrameworkDispatcher.new(current_project_root_hack)
142
- end
143
- end
144
-
145
- #
146
- # @todo this sucks. i didn't have time to think about how this should
147
- # work when i wrote it. The problem is, given that we are a nanoc
148
- # project, how do we know where live the tests we are spec-docing?
149
- #
150
- # For now we assume that the mysite folder is one level inside the root
151
- # of the (gem-like) project folder and we assert that the assumed root
152
- # looks right but this will be broken in the likely event that the nanoc
153
- # project will live elsewhere relative to the gem-like root.
154
- #
155
- def current_project_root_hack
156
- presumed_root = File.dirname(FileUtils.pwd)
157
- thems = %w(spec test)
158
- found = thems.detect{ |dir| File.directory?(presumed_root+'/'+dir) }
159
- fail("couldn't find " << oxford_comma(thems,' or ', &quoted) <<
160
- "in #{presumed_root}") unless found
161
- presumed_root
162
- end
163
-
164
- def ellipsis_default
165
- "..."
166
- end
167
-
168
- def filter_fence content
169
- with_each_tag_in(content, ReFenceCap) do |md|
170
- render_block_fence md
171
- end
172
- end
173
-
174
- def filter_see_test content
175
- with_each_tag_in(content, ReSeeTest) do |md|
176
- render_block_see_test md
177
- end
178
- end
179
-
180
- #
181
- # if the string has anything that looks like colors in it,
182
- # then just highlite the colors (as html), else
183
- # highlight things that look like prompts (as html)
184
- #
185
- def lines_highlighted content
186
- if colored_content = terminal_color_to_html(content)
187
- [colored_content]
188
- else
189
- these = content.split("\n").map do |line|
190
- line.sub( %r!\A(~[^>]*>)?(.*)\Z! ) do
191
- tags = [];
192
- tags.push "<span class='prompt'>#{h($1)}</span>" if $1
193
- tags.push "<span class='normal'>#{h($2)}</span>" unless $2.empty?
194
- tags.join('')
195
- end
196
- end
197
- these
198
- end
199
- end
200
-
201
- # @return the amount to advance the cursor by
202
- def process_sexp_ellipsis lines, sexp, i
203
- j = i
204
- fail("need :out_begin") unless sexp[j].first == :out_begin
205
- lines.push sexp[j][1].strip
206
- j += 1
207
- if sexp[j] && sexp[j].first == :cosmetic_ellipsis
208
- lines.push sexp[j][1]
209
- j += 1
210
- else
211
- lines.push ellipsis_default
212
- end
213
- fail("need :out_end") unless sexp[j] && sexp[j].first == :out_end
214
- lines.push sexp[j][1]
215
- ret = j - i
216
- ret
217
- end
218
-
219
- def prompt_str_cd new_dir
220
- /\A(.+) > \Z/ =~ prompt_str or
221
- fail("can't determine cwd from #{prmpt_str.inspect}")
222
- new_pwd = "#{$1}/#{new_dir}"
223
- @old_prompts ||= []
224
- @old_prompts.push prompt_str
225
- @prompt_str = "#{new_pwd} > "
226
- nil
227
- end
228
-
229
- def prompt_str_cd_pop
230
- @prompt_str = @old_prompts.pop
231
- end
232
-
233
- def prompt_str_default
234
- '~ > '
235
- end
236
-
237
- public # avoid warnings
238
- attr_reader :prompt_str
239
- private :prompt_str
240
- private
241
-
242
- def render_block_fence md
243
- if ! RecognizedTags.include?(md[:tag_name])
244
- fail("sorry, there has been a mistake. I shouldn't have parsed it "<<
245
- "but i went ahead and parsed a #{md[:tag_name].inspect} tag even "<<
246
- "though i don't know what to do with it. Known tags are "<<
247
- oxford_comma(RecognizedTags,&quoted)
248
- )
249
- end
250
- case md[:tag_name]
251
- when 'ruby'; render_block_fence_ruby md
252
- when 'from the command line'; render_block_fence_terminal md
253
- end
254
- end
255
-
256
- def render_block_see_test md
257
- md2 = ReSeeTestParse.match(md[:content]) or
258
- fail("couldn't parse see_test string: #{md[:content].inspect} -- "<<
259
- 'string must look like: \'(see: test_file.rb/"some test name")\''
260
- )
261
- getter = sexp_getter
262
- sexp = getter.get_sexp md2[:testfile], md2[:testname]
263
- sexp.first.first == :method or fail("i'm done with this kind of sexp")
264
- methname = sexp.first[1]
265
- idx = 0
266
- last = sexp.length - 1
267
- if md2[:xtra]
268
- idx = advance_to_story(sexp, md2, idx)
269
- end
270
- idx += 1 if sexp[0] && sexp[0].first == :method && idx == 0
271
- catch(:done) do
272
- while idx <= last
273
- node = sexp[idx]
274
- type = node.first
275
- case type
276
- when :cd, :command
277
- idx += process_sexp_command sexp, idx
278
- when :method
279
- if node[1] != methname
280
- fail("i don't like this kind of sexp anymore -- "<<
281
- "#{methname.inspect} != #{node[1].inspect}"
282
- )
283
- end
284
- when :note
285
- process_sexp_note sexp, idx
286
- when :record_ruby
287
- idx += ProcessSnippet.new(self, sexp, idx).process
288
- when :story
289
- # always stop at next story?
290
- throw :done
291
- else
292
- fail("unexpected sexp node here: #{type.inspect} idx: #{idx}")
293
- end
294
- idx += 1
295
- end
296
- end
297
- end
298
-
299
- def render_block_fence_terminal md
300
- content = reindent_content md
301
- render_terminal_div_highlighted content
302
- end
303
-
304
- def render_block_fence_ruby md
305
- content = reindent_content md
306
- content2 = content.strip # i think
307
- hilited = converter_ruby.convert(content2, false)
308
- pre_block = "\n<pre class='ruby'>\n#{hilited}\n</pre>\n"
309
- @chunks.push pre_block
310
- end
311
- public :render_block_fence_ruby # visitors
312
-
313
- def render_command_div content
314
- fake_command = "#{prompt_str}#{content}"
315
- render_terminal_div_highlighted fake_command
316
- end
317
-
318
- # @return [integer] how much to advance the cursor by
319
- # when you either hit the end or hit an unrecognized node
320
- # adds to rendered output a div with the command and output
321
- def process_sexp_command sexp, i
322
- lines = []
323
- j = i
324
- last = sexp.length - 1
325
- catch(:done) do
326
- while j <= last
327
- type = sexp[j].first
328
- case type
329
- when :cd; lines.push "#{prompt_str}cd #{sexp[j][1]}"
330
- prompt_str_cd sexp[j][1]
331
- when :cd_end; prompt_str_cd_pop
332
- when :command; lines.push "#{prompt_str}#{sexp[j][1]}"
333
- when :out; lines.push sexp[j][1].strip
334
- when :out_begin
335
- j += process_sexp_ellipsis lines, sexp, j
336
- else;
337
- j -= 1 unless j == i
338
- throw :done
339
- end
340
- j += 1
341
- end
342
- end
343
- raw_content = lines.join("\n")
344
- render_terminal_div_highlighted raw_content
345
- ret = j-i
346
- ret
347
- end
348
-
349
- # @return [nil] adds the output raw to the blickle blackle
350
- def process_sexp_note sexp, idx
351
- chunk = sexp[idx][1].call
352
- @chunks.push chunk
353
- end
354
-
355
- def render_terminal_div_highlighted content
356
- lines = ['<pre class="terminal">']
357
- lines.concat lines_highlighted(content)
358
- lines.push '</pre>'
359
- html = lines * "\n" + "\n"
360
- @chunks.push html
361
- end
362
-
363
- def render_unparsed start, last
364
- chunk = @content[start..last]
365
- @chunks.push chunk
366
- end
367
-
368
- def reindent_content md
369
- raw_content = md[:content]
370
- indent = md[:indent]
371
- return raw_content if indent == ''
372
- # of all non-blank lines find the minimum indent.
373
- x = raw_content.scan(/^[[:space:]]+(?=[^[:space:]])/).map(&:length).min
374
- # if for some reason the content has less indent than the fences,
375
- # don't alter any of it.
376
- return raw_content if x < indent.length
377
- re = /^#{Regexp.new(indent)}/
378
- unindented_content = raw_content.gsub(re, '')
379
- unindented_content
380
- end
381
-
382
- # ignoring multiline crap for now
383
- def ruby_snippet_inspect inspect
384
- "\n#=> #{inspect}"
385
- end
386
-
387
- def with_each_tag_in content, regexp, &block
388
- @content = content
389
- @chunks = []
390
- unparsed_start = 0
391
- offset = 0
392
- last = content.length - 1
393
- while offset <= last && md = regexp.match(content[offset..-1])
394
- unparsed_end = md.offset(0)[0] - 1 + offset
395
- offset += md.offset(0)[1]+1
396
- render_unparsed(unparsed_start, unparsed_end)
397
- unparsed_start = offset # offset is where we start searching next
398
- block.call(md)
399
- end
400
- render_unparsed(unparsed_start, -1)
401
- @chunks.join('')
402
- end
403
-
404
- require 'strscan'
405
- module TerminalColorToHtml
406
- # this sucks.
407
- #
408
- def terminal_color_to_html str
409
- return nil unless str.index("\e[") # save a whale
410
- scn = StringScanner.new(str)
411
- sexp = []
412
- while true
413
- foo = scn.scan(/(.*?)(?=\e\[)/m)
414
- if ! foo
415
- blork = scn.scan_until(/\Z/m) or fail("worglebezoik")
416
- sexp.push([:content, blork]) unless blork.empty?
417
- break;
418
- end
419
- foo or fail("oopfsh")
420
- sexp.push([:content, foo]) unless foo.empty?
421
- bar = scn.scan(/\e\[/) or fail("goff")
422
- baz = scn.scan(/\d+(?:;\d+)*/)
423
- baz or fail("narghh")
424
- if '0'==baz
425
- sexp.push([:pop])
426
- else
427
- sexp.push([:push, *baz.split(';')])
428
- end
429
- biff = scn.scan(/m/) or fail("noiflphh")
430
- end
431
- html = terminal_colorized_sexp_to_html sexp
432
- html
433
- end
434
- private
435
- # the other side of these associations lives in trollop-subset.css
436
- Code2CssClass = {
437
- '1' => 'bright', '30' => 'black', '31' => 'red', '32' => 'green',
438
- '33' => 'yellow', '34' => 'blue', '35' => 'magenta', '36' => 'cyan',
439
- '37' => 'white'
440
- }
441
- def terminal_code_to_css_class code
442
- Code2CssClass[code] or
443
- fail("sorry, no known code for #{code.inspect}. "<<
444
- "(maybe you should make one?)")
445
- end
446
- def terminal_colorized_sexp_to_html sexp
447
- i = -1;
448
- last = sexp.length - 1;
449
- parts = []
450
- catch(:done) do
451
- while (i+=1) <= last
452
- codes = nil
453
- while i <= last && sexp[i].first == :push
454
- codes ||= []
455
- codes.concat sexp[i][1..-1]
456
- i += 1
457
- end
458
- if codes
459
- classes = codes.map{|c| terminal_code_to_css_class(c) }*' '
460
- parts.push "<span class='#{classes}'>"
461
- end
462
- throw :done if i > last
463
- case sexp[i].first
464
- when :content; parts.push(sexp[i][1])
465
- when :pop; parts.push('</span>')
466
- else; fail('fook');
467
- end
468
- end
469
- end
470
- html = parts*''
471
- html
472
- end
473
- end
474
-
475
- module HackHelpers
476
- # stand-in for ruby-2-ruby
477
- #
478
-
479
- def leading_indent str
480
- /\A([ \t]*)/ =~ str && $1
481
- end
482
- def re_for_line_with_same_indent_as str
483
- ind = leading_indent(str)
484
- re = /\A#{Regexp.escape(ind)}(?=[^ \t])/
485
- re
486
- end
487
- def re_for_here here
488
- /\A[ \t]*#{Regexp.escape(here)}[ \t]*\n?\Z/
489
- end
490
- def re_for_unindent_gsub indent
491
- re = /\A#{Regexp.escape(indent)}/
492
- re
493
- end
494
- def string_diff_assert long, short
495
- idx = long.index(short) or fail("short not found in long -- "<<
496
- "#{short.inspect} in #{long.inspect}")
497
- head = long[0,idx] # usu. ''
498
- tail = long[idx + short.length..-1]
499
- head + tail
500
- end
501
- end
502
-
503
- class ProcessSnippet
504
- include HackHelpers
505
-
506
- def initialize filter, sexp, idx
507
- @prefix = '# => '
508
- sexp[idx].first == :record_ruby or fail("must be record_ruby")
509
- @filter, @sexp, @idx = filter, sexp, idx
510
- end
511
- ReInspect = /\A([ \t]*)(?:nandoc\.inspect[ \t]*)(.+)\Z/
512
- NanDoc::RegexpEnhance.names(ReInspect, :indent, :tail)
513
- ReOut = /\A[ \t]*nandoc\.out\([ \t]*<<-'?([A-Z]+)/
514
- ReUntilDo = /\A[ \t]*\)[ \t]*do[ \t]*\Z/
515
-
516
- ReHere = /\A(.*)(?:, ?<<-'?([A-Z]+))/
517
- NanDoc::RegexpEnhance.names(ReHere, :keep, :here)
518
-
519
- ConsumeThese = [:inspect, :out]
520
-
521
- def process
522
- j = @idx
523
- snip = @sexp[j][1]
524
- @lines = snip.file_lines.dup # we will be changing values
525
- @inspects = []
526
- while @sexp[j+1] && ConsumeThese.include?(@sexp[j+1].first)
527
- j += 1
528
- @inspects.push @sexp[j]
529
- end
530
- inspects_interpolate if @inspects.any?
531
- unindented_lines = @lines[snip.line_start..snip.line_stop-2]
532
- fake_unindented_ruby = unindented_lines.compact.join('')
533
- indent = /\A([ \t]*)/ =~ fake_unindented_ruby && $1
534
- fake_md = {:indent => indent, :content => fake_unindented_ruby}
535
- @filter.render_block_fence_ruby(fake_md)
536
- advance_by = j - @idx
537
- advance_by
538
- end
539
- private
540
- def erase_to_here offset, here
541
- re = /\A[ \t]*#{Regexp.escape(here)}\Z/
542
- found = (offset+1..@lines.length-1).detect{|idx| @lines[idx] =~ re }
543
- found or fail("heredoc hack failed. no #{re} found.")
544
- (offset+1..found).each{ |idx| @lines[idx] = nil }
545
- nil
546
- end
547
-
548
- # whether with a nandoc.out or nandoc.inspect, keeping the indentation
549
- # that's in the sourcefile, substitute real code for pretty code,
550
- # without changing the offsets of the lines. fragile hack.
551
- # @todo ruby2ruby?
552
- #
553
- def inspects_interpolate
554
- @inspects.each do |ins|
555
- # each call below will alter @lines (without shifting them)
556
- # accordingly, replacing actual code with pretty code (and comments)
557
- case ins[0]
558
- when :inspect; process_inspect(ins)
559
- when :out; process_out(ins)
560
- else fail("no: #{ins[0].inspect}")
561
- end
562
- end
563
- end
564
-
565
- # the block content gets output as if it's bare ruby,
566
- # the output (whether it was expected or actual we don't care)
567
- # gets output with leading comment markers. All of this nonsense is
568
- # bs proof of concept that needs to get blown away by ruby2ruby or
569
- # something
570
- #
571
- def process_out sexp
572
- call_offset = sexp[2][:line] - 1
573
- first = @lines[call_offset]
574
- ReOut =~ first or fail("DocSpec hack fail: Didn't look like "<<
575
- "nandoc.out line: #{first.inspect}\nExpecting line to match "<<
576
- " #{reOut}")
577
- j = call_offset + 1
578
- last = @lines.length - 1
579
- j += 1 until j > last || ReUntilDo =~ @lines[j]
580
- j <= last or fail("DocSpec hack fail: Couldn't find do block "<<
581
- "anywhere before EOF with #{ReUntilDo}")
582
- do_line = @lines[j]
583
- re = re_for_line_with_same_indent_as(do_line)
584
- repl_lines = []
585
- j += 1
586
- repl_from_here = j
587
- j += 1 until j > last || re =~ @lines[j]
588
- j <= last or fail("DocSpec hack fail: Couldn't find end of do "<<
589
- "block anywhere before EOF with #{re}")
590
- offset_of_line_with_end = j
591
- repl_lines = @lines[repl_from_here..offset_of_line_with_end-1]
592
- repl_lines.any? or fail("DocSpec hack fail -- no lines")
593
- ind_short = leading_indent(do_line)
594
- ind_long = leading_indent(repl_lines.first)
595
- ind_diff = string_diff_assert(ind_long, ind_short)
596
- unindent = re_for_unindent_gsub(ind_diff)
597
- repl_lines.map{ |x| x.sub!(unindent, '') } # this changes @lines val
598
- (0..repl_lines.length-1).each do |l|
599
- actual_offset = call_offset + l
600
- @lines[actual_offset] = repl_lines[l]
601
- end
602
- erase_from_here = call_offset + repl_lines.length
603
- (erase_from_here..offset_of_line_with_end).each do |l|
604
- @lines[l] = nil
605
- end
606
- # this is so fragile, it requires multiline blah blah
607
- commented_content = sexp[1].gsub(/^/m, "#{ind_short}# ")
608
- @lines[erase_from_here] = commented_content
609
- nil
610
- end
611
-
612
- #
613
- # comments at process_out apply to this too
614
- #
615
- def process_inspect sexp
616
- offset = sexp[2][:line] - 1
617
- act = @lines[offset]
618
- md = ReInspect.match(act) or
619
- fail("hack fail of nandoc.inspect near #{act.inspect}")
620
- md = md.to_hash
621
- tail = md[:tail]
622
- my_lines = []
623
- md2 = ReHere.match(tail)
624
- return process_inspect_oneline(sexp) unless md2
625
- md2 = md2.to_hash
626
- ind = leading_indent(@lines[offset])
627
- my_lines.push "#{ind}#{md2[:keep]}\n"
628
- re = re_for_here(md2[:here])
629
- j = offset + 1
630
- last = @lines.length - 1
631
- until re =~ @lines[j] || j > last
632
- back_one = @lines[j].sub(/\A(?: |\t)/,'')
633
- my_lines.push back_one.sub(/\A([\t ]*)/){ "#{$1}#{@prefix}" }
634
- j += 1
635
- end
636
- j > last && fail("DocSpec hack fail: #{md2[:here]} not found "<<
637
- "anywhere before EOF")
638
- (offset..j).each do |k|
639
- @lines[k] = nil
640
- end
641
- (0..my_lines.length-1).each do |k|
642
- l = offset+k
643
- @lines[l] = my_lines[k]
644
- end
645
- end
646
-
647
- def process_inspect_oneline sexp
648
- offset = sexp[2][:line] - 1
649
- line = @lines[offset]
650
- /\A([ \t]*)nandoc.inspect *([^,]+), *([^,]+)\n\Z/ =~ line or fail(
651
- "DocSpec hack fail: Why can't we parse this inspect "<<
652
- " line?\n#{line.inspect}")
653
- ind, keep, val = $1, $2, $3 # actually we don't want $3
654
- replace_with = "#{ind}#{keep}\n#{ind}#{@prefix}#{sexp[1]}\n"
655
- # assume no newlines in value when the whole thing was oneline
656
- @lines[offset] = replace_with
657
- nil
658
- end
82
+ CustomTags.change_item_content content
659
83
  end
660
84
  end
661
85
  end
86
+
87
+ Nanoc3::Filter.register ::NanDoc::Filters::General, :nandoc
@@ -1,12 +1,13 @@
1
+ require 'nandoc/cli'
2
+
1
3
  module Cri
2
4
  class Base
3
- # hack
4
- include NanDoc::TaskCommon
5
+ include NanDoc::Cli::CommandMethods
5
6
  def remove_command command_class
6
7
  if idx = @commands.index{|x| x.kind_of?(command_class) }
7
8
  @commands.delete_at(idx)
8
9
  else
9
- task_abort("command not found of class #{command_class}")
10
+ command_abort("command not found of class #{command_class}")
10
11
  end
11
12
  end
12
13
  end
@@ -1,3 +1,5 @@
1
+ require 'nandoc/cli'
2
+
1
3
  module NanDoc
2
4
 
3
5
  class DataSource < ::Nanoc3::DataSources::FilesystemUnified
@@ -12,8 +14,7 @@ module NanDoc
12
14
  # Some of the hacks in this file are the worst in the whole project. @todo
13
15
  #
14
16
 
15
-
16
- include NanDoc::TaskCommon # task_abort()
17
+ include Cli::CommandMethods # command_abort
17
18
 
18
19
  def initialize *a
19
20
  super(*a)
@@ -110,7 +111,7 @@ module NanDoc
110
111
  # this is NanDoc.
111
112
  #
112
113
  def error_for_no_files files
113
- task_abort <<-HERE.gsub(/\n +/,"\n").strip
114
+ command_abort <<-HERE.gsub(/\n +/,"\n").strip
114
115
  No matching content file(s) found at or under (#{files.join(', ')})
115
116
  from here. (This corresponds to the 'source_file_basenames' setting in
116
117
  config.yaml.) Did you generate the NanDoc site in the right directory?
@@ -189,7 +190,7 @@ module NanDoc
189
190
  # (undefined on name collision)
190
191
  #
191
192
  def orphan_rescue items
192
- require File.expand_path('../support/orphanage.rb', __FILE__)
193
+ require 'nandoc/support/orphanage.rb'
193
194
  Orphanage.rescue_orphans(@config, items)
194
195
  end
195
196
 
@@ -1,3 +1,5 @@
1
+ require 'nandoc/support/string-methods.rb'
2
+
1
3
  class Nanoc3::Item
2
4
  #
3
5
  # hacks we use for stuff like sitemap and topnav generation
@@ -13,7 +15,7 @@ class Nanoc3::Item
13
15
  end
14
16
 
15
17
 
16
- include NanDoc::StringFormatting # basename_no_extension()
18
+ include NanDoc::StringMethods # basename_no_extension()
17
19
 
18
20
  attr_accessor :identifier # know what you are doing if you set it
19
21
 
@@ -0,0 +1,6 @@
1
+ me = File.dirname(__FILE__)+'/hacks'
2
+ require me + '/cri-hacks.rb'
3
+ require me + '/item-class-hacks.rb'
4
+ require me + '/data-source.rb'
5
+
6
+ Nanoc3::DataSource.register ::NanDoc::DataSource, :nandoc
@@ -18,7 +18,7 @@ module NanDoc::Helpers::NanDocHelpers
18
18
  # @api private
19
19
  #
20
20
  class MenuBouncy
21
- include NanDoc::StringFormatting
21
+ include NanDoc::StringMethods
22
22
  def initialize(binding, &block)
23
23
  @separator_default = '&gt;'
24
24
  @tab = ' '
@@ -1,3 +1,6 @@
1
+ require 'nandoc/support/shared-attr-reader'
2
+ require 'nandoc/support/secret-parent'
3
+
1
4
  module NanDoc::Helpers::NanDocHelpers
2
5
 
3
6
  #