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.
- data/README +5 -4
- data/Rakefile +1 -1
- data/bin/nandoc +2 -1
- data/doc/FAQ.md +3 -0
- data/doc/PROVISO.md +39 -0
- data/doc/commands/diff.md +49 -0
- data/doc/svg/less-fonts.svg +2 -2
- data/lib/nandoc/cli/README.md +6 -0
- data/lib/nandoc/cli/command-methods.rb +38 -0
- data/lib/nandoc/cli/option-methods/exclusive-options.rb +56 -0
- data/lib/nandoc/cli/option-methods/option-enum.rb +64 -0
- data/lib/nandoc/cli/option-methods.rb +35 -0
- data/lib/nandoc/cli.rb +3 -0
- data/lib/nandoc/commands/create-nandoc-site.rb +9 -12
- data/lib/nandoc/commands/diff.rb +14 -11
- data/lib/nandoc/commands.rb +9 -0
- data/lib/nandoc/{config.rb → core/config.rb} +18 -9
- data/lib/nandoc/core/project.rb +50 -0
- data/lib/nandoc/doc/hack-free-zone-defined.md +33 -0
- data/lib/nandoc/erb/agent.rb +5 -5
- data/lib/nandoc/{test/minitest-extlib.rb → extlib/minitest.rb} +1 -1
- data/lib/nandoc/filters/builtin-tags/fence/terminal.rb +24 -0
- data/lib/nandoc/filters/builtin-tags/fence-dispatcher.rb +43 -0
- data/lib/nandoc/filters/builtin-tags/fences.rb +4 -0
- data/lib/nandoc/filters/builtin-tags/see-test.rb +67 -0
- data/lib/nandoc/filters/builtin-tags.rb +11 -0
- data/lib/nandoc/filters/custom-tag.rb +43 -0
- data/lib/nandoc/filters/custom-tags.rb +19 -0
- data/lib/nandoc/filters/tag-parse-instance-methods.rb +11 -0
- data/lib/nandoc/filters/tag-parser.rb +206 -0
- data/lib/nandoc/filters.rb +11 -585
- data/lib/nandoc/{cri-hacks.rb → hacks/cri-hacks.rb} +4 -3
- data/lib/nandoc/{data-source.rb → hacks/data-source.rb} +5 -4
- data/lib/nandoc/{item-class-hacks.rb → hacks/item-class-hacks.rb} +3 -1
- data/lib/nandoc/hacks.rb +6 -0
- data/lib/nandoc/helpers/menu-bouncy.rb +1 -1
- data/lib/nandoc/helpers/site-map.rb +3 -0
- data/lib/nandoc/helpers.rb +1 -1
- data/lib/nandoc/html/tags.rb +65 -0
- data/lib/nandoc/html.rb +6 -0
- data/lib/nandoc/parse-readme.rb +4 -0
- data/lib/nandoc/spec-doc/agent-instance-methods.rb +24 -0
- data/lib/nandoc/spec-doc/code-snippet.rb +59 -0
- data/lib/nandoc/spec-doc/generic-agent.rb +40 -0
- data/lib/nandoc/spec-doc/mock-prompt.rb +3 -9
- data/lib/nandoc/spec-doc/parse-trace.rb +25 -0
- data/lib/nandoc/spec-doc/{mini-test/spec-instance-methods.rb → playback/html/foo-bar.rb} +0 -0
- data/lib/nandoc/spec-doc/playback/html.rb +2 -0
- data/lib/nandoc/spec-doc/playback/players/method.rb +64 -0
- data/lib/nandoc/spec-doc/playback/players/ruby.rb +158 -0
- data/lib/nandoc/spec-doc/playback/players/terminal.rb +93 -0
- data/lib/nandoc/spec-doc/playback/players.rb +4 -0
- data/lib/nandoc/spec-doc/playback/support/playback-methods.rb +44 -0
- data/lib/nandoc/spec-doc/playback/support/sexp-scanner.rb +61 -0
- data/lib/nandoc/spec-doc/playback/support.rb +3 -0
- data/lib/nandoc/spec-doc/playback/terminal/color-to-html.rb +100 -0
- data/lib/nandoc/spec-doc/playback.rb +3 -0
- data/lib/nandoc/spec-doc/recordings.rb +55 -0
- data/lib/nandoc/spec-doc/ruby2ruby-standin.rb +37 -0
- data/lib/nandoc/spec-doc/test-case-agent.rb +1 -1
- data/lib/nandoc/spec-doc/{mini-test.rb → test-framework/mini-test/proxy.rb} +9 -31
- data/lib/nandoc/spec-doc/{test-framework-proxy.rb → test-framework/proxy.rb} +27 -50
- data/lib/nandoc/spec-doc.rb +57 -13
- data/lib/nandoc/{test → support}/diff-to-string.rb +0 -0
- data/lib/nandoc/support/regexp-enhance.rb +6 -0
- data/lib/nandoc/support/regexp.rb +12 -0
- data/lib/nandoc/support/secret-parent.rb +21 -0
- data/lib/nandoc/support/shared-attr-reader.rb +32 -0
- data/lib/nandoc/support/site-merge.rb +1 -1
- data/lib/nandoc/support/site-methods.rb +4 -4
- data/lib/nandoc/support/stream-colorizer.rb +1 -1
- data/lib/nandoc/support/string-methods.rb +56 -0
- data/lib/nandoc.rb +12 -35
- data/proto/README.md +4 -2
- data/test/test.rb +1 -0
- metadata +58 -25
- data/doc/bar/baz.md +0 -4
- data/doc/bar/bliff.md +0 -8
- data/doc/foo.md +0 -5
- data/doc/getting-started.rb +0 -13
- data/lib/nandoc/spec-doc/support-modules.rb +0 -158
- data/lib/nandoc/spec-doc/test-framework-dispatcher.rb +0 -15
- data/lib/nandoc/support-modules.rb +0 -273
- data/lib/nandoc/treebis/NOGIT-DOCS/NEWS.md +0 -5
- data/lib/nandoc/treebis/NOGIT-README.md +0 -65
- data/lib/nandoc/treebis/nandoc.persistent.json +0 -3
data/lib/nandoc/filters.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
|
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
|
-
|
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
|
-
|
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 ', "ed) <<
|
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,"ed)
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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::
|
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
|
|
data/lib/nandoc/hacks.rb
ADDED