nandoc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +124 -0
- data/Rakefile +53 -0
- data/bin/nandoc +6 -0
- data/doc/CREDITS.md +6 -0
- data/doc/FAQ/why-not-wiki.md +20 -0
- data/doc/FAQ.md +68 -0
- data/doc/TODOs-and-BUGs.md +15 -0
- data/doc/bar/baz.md +4 -0
- data/doc/bar/bliff.md +8 -0
- data/doc/foo.md +5 -0
- data/doc/getting-started.rb +13 -0
- data/doc/svg/less-fonts.svg +21 -0
- data/lib/nandoc/commands/create-nandoc-site.rb +225 -0
- data/lib/nandoc/commands/diff.rb +279 -0
- data/lib/nandoc/config.rb +58 -0
- data/lib/nandoc/cri-hacks.rb +13 -0
- data/lib/nandoc/data-source.rb +239 -0
- data/lib/nandoc/filters.rb +661 -0
- data/lib/nandoc/helpers/menu-bouncy.rb +109 -0
- data/lib/nandoc/helpers/site-map.rb +157 -0
- data/lib/nandoc/helpers/top-nav.rb +47 -0
- data/lib/nandoc/helpers.rb +42 -0
- data/lib/nandoc/item-class-hacks.rb +57 -0
- data/lib/nandoc/nandoc.persistent.json +3 -0
- data/lib/nandoc/parse-readme.rb +95 -0
- data/lib/nandoc/spec-doc/mini-test/spec-instance-methods.rb +0 -0
- data/lib/nandoc/spec-doc/mini-test.rb +105 -0
- data/lib/nandoc/spec-doc/mock-prompt.rb +121 -0
- data/lib/nandoc/spec-doc/support-modules.rb +158 -0
- data/lib/nandoc/spec-doc/test-case-agent.rb +57 -0
- data/lib/nandoc/spec-doc/test-framework-dispatcher.rb +15 -0
- data/lib/nandoc/spec-doc/test-framework-proxy.rb +78 -0
- data/lib/nandoc/spec-doc.rb +46 -0
- data/lib/nandoc/support/diff-proxy.rb +113 -0
- data/lib/nandoc/support/orphanage.rb +77 -0
- data/lib/nandoc/support/path-tardo.rb +85 -0
- data/lib/nandoc/support/regexp-enhance.rb +76 -0
- data/lib/nandoc/support/site-diff.rb +46 -0
- data/lib/nandoc/support/site-merge.rb +62 -0
- data/lib/nandoc/support/site-methods.rb +69 -0
- data/lib/nandoc/support/stream-colorizer.rb +203 -0
- data/lib/nandoc/support-modules.rb +270 -0
- data/lib/nandoc/test/diff-to-string.rb +251 -0
- data/lib/nandoc/test/minitest-extlib.rb +53 -0
- data/lib/nandoc/treebis/NOGIT-DOCS/NEWS.md +5 -0
- data/lib/nandoc/treebis/NOGIT-README.md +65 -0
- data/lib/nandoc/treebis/nandoc.persistent.json +3 -0
- data/lib/nandoc.rb +48 -0
- data/proto/README.md +31 -0
- data/proto/default/Rakefile +1 -0
- data/proto/default/Rules +46 -0
- data/proto/default/config.yaml +57 -0
- data/proto/default/content/css/nanoc-dist-altered.css +213 -0
- data/proto/default/content/css/trollop-subset.css +116 -0
- data/proto/default/content/js/menu-bouncy.js +126 -0
- data/proto/default/content/stylesheet.css.diff +20 -0
- data/proto/default/content/vendor/jquery-1.3.js +4241 -0
- data/proto/default/content/vendor/jquery.easing.1.3.js +205 -0
- data/proto/default/layouts/default.html +70 -0
- data/proto/default/lib/default.orig.rb +2 -0
- data/proto/default/lib/default.rb +5 -0
- data/proto/default/treebis-task.rb +28 -0
- data/proto/misc/orphan-surrogate.md +6 -0
- data/test/test.rb +102 -0
- metadata +166 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
module NanDoc::Helpers::NanDocHelpers
|
2
|
+
|
3
|
+
#
|
4
|
+
# render topnav with one level of menu dropdows
|
5
|
+
# with buggy animated opening and closing.
|
6
|
+
#
|
7
|
+
# usage example:
|
8
|
+
# nandoc_menu_bouncy(binding) do |it|
|
9
|
+
# it.separator = These['❧']
|
10
|
+
# it.tabs = 4
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
def nandoc_menu_bouncy binding, &block
|
14
|
+
MenuBouncy.new(binding, &block).render
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
class MenuBouncy
|
21
|
+
include NanDoc::StringFormatting
|
22
|
+
def initialize(binding, &block)
|
23
|
+
@separator_default = '>'
|
24
|
+
@tab = ' '
|
25
|
+
@tabs = 0
|
26
|
+
@item = eval('@item', binding)
|
27
|
+
block.call(self)
|
28
|
+
end
|
29
|
+
attr_accessor :separator_default, :tab, :tabs
|
30
|
+
alias_method :separator=, :separator_default=
|
31
|
+
alias_method :separator, :separator_default
|
32
|
+
alias_method :menu_item_bullet_right, :separator_default
|
33
|
+
def render
|
34
|
+
item = @item
|
35
|
+
chunks = []
|
36
|
+
if item.nandoc_sorted_visible_children.any?
|
37
|
+
chunks.push render_branch(item)
|
38
|
+
else
|
39
|
+
chunks.push render_leaf(item)
|
40
|
+
end
|
41
|
+
while item = item.parent
|
42
|
+
chunks.push render_branch(item)
|
43
|
+
end
|
44
|
+
html = chunks.reverse.join('')
|
45
|
+
html2 = reindent html
|
46
|
+
html2.strip
|
47
|
+
end
|
48
|
+
private
|
49
|
+
def render_branch item
|
50
|
+
[
|
51
|
+
render_branch_label(item),
|
52
|
+
render_branch_sep_hack(item)
|
53
|
+
].join
|
54
|
+
end
|
55
|
+
def render_branch_label item
|
56
|
+
<<-H
|
57
|
+
<div class='nanoc-sidebar-h2 nandoc-menu-lvl-1'>
|
58
|
+
#{render_link_or_label(item)}
|
59
|
+
</div>
|
60
|
+
H
|
61
|
+
end
|
62
|
+
def render_branch_sep_hack item
|
63
|
+
lines = [<<-H
|
64
|
+
<div class='bouncy-lvl1-sep'>#{separator}
|
65
|
+
<div class='bouncy-lvl2-menu'>
|
66
|
+
H
|
67
|
+
]
|
68
|
+
cx = item.nandoc_sorted_visible_children
|
69
|
+
hh = cx.map{ |x| render_level_2_item(x) }
|
70
|
+
lines.concat hh
|
71
|
+
lines.push <<-H
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
H
|
75
|
+
lines.join
|
76
|
+
end
|
77
|
+
def render_level_2_item item
|
78
|
+
<<-H
|
79
|
+
<div class='bouncy-lvl2-item'>
|
80
|
+
<span class='bouncy-lvl2-content'>
|
81
|
+
#{render_link_or_label(item)}
|
82
|
+
</span>
|
83
|
+
<span class='bouncy-lvl2-sep'>#{menu_item_bullet_right}</span>
|
84
|
+
</div>
|
85
|
+
H
|
86
|
+
end
|
87
|
+
def render_label item
|
88
|
+
item.nandoc_title
|
89
|
+
end
|
90
|
+
def render_leaf item
|
91
|
+
<<-H
|
92
|
+
<div class='nanoc-sidebar-h2 nandoc-menu-lvl-1'>
|
93
|
+
#{render_label(item)}
|
94
|
+
</div>
|
95
|
+
H
|
96
|
+
end
|
97
|
+
def render_link_default item
|
98
|
+
"<a href='#{item.identifier}'>#{item.nandoc_title}</a>"
|
99
|
+
end
|
100
|
+
alias_method :render_link, :render_link_default
|
101
|
+
def render_link_or_label item
|
102
|
+
if item == @item
|
103
|
+
render_label item
|
104
|
+
else
|
105
|
+
render_link item
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module NanDoc::Helpers::NanDocHelpers
|
2
|
+
|
3
|
+
#
|
4
|
+
# @see default.html for example usage.
|
5
|
+
#
|
6
|
+
def nandoc_sitemap binding, name=nil, &block
|
7
|
+
name ||= SiteMap.next_unique_name
|
8
|
+
SiteMap.singleton(name, binding, &block).render_parent
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
class SiteMap
|
15
|
+
extend BlockAttrAccessor, NanDoc::SharedAttrReader
|
16
|
+
include NanDoc::SecretParent
|
17
|
+
module Glyphs; end # forward declaration
|
18
|
+
include Glyphs
|
19
|
+
@singletons = {}
|
20
|
+
@next_unique_name = -1
|
21
|
+
class << self
|
22
|
+
def next_unique_name
|
23
|
+
@next_unique_name += 1
|
24
|
+
@next_unique_name
|
25
|
+
end
|
26
|
+
def singleton(name, binding, &block)
|
27
|
+
@singletons[name] ||= begin
|
28
|
+
sing = new
|
29
|
+
sing.init_root(binding, &block)
|
30
|
+
sing
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
def initialize
|
35
|
+
@tab = ' '
|
36
|
+
end
|
37
|
+
attr_accessor :glyphs, :item, :is_first, :is_last,
|
38
|
+
:root_identifier, :tabs, :tab
|
39
|
+
attr_reader :level
|
40
|
+
block_attr_accessor :children, :render_child # defines *_proc
|
41
|
+
shared_attr_reader :children_proc, :glyphs, :tab, :render_child_proc,
|
42
|
+
:render_parent_proc # children will access root nodes's attrs for these
|
43
|
+
|
44
|
+
def init_root binding, &block
|
45
|
+
block.call(self)
|
46
|
+
@is_first = @is_last = true
|
47
|
+
@level = 0
|
48
|
+
@item = nil
|
49
|
+
@tabs ||= 0
|
50
|
+
root = eval('@items',binding).find{|x| x.identifier == root_identifier}
|
51
|
+
children_populate_recursive [root]
|
52
|
+
end
|
53
|
+
def init_child parent, item
|
54
|
+
self.parent = parent
|
55
|
+
@item = item
|
56
|
+
self.shared = parent.shared # this does a lot, see SharedAttrReader
|
57
|
+
@level = parent.level + 1
|
58
|
+
@tabs = parent.tabs + 1
|
59
|
+
cx = children_proc.call(@item)
|
60
|
+
children_populate_recursive cx
|
61
|
+
end
|
62
|
+
def children_populate_recursive cx
|
63
|
+
if cx.any? # keep our @children nil unless we have any children
|
64
|
+
last_idx = cx.size - 1
|
65
|
+
@children = cx.each.with_index.map do |item, idx|
|
66
|
+
map = self.class.new
|
67
|
+
map.is_first = idx == 0
|
68
|
+
map.is_last = idx == last_idx
|
69
|
+
map.init_child self, item
|
70
|
+
map
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def merge_opts opts
|
76
|
+
fail("just for setting tabs for now") unless opts.keys == [:tabs]
|
77
|
+
@tabs = opts[:tabs]
|
78
|
+
opts
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [String] <ul> for e.g. Sets block if given.
|
82
|
+
def render_parent &block
|
83
|
+
if block_given?
|
84
|
+
@render_parent_proc = block
|
85
|
+
class << self
|
86
|
+
attr_accessor :render_parent_proc
|
87
|
+
end
|
88
|
+
nil
|
89
|
+
elsif @children.nil?
|
90
|
+
nil
|
91
|
+
else
|
92
|
+
h1 = render_parent_proc.call(self)
|
93
|
+
h2 = reindent(h1).strip
|
94
|
+
h2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [String] chunk of <li's> for eg.
|
99
|
+
def render_children opts={}
|
100
|
+
these = @children.map do |map|
|
101
|
+
map.merge_opts opts
|
102
|
+
h1 = render_child_proc.call(map)
|
103
|
+
h2 = map.reindent(h1)
|
104
|
+
h3 = h2.strip
|
105
|
+
h3
|
106
|
+
end
|
107
|
+
last = @children.last
|
108
|
+
hz = these.join("\n" + last.tab * last.tabs) if last
|
109
|
+
hz
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
module SiteMap::Glyphs
|
114
|
+
# http://www.alanwood.net/unicode/box_drawing.html
|
115
|
+
Blank = ' '
|
116
|
+
DownLf = '┐' # ┐
|
117
|
+
DownRt = '┌' # ┌
|
118
|
+
HvVtLf = '┫' # ┫
|
119
|
+
HvVert = '┃' # ┃
|
120
|
+
UpLeft = '┘' # ┘
|
121
|
+
UpRite = '└' # └
|
122
|
+
Vertic = '│' # │
|
123
|
+
VertLf = '┤' # ┤
|
124
|
+
VertRt = '├' # ├
|
125
|
+
VtHori = '┼' # ┼
|
126
|
+
ArcUpL = '╯' # ╯
|
127
|
+
DashQV =' ┊' # ┊
|
128
|
+
|
129
|
+
UseThisForBlanks = proc{|node| DashQV }
|
130
|
+
# DashQV is nice b/c fixed width
|
131
|
+
|
132
|
+
def glyphs_right_for_child
|
133
|
+
@glyphs_right_for_child ||= begin
|
134
|
+
case level
|
135
|
+
when 0; [] # e.g. the object that is rendering [home]
|
136
|
+
when 1; [] # e.g. home, the (lvl2) children have no inheirited
|
137
|
+
else
|
138
|
+
x = [ is_last ? UseThisForBlanks.call(self) : HvVert ]
|
139
|
+
x.concat(parent.glyphs_right_for_child) if parent
|
140
|
+
x
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def glyphs_right
|
146
|
+
case level
|
147
|
+
when 0; fail('never')
|
148
|
+
when 1; ''
|
149
|
+
else
|
150
|
+
these = [ is_last ? ArcUpL : HvVtLf ]
|
151
|
+
these.concat( parent.glyphs_right_for_child ) if parent
|
152
|
+
# these.concat Array.new([0, level-1].max, DashQV)
|
153
|
+
these.join('')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module NanDoc::Helpers::NanDocHelpers
|
2
|
+
|
3
|
+
#
|
4
|
+
# nandoc_topnav do |sm|
|
5
|
+
# sm.binding = binding
|
6
|
+
# sm.item { |i| <<-H
|
7
|
+
# <span class='nanoc-sidebar-h2'>#{i.nandoc_title}</span>
|
8
|
+
# H
|
9
|
+
# }
|
10
|
+
# sm.current_item { |i| <<-H
|
11
|
+
# <span class='nanoc-sidebar-h2'>#{i.nandoc_title}</span>
|
12
|
+
# H
|
13
|
+
# }
|
14
|
+
# sm.separator { <<-H
|
15
|
+
# <span class='nanoc-sep'>❧</span>
|
16
|
+
# H
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
|
20
|
+
def nandoc_topnav &block
|
21
|
+
TopNav.new(&block).render
|
22
|
+
end
|
23
|
+
|
24
|
+
class TopNav
|
25
|
+
extend BlockAttrAccessor
|
26
|
+
def initialize(&b)
|
27
|
+
block_attr_accessor_init
|
28
|
+
@current_item = @items = @item = nil
|
29
|
+
b.call(self)
|
30
|
+
end
|
31
|
+
block_attr_accessor :current_item, :item, :separator
|
32
|
+
attr_accessor :binding
|
33
|
+
def render
|
34
|
+
item = eval('@item', @binding)
|
35
|
+
temdoz = [@current_item_proc.call(item)]
|
36
|
+
while item = item.parent
|
37
|
+
temdoz.concat [@separator_proc.call, @item_proc.call(item)]
|
38
|
+
end
|
39
|
+
temdoz.reverse
|
40
|
+
end
|
41
|
+
class << self
|
42
|
+
def home_page &b
|
43
|
+
@home_page ||= b.call
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module NanDoc::Helpers
|
2
|
+
module NanDocHelpers
|
3
|
+
# @todo-now test this
|
4
|
+
include NanDoc::StringFormatting # indent() unindent() no_blank_lines()
|
5
|
+
module BlockAttrAccessor
|
6
|
+
attr_accessor :block_attr_accessors
|
7
|
+
class << self
|
8
|
+
def extended mod
|
9
|
+
mod.instance_variable_set('@block_attr_accessors', []) unless
|
10
|
+
mod.instance_variable_defined?('@block_attr_accessors')
|
11
|
+
mod.send(:define_method, :block_attr_accessor_init) do
|
12
|
+
self.class.block_attr_accessors.each do |name|
|
13
|
+
instance_variable_set("@#{name}_proc",nil) unless
|
14
|
+
instance_variable_defined?("@#{name}_proc")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
def block_attr_accessor *names
|
20
|
+
names.each do |setter_name|
|
21
|
+
@block_attr_accessors.push(setter_name) # etc
|
22
|
+
attr_name = "@#{setter_name}_proc"
|
23
|
+
getter_name = "#{setter_name}_proc"
|
24
|
+
define_method(setter_name) do |&block|
|
25
|
+
raise ArgumentError.new(
|
26
|
+
"no block given for #{self.class}##{setter_name}"
|
27
|
+
) unless block
|
28
|
+
instance_variable_set attr_name, block
|
29
|
+
end
|
30
|
+
define_method(getter_name) do
|
31
|
+
instance_variable_get attr_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
here = File.dirname(__FILE__)+'/helpers'
|
40
|
+
require here + '/menu-bouncy.rb'
|
41
|
+
require here + '/site-map.rb'
|
42
|
+
require here + '/top-nav.rb'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Nanoc3::Item
|
2
|
+
#
|
3
|
+
# hacks we use for stuff like sitemap and topnav generation
|
4
|
+
#
|
5
|
+
class << self
|
6
|
+
def sorted_visible_children
|
7
|
+
@svc ||= begin
|
8
|
+
proc do |node|
|
9
|
+
node.children.select{|c| c.nandoc_visible? }.sort_by(&:nandoc_title)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
include NanDoc::StringFormatting # basename_no_extension()
|
17
|
+
|
18
|
+
attr_accessor :identifier # know what you are doing if you set it
|
19
|
+
|
20
|
+
#
|
21
|
+
# come up with some title by any means necessary
|
22
|
+
#
|
23
|
+
def nandoc_title
|
24
|
+
if @attributes[:title]
|
25
|
+
@attributes[:title]
|
26
|
+
elsif ! nandoc_content_node?
|
27
|
+
identifier
|
28
|
+
elsif no_ext = basename_no_extension(@attributes[:content_filename])
|
29
|
+
no_ext.gsub(/[-_]/, ' ') # we could do wiki-name like crap
|
30
|
+
elsif ! (foo = File.basename(@attributes[:content_filename])).empty?
|
31
|
+
foo
|
32
|
+
else
|
33
|
+
identifier == '/' ? 'HOME' : identifier.gsub('/',' - ')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def nandoc_content_node?
|
38
|
+
/\A\/(?:css|js|vendor)\// !~ identifier # @todo will have to change!
|
39
|
+
end
|
40
|
+
|
41
|
+
def nandoc_content_leaf?
|
42
|
+
nandoc_content_node? # hm
|
43
|
+
end
|
44
|
+
|
45
|
+
def nandoc_content_branch?
|
46
|
+
false # hm
|
47
|
+
end
|
48
|
+
|
49
|
+
def nandoc_sorted_visible_children
|
50
|
+
self.class.sorted_visible_children.call(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def nandoc_visible?
|
54
|
+
!self[:hidden] && path && nandoc_content_node?
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module NanDoc
|
2
|
+
class ParseReadme
|
3
|
+
#
|
4
|
+
# If you are really really crazy then you don't like
|
5
|
+
# repeating yourself between your gemspec and your README with regard to
|
6
|
+
# the project summary and description.
|
7
|
+
#
|
8
|
+
# This is a quick and dirty hack to parse your README (or similary
|
9
|
+
# formatted file) in a really rough way for when you are building your
|
10
|
+
# gemspec -- it doesn't use a markdown parser or whatever. It scans the
|
11
|
+
# README file for a line like "## Summary" and reads the next line with
|
12
|
+
# content after it. (ditto "## Description" etc.)
|
13
|
+
#
|
14
|
+
# See the Rakefile of this project for example usage.
|
15
|
+
#
|
16
|
+
# @see note below near 'jeweler'
|
17
|
+
#
|
18
|
+
|
19
|
+
def initialize(path=nil, &block)
|
20
|
+
@parsed_content = {}
|
21
|
+
@lines = nil
|
22
|
+
@path = path and get_lines!
|
23
|
+
instance_eval(&block) if block_given?
|
24
|
+
end
|
25
|
+
class << self
|
26
|
+
alias_method :parse, :new
|
27
|
+
def description file
|
28
|
+
DeferredParse.new(file, :description)
|
29
|
+
end
|
30
|
+
def summary file
|
31
|
+
DeferredParse.new(file, :summary)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
attr_accessor :lines
|
35
|
+
def path name
|
36
|
+
@path = name
|
37
|
+
get_lines!
|
38
|
+
name
|
39
|
+
end
|
40
|
+
def parse_section *names
|
41
|
+
names.each do |name|
|
42
|
+
re = /\A#* ?#{Regexp.escape(name.to_s)}\Z/i
|
43
|
+
idx = (@lines.index{|x| re =~ x } or
|
44
|
+
fail("#{name.to_s.inspect} section not found in #{path}")) + 1
|
45
|
+
idx += 1 while @lines[idx] && /\A[[:space:]]+\Z/ =~ @lines[idx]
|
46
|
+
line = @lines[idx] or
|
47
|
+
fail("couldn't find content following #{name.to_s} section")
|
48
|
+
@parsed_content[name] = line.strip
|
49
|
+
class << self; self end.send(:define_method, name) do
|
50
|
+
@parsed_content[name]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
alias_method :parse_sections, :parse_section
|
56
|
+
private
|
57
|
+
def get_lines!
|
58
|
+
@lines = File.open(@path).lines.map
|
59
|
+
end
|
60
|
+
class DeferredParse
|
61
|
+
#
|
62
|
+
# This whole thing is a ridiculously fragile and secret hack
|
63
|
+
# that is maybe pointless @todo
|
64
|
+
# The point is to defer opening and parsing the README file unless
|
65
|
+
# necessary. (But it didn't work as intended, but no big deal.)
|
66
|
+
#
|
67
|
+
# If you use it is is recommended that you use jeweler and the
|
68
|
+
# gemspec:debug task to check its work.
|
69
|
+
#
|
70
|
+
|
71
|
+
@files = {}
|
72
|
+
class << self
|
73
|
+
attr_reader :files
|
74
|
+
end
|
75
|
+
def initialize path, section
|
76
|
+
@path, @section = path, section
|
77
|
+
@as_string = nil
|
78
|
+
end
|
79
|
+
def strip
|
80
|
+
as_string.strip
|
81
|
+
end
|
82
|
+
def to_s
|
83
|
+
as_string # can't simply alias it b/c it is private
|
84
|
+
end
|
85
|
+
private
|
86
|
+
def as_string
|
87
|
+
@as_string ||= begin
|
88
|
+
parse = (self.class.files[@path] ||= ParseReadme.new(@path))
|
89
|
+
parse.parse_section(@section) unless parse.respond_to?(@section)
|
90
|
+
parse.send(@section)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
File without changes
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require File.expand_path('../../test/minitest-extlib.rb', __FILE__)
|
3
|
+
|
4
|
+
module NanDoc::SpecDoc::MiniTest
|
5
|
+
class Proxy < ::NanDoc::SpecDoc::TestFrameworkProxy
|
6
|
+
|
7
|
+
def initialize(*a)
|
8
|
+
super(*a)
|
9
|
+
@hacked_minitest = false
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
#
|
15
|
+
# given
|
16
|
+
# @param [String] the natural sounding string name as it appears in
|
17
|
+
# documentation,
|
18
|
+
# @return [Array] a pair of strings: suite name and method name
|
19
|
+
#
|
20
|
+
def find_test str
|
21
|
+
meth_tail = str.gsub(/\W+/, '_').downcase
|
22
|
+
# i *think* we want *not* to escape it below
|
23
|
+
filter = /\Atest_\d{4}_#{meth_tail}\Z/
|
24
|
+
found_meths = []
|
25
|
+
found_pairs = []
|
26
|
+
::MiniTest::Unit::TestCase.test_suites.each do |suite|
|
27
|
+
if (foundfound = suite.test_methods.grep(filter)).any?
|
28
|
+
found_pairs.push [suite, foundfound]
|
29
|
+
found_meths.concat foundfound
|
30
|
+
end
|
31
|
+
end
|
32
|
+
case found_meths.size
|
33
|
+
when 0;
|
34
|
+
fail("no tests were found whose name matches the pattern #{filter}")
|
35
|
+
when 1;
|
36
|
+
ff = found_pairs.first
|
37
|
+
[ff[0], ff[1][0]] # suite and method name
|
38
|
+
else
|
39
|
+
fail("found more than one test matching the pattern for \"#{str}\""<<
|
40
|
+
" -- (#{found_meths.join(', ')})")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# do whatever you have to do to prepare minitest to run nandoc-enabled
|
46
|
+
# tests
|
47
|
+
#
|
48
|
+
def hack_minitest
|
49
|
+
return if @hacked_minitest
|
50
|
+
@testout = StringIO.new
|
51
|
+
::MiniTest::Unit.output = @testout
|
52
|
+
# this is set but ignored which is ok. it gets method names and dots
|
53
|
+
sing = class << ::MiniTest::Unit; self end
|
54
|
+
sing.send(:define_method, :autorun){ } # override it to do nothing!!
|
55
|
+
@hacked_minitest = true
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# given
|
60
|
+
# @param [String] testfile name (just semantic not formal)
|
61
|
+
# @param [String] testname (just semantic not formal)
|
62
|
+
# @param [String] a test case name and
|
63
|
+
# @param [String] a method name,
|
64
|
+
# run the test in question which will hopefully write to the recordings
|
65
|
+
# experimentally
|
66
|
+
# @return an exit status of 0 if everything's ok
|
67
|
+
#
|
68
|
+
def run_test_case_method testfile, testname, test_case, meth_name
|
69
|
+
hack_minitest unless @hacked_minitest
|
70
|
+
unambig_re = /\A#{Regexp.escape(meth_name)}\Z/
|
71
|
+
runner = ::MiniTest::Unit.new
|
72
|
+
runner.instance_variable_set('@verbose', true)
|
73
|
+
test_count, ass_count = runner.run_test_suites unambig_re
|
74
|
+
fail("didn't run any tests for #{unambig_re.source}") unless
|
75
|
+
test_count == 1
|
76
|
+
if runner.report.any?
|
77
|
+
return handle_failed_tests(runner, testfile, testname)
|
78
|
+
end
|
79
|
+
return 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
#
|
85
|
+
# These are the methods that will be available to nandoc-enhanced tests.
|
86
|
+
# For now it is recommended to leave this as just the one method nandoc(),
|
87
|
+
# which will return the TestCaseAgent.
|
88
|
+
#
|
89
|
+
module SpecInstanceMethods
|
90
|
+
class << self
|
91
|
+
def include_to mod
|
92
|
+
unless mod.ancestors.include?(::MiniTest::Spec)
|
93
|
+
fail(
|
94
|
+
"Sorry, for now SpecDoc can only extend MiniTest::Spec "<<
|
95
|
+
" tests. Couldn't extend #{mod}."
|
96
|
+
)
|
97
|
+
end
|
98
|
+
mod.send(:include, self)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
def nandoc
|
102
|
+
@nandoc_agent ||= ::NanDoc::SpecDoc::TestCaseAgent.new(self)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|