nandoc 0.0.3 → 0.0.4

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 (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
  #