docubot 0.3.3 → 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/bin/docubot +5 -1
- data/lib/docubot.rb +4 -2
- data/lib/docubot/bundle.rb +109 -61
- data/lib/docubot/converter.rb +4 -1
- data/lib/docubot/converters/haml.rb +1 -1
- data/lib/docubot/glossary.rb +3 -0
- data/lib/docubot/link_tree.rb +109 -0
- data/lib/docubot/metasection.rb +61 -0
- data/lib/docubot/page.rb +40 -118
- data/lib/docubot/shells/docubot-help/3_Advanced_Topics/Controlling the Table of Contents.md +2 -4
- data/lib/docubot/shells/nvphysx/_templates/_root/common.css +10 -5
- data/lib/docubot/shells/nvphysx/_templates/_root/glossary.css +1 -0
- data/lib/docubot/shells/nvphysx/_templates/_root/glossary.js +11 -1
- data/lib/docubot/shells/nvphysx/_templates/section.haml +9 -0
- data/lib/docubot/templates/index.haml +13 -20
- data/lib/docubot/templates/section.haml +1 -4
- data/lib/docubot/templates/toc.haml +2 -11
- data/lib/docubot/templates/top.haml +7 -4
- data/lib/docubot/writers/chm.rb +6 -5
- data/lib/docubot/writers/chm/hhc.erb +35 -12
- data/lib/docubot/writers/chm/hhk.erb +1 -1
- data/lib/docubot/writers/chm/hhp.erb +2 -2
- data/lib/docubot/writers/html.rb +33 -23
- data/spec/_all.rb +1 -0
- data/spec/_helper.rb +10 -0
- data/spec/bundle.rb +193 -2
- data/spec/global.rb +28 -0
- data/spec/glossary.rb +13 -11
- data/spec/page.rb +35 -9
- data/spec/samples/attributes/defaults.haml +34 -0
- data/spec/samples/attributes/explicit1.haml +43 -0
- data/spec/samples/attributes/explicit2.haml +42 -0
- data/spec/samples/attributes/hidden.haml +40 -0
- data/spec/samples/attributes/index.md +8 -0
- data/spec/samples/collisions/page1.md +3 -0
- data/spec/samples/collisions/page1.textile +3 -0
- data/spec/samples/collisions/page2.haml +4 -0
- data/spec/samples/collisions/page2.html +3 -0
- data/spec/samples/collisions/page2.txt +3 -0
- data/spec/samples/collisions/page3.bin +1 -0
- data/spec/samples/collisions/page3.md +3 -0
- data/spec/samples/{link_test/sub2/bozo.bin → files/BUILDING.txt} +0 -0
- data/spec/samples/{titletest/1 First One.txt → files/_static/Thumbs.db} +0 -0
- data/spec/samples/{titletest/2_Second_One.txt → files/_static/foo.ai} +0 -0
- data/spec/samples/{titletest/4 Fourth_One.txt → files/_static/foo.png} +0 -0
- data/spec/samples/{titletest/5_Fifth One.txt → files/_static/foo.psd} +0 -0
- data/spec/samples/files/another.md +0 -0
- data/spec/samples/files/common.css +0 -0
- data/spec/samples/files/first.textile +0 -0
- data/spec/samples/files/index.md +2 -0
- data/spec/samples/files/section/foo.jpg +0 -0
- data/spec/samples/files/section/page.haml +0 -0
- data/spec/samples/files/section/sub section/Thumbs.db b/data/spec/samples/files/section/sub → section/Thumbs.db +0 -0
- data/spec/samples/files/section/sub section/foo.gif b/data/spec/samples/files/section/sub → section/foo.gif +0 -0
- data/spec/samples/files/section/sub section/page.txt b/data/spec/samples/files/section/sub → section/page.txt +0 -0
- data/spec/samples/{link_test → links}/index.txt +0 -0
- data/spec/samples/{link_test → links}/root.md +0 -0
- data/spec/samples/{link_test → links}/sub1/inner1.md +0 -0
- data/spec/samples/{link_test → links}/sub2.md +0 -0
- data/spec/samples/links/sub2/bozo.bin +0 -0
- data/spec/samples/{link_test → links}/sub2/inner2.md +0 -0
- data/spec/samples/templates/_templates/404.haml +1 -0
- data/spec/samples/templates/_templates/doubler.haml +7 -0
- data/spec/samples/templates/_templates/page.haml +2 -0
- data/spec/samples/templates/goaway.txt +3 -0
- data/spec/samples/templates/onepara_html.html +3 -0
- data/spec/samples/templates/onepara_md.md +5 -0
- data/spec/samples/templates/twopara_haml.haml +7 -0
- data/spec/samples/templates/twopara_textile.textile +6 -0
- data/spec/samples/titles/1 First One.txt b/data/spec/samples/titles/1 First → One.txt +0 -0
- data/spec/samples/titles/2_Second_One.txt +0 -0
- data/spec/samples/{titletest → titles}/3_renamed.txt +0 -0
- data/spec/samples/titles/4 Fourth_One.txt b/data/spec/samples/titles/4 → Fourth_One.txt +0 -0
- data/spec/samples/titles/5_Fifth One.txt b/data/spec/samples/titles/5_Fifth → One.txt +0 -0
- data/spec/samples/titles/911.txt +0 -0
- data/spec/samples/titles/index.txt +2 -0
- data/spec/templates.rb +42 -0
- data/spec/toc.rb +64 -30
- metadata +53 -14
- data/spec/samples/titletest/index.txt +0 -2
@@ -3,22 +3,45 @@
|
|
3
3
|
<HEAD>
|
4
4
|
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
|
5
5
|
<!-- Sitemap 1.0 -->
|
6
|
-
|
6
|
+
<%
|
7
|
+
ICON = {
|
8
|
+
:book => 1,
|
9
|
+
:folder => 5,
|
10
|
+
:question => 9,
|
11
|
+
:page => 11,
|
12
|
+
:internet => 13,
|
13
|
+
:info => 17,
|
14
|
+
:shortcut => 19,
|
15
|
+
:letter => 23,
|
16
|
+
:attachment => 25,
|
17
|
+
:contact => 27,
|
18
|
+
:sound => 29,
|
19
|
+
:cd => 31,
|
20
|
+
:movie => 33,
|
21
|
+
:list => 35,
|
22
|
+
:idea => 37,
|
23
|
+
:note => 39,
|
24
|
+
:tool => 41
|
25
|
+
}
|
26
|
+
|
27
|
+
@write_section = lambda do |node|
|
28
|
+
%>
|
7
29
|
<UL>
|
8
|
-
<%
|
9
|
-
|
30
|
+
<%node.children.each do |child|
|
31
|
+
icon = if child.anchor
|
32
|
+
ICON[:info]
|
33
|
+
elsif child.page.icon
|
34
|
+
ICON[ child.page.icon.downcase.to_sym ] || child.page.icon
|
35
|
+
else
|
36
|
+
child.leaf? ? ICON[:page] : ICON[:book]
|
37
|
+
end
|
38
|
+
%>
|
10
39
|
<LI> <OBJECT type="text/sitemap">
|
11
40
|
<param name="Name" value="<%=CGI.escapeHTML child.title%>">
|
12
|
-
<param name="Local" value="<%=FileUtils.win_path( @html_path / child.
|
13
|
-
|
14
|
-
%><param name="ImageNumber" value="<%=child.icon%>"><%
|
15
|
-
elsif child.sublink?
|
16
|
-
%><param name="ImageNumber" value="17"><%
|
17
|
-
elsif child.leaf?
|
18
|
-
%><param name="ImageNumber" value="11"><%
|
19
|
-
end%>
|
41
|
+
<param name="Local" value="<%=FileUtils.win_path( @html_path / child.link ).gsub('&','%26')%>">
|
42
|
+
<param name="ImageNumber" value="<%=icon%>">
|
20
43
|
</OBJECT>
|
21
|
-
<%@write_section[child] unless child.
|
44
|
+
<%@write_section[child] unless child.children.empty?%>
|
22
45
|
<%end%>
|
23
46
|
</UL>
|
24
47
|
<%end%>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<param name="FrameName" value="right">
|
9
9
|
</OBJECT>
|
10
10
|
<UL>
|
11
|
-
<%@
|
11
|
+
<%@global.index.each do |entry,pages|%>
|
12
12
|
<LI> <OBJECT type="text/sitemap">
|
13
13
|
<param name="Name" value="<%=entry%>">
|
14
14
|
<param name="Local" value="<%=FileUtils.win_path( @html_path/pages.first.html_path )%>">
|
@@ -7,11 +7,11 @@ Index file="<%=FileUtils.win_path @hhk%>"
|
|
7
7
|
<%end%>Display compile progress=No
|
8
8
|
Full-text search=Yes
|
9
9
|
Language=0x409 English (United States)
|
10
|
-
Title=<%=@
|
10
|
+
Title=<%=@global.title%>
|
11
11
|
|
12
12
|
|
13
13
|
[FILES]
|
14
|
-
<%@
|
14
|
+
<%@bundle.pages.each do |page|
|
15
15
|
%><%=FileUtils.win_path( @html_path/page.html_path) %>
|
16
16
|
<%end
|
17
17
|
@bundle.extras.each do |file|
|
data/lib/docubot/writers/html.rb
CHANGED
@@ -12,6 +12,8 @@ class DocuBot::HTMLWriter < DocuBot::Writer
|
|
12
12
|
|
13
13
|
master_templates = DocuBot::TEMPLATE_DIR
|
14
14
|
source_templates = source/'_templates'
|
15
|
+
master_root = master_templates/'_root'
|
16
|
+
source_root = source_templates/'_root'
|
15
17
|
|
16
18
|
# Copy any files found in the source directory that weren't made into pages
|
17
19
|
@bundle.extras.each do |file|
|
@@ -33,26 +35,34 @@ class DocuBot::HTMLWriter < DocuBot::Writer
|
|
33
35
|
o = Object.new
|
34
36
|
|
35
37
|
# Write out every page
|
36
|
-
|
37
|
-
|
38
|
-
@bundle.toc.descendants.each do |
|
39
|
-
next if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
FileUtils.mkdir_p( File.dirname( page.html_path ) )
|
44
|
-
File.open( page.html_path, 'w' ){ |f| f << html }
|
45
|
-
end
|
38
|
+
top = File.exists?( source_templates/'top.haml' ) ? source_templates/'top.haml' : master_templates/'top.haml'
|
39
|
+
top = Haml::Engine.new( IO.read( top ), HAML_OPTIONS )
|
40
|
+
@bundle.toc.descendants.each do |node|
|
41
|
+
next if node.anchor
|
42
|
+
|
43
|
+
contents = node.page.to_html
|
44
|
+
template = node.page.template # Call page.to_html first to ensure page.template is set
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
custom_js = "#{template}.js"
|
47
|
+
custom_js = nil unless File.exists?( source_root/custom_js ) || File.exists?( master_root/custom_js )
|
48
|
+
|
49
|
+
custom_css = "#{template}.css"
|
50
|
+
custom_css = nil unless File.exists?( source_root/custom_css ) || File.exists?( master_root/custom_css )
|
51
|
+
|
52
|
+
variables = {
|
53
|
+
:page => node.page,
|
54
|
+
:contents => contents,
|
55
|
+
:global => @bundle.global,
|
56
|
+
:root => node.root,
|
57
|
+
:breadcrumb => node.ancestors,
|
58
|
+
:custom_js => custom_js,
|
59
|
+
:custom_css => custom_css
|
60
|
+
}
|
61
|
+
html = top.render( o, variables )
|
62
|
+
FileUtils.mkdir_p( File.dirname( node.file ) )
|
63
|
+
File.open( node.file, 'w' ){ |f| f << html }
|
54
64
|
end
|
55
|
-
|
65
|
+
|
56
66
|
File.open( 'glossary-terms.js', 'w' ){ |f| f << @bundle.glossary.to_js }
|
57
67
|
end
|
58
68
|
|
@@ -61,13 +71,13 @@ class DocuBot::HTMLWriter < DocuBot::Writer
|
|
61
71
|
end
|
62
72
|
|
63
73
|
module Haml::Helpers
|
64
|
-
def li_pages_for(
|
65
|
-
|
66
|
-
haml_tag :li do
|
67
|
-
haml_tag :a, :href=>child.
|
74
|
+
def li_pages_for( node )
|
75
|
+
node.children.each do |child|
|
76
|
+
haml_tag :li, :class=>(child.anchor ? 'sublink' : child.children.empty? ? 'section' : 'page' ) do
|
77
|
+
haml_tag :a, :href=>child.link do
|
68
78
|
haml_concat child.title
|
69
79
|
end
|
70
|
-
unless child.
|
80
|
+
unless child.children.empty?
|
71
81
|
haml_tag :ul do
|
72
82
|
li_pages_for child
|
73
83
|
end
|
data/spec/_all.rb
CHANGED
data/spec/_helper.rb
CHANGED
@@ -4,3 +4,13 @@ require 'minitest/spec'
|
|
4
4
|
require 'docubot'
|
5
5
|
SAMPLES = File.dirname(__FILE__)/'samples'
|
6
6
|
MiniTest::Unit.autorun
|
7
|
+
|
8
|
+
class MiniTest::Spec
|
9
|
+
class << self
|
10
|
+
alias_method :__it__, :it
|
11
|
+
end
|
12
|
+
def self.it desc, &block
|
13
|
+
block ||= proc{ skip "(no tests defined)" }
|
14
|
+
__it__( desc, &block )
|
15
|
+
end
|
16
|
+
end
|
data/spec/bundle.rb
CHANGED
@@ -18,7 +18,7 @@ describe "Bundle from empty directory" do
|
|
18
18
|
|
19
19
|
it "should have an empty TOC" do
|
20
20
|
@bundle.toc.wont_be_nil
|
21
|
-
@bundle.toc.
|
21
|
+
@bundle.toc.descendants.must_be_empty
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should have an empty index" do
|
@@ -61,7 +61,7 @@ end
|
|
61
61
|
describe "Gathering links" do
|
62
62
|
before do
|
63
63
|
@out, @err = capture_io do
|
64
|
-
@bundle = DocuBot::Bundle.new SAMPLES/'
|
64
|
+
@bundle = DocuBot::Bundle.new SAMPLES/'links'
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -140,3 +140,194 @@ describe "Gathering links" do
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
end
|
143
|
+
|
144
|
+
describe "Identifying Conflicts" do
|
145
|
+
it "should raise when multiple pages will write to the same html" do
|
146
|
+
proc{
|
147
|
+
@bundle = DocuBot::Bundle.new( SAMPLES/'collisions' )
|
148
|
+
}.must_raise(DocuBot::Bundle::PageCollision)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should include the title and filename of every conflicting page" do
|
152
|
+
begin
|
153
|
+
@bundle = DocuBot::Bundle.new( SAMPLES/'collisions' )
|
154
|
+
rescue DocuBot::Bundle::PageCollision => e
|
155
|
+
e.message.must_include "page1.md"
|
156
|
+
e.message.must_include "page1.textile"
|
157
|
+
e.message.must_include "Page 1 (from Markdown)"
|
158
|
+
e.message.must_include "Page 1 (from Textile)"
|
159
|
+
e.message.must_include "page2.html"
|
160
|
+
e.message.must_include "page2.txt"
|
161
|
+
e.message.must_include "page2.haml"
|
162
|
+
e.message.must_include "Page 2 (from html)"
|
163
|
+
e.message.must_include "Page 2 (from text)"
|
164
|
+
e.message.must_include "Page 2 (from haml)"
|
165
|
+
e.message.wont_include "page3.md"
|
166
|
+
e.message.wont_include "page3.bin"
|
167
|
+
e.message.wont_include "Page 3"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "Bundle with Extra Files" do
|
174
|
+
before do
|
175
|
+
@out, @err = capture_io do
|
176
|
+
@bundle = DocuBot::Bundle.new( SAMPLES/'files' )
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should keep track of extra files seen" do
|
181
|
+
@bundle.extras.wont_be_nil
|
182
|
+
static_files = %w[ common.css _static/foo.png section/foo.jpg ]
|
183
|
+
static_files << "section/sub section/foo.gif"
|
184
|
+
static_files.each do |path|
|
185
|
+
@bundle.extras.must_include path
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should not count page sources as extra files" do
|
190
|
+
page_files = %w[ index.md another.md first.textile section/page.haml ]
|
191
|
+
page_files << "section/sub section/page.txt"
|
192
|
+
page_files.each do |path|
|
193
|
+
@bundle.extras.wont_include path
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should skip files specified by global glob matches" do
|
198
|
+
@bundle.global.ignore.as_list.must_equal %w[ **/*.psd **/*.ai **/Thumbs.db BUILDING.txt ]
|
199
|
+
bad_files = %w[ _static/foo.ai _static/foo.psd _static/Thumbs.db ]
|
200
|
+
bad_files << "section/sub section/Thumbs.db"
|
201
|
+
bad_files.each do |path|
|
202
|
+
@bundle.extras.wont_include path
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should not count ignored files as the source for pages" do
|
207
|
+
@bundle.pages.find{ |page| page.file == 'BUILDING.txt' }.must_be_nil
|
208
|
+
@bundle.page_by_file_path['BUILDING.txt'].must_be_nil
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "Pages in bundles" do
|
213
|
+
before do
|
214
|
+
@titles = [ 'First One', 'Second One', 'Third One', 'Fourth One', 'Fifth One', '911' ]
|
215
|
+
Dir.chdir SAMPLES/'links' do
|
216
|
+
@files = Dir['**/*'] - %w[ index.txt sub2/bozo.bin ]
|
217
|
+
@htmls = @files.map{ |path|
|
218
|
+
path[/\.[^.]+$/] ? path.gsub(/\.[^.]+$/,'.html') : path/'index.html'
|
219
|
+
}
|
220
|
+
end
|
221
|
+
@out, @err = capture_io do
|
222
|
+
@titles_bundle = DocuBot::Bundle.new SAMPLES/'titles'
|
223
|
+
@links_bundle = DocuBot::Bundle.new SAMPLES/'links'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should allow you to find arrays of pages by title" do
|
228
|
+
@titles_bundle.pages_by_title.wont_be_nil
|
229
|
+
@titles.each do |page_title|
|
230
|
+
pages = @titles_bundle.pages_by_title[page_title]
|
231
|
+
pages.must_be_kind_of Array
|
232
|
+
pages.length.must_equal 1
|
233
|
+
pages.first.must_be_kind_of DocuBot::Page
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should return an empty array for a non-existent page" do
|
238
|
+
pages = @titles_bundle.pages_by_title['NONE SUCH']
|
239
|
+
pages.must_be_kind_of Array
|
240
|
+
pages.length.must_equal 0
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should not include the main index file in the titles" do
|
244
|
+
pages = @titles_bundle.pages_by_title["Title Changin'"]
|
245
|
+
pages.must_be_kind_of Array
|
246
|
+
pages.length.must_equal 0
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should give access to pages by source file path" do
|
250
|
+
@links_bundle.page_by_file_path.wont_be_nil
|
251
|
+
@files.each do |path|
|
252
|
+
@links_bundle.page_by_file_path[path].must_be_kind_of DocuBot::Page
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should return nil for an unfound file path" do
|
257
|
+
@links_bundle.page_by_file_path['NONE SUCH'].must_be_nil
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should not include raw files in the file paths" do
|
261
|
+
@links_bundle.page_by_file_path['sub2/bozo.bin'].must_be_nil
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should give access to pages by html file path" do
|
265
|
+
@links_bundle.page_by_html_path.wont_be_nil
|
266
|
+
@htmls.each do |path|
|
267
|
+
p path unless @links_bundle.page_by_html_path[path]
|
268
|
+
@links_bundle.page_by_html_path[path].wont_be_nil
|
269
|
+
@links_bundle.page_by_html_path[path].must_be_kind_of DocuBot::Page
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should return nil for an unfound html path" do
|
274
|
+
@links_bundle.page_by_html_path['NONE SUCH'].must_be_nil
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should not include raw files in the html paths" do
|
278
|
+
@links_bundle.page_by_html_path['sub2/bozo.bin'].must_be_nil
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "Global bundle attributes" do
|
283
|
+
before do
|
284
|
+
@out, @err = capture_io do
|
285
|
+
@bundle = DocuBot::Bundle.new SAMPLES/'attributes'
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should have a global object" do
|
290
|
+
@bundle.global.wont_be_nil
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should be indexable by method and return strings" do
|
294
|
+
@bundle.global.author.must_equal "Gavin Kistner"
|
295
|
+
@bundle.global.default.must_equal "All About Mr. Friggles"
|
296
|
+
@bundle.global.quotes.must_equal %q{"It's all about Mr. Benjamin", "I have never seen this cat before in my life!"}
|
297
|
+
@bundle.global.awesome.must_equal "true"
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should be indexable by string" do
|
301
|
+
@bundle.global['author.email'].must_equal "!@phrogz.net"
|
302
|
+
@bundle.global['author website'].must_equal "http://phrogz.net"
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should use utf8 for the strings" do
|
306
|
+
if Object.const_defined? :Encoding
|
307
|
+
Encoding.compatible?( @bundle.global.title, "UTF-8™")
|
308
|
+
end
|
309
|
+
@bundle.global.title.must_equal "Friggles® The Cat, ©2009"
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should allow casting values to boolean" do
|
313
|
+
@bundle.global.awesome.as_boolean.must_equal true
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should allow casting values to arrays of strings" do
|
317
|
+
quotes = @bundle.global.quotes.as_list
|
318
|
+
quotes.must_be_kind_of Array
|
319
|
+
quotes.must_equal [ "It's all about Mr. Benjamin", "I have never seen this cat before in my life!" ]
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
describe "Page attributes" do
|
324
|
+
before do
|
325
|
+
@out, @err = capture_io do
|
326
|
+
@bundle = DocuBot::Bundle.new SAMPLES/'attributes'
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
it "does something" do
|
331
|
+
|
332
|
+
end
|
333
|
+
end
|
data/spec/global.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
require File.join(File.dirname(__FILE__), "_helper")
|
3
|
+
|
4
|
+
# http://www.w3.org/TR/html4/types.html#type-id
|
5
|
+
# We disallow colons or periods in the ID because they mess up CSS selectors
|
6
|
+
# We require an octothorpe at the front because it makes life easier
|
7
|
+
VALID_ID = /#[a-z][\w-]*/i
|
8
|
+
|
9
|
+
describe "Generating IDs from Text" do
|
10
|
+
it "must create a valid identifier from a variety of input" do
|
11
|
+
DocuBot.id_from_text("foo").must_match VALID_ID
|
12
|
+
DocuBot.id_from_text("foo-bar").must_match VALID_ID
|
13
|
+
DocuBot.id_from_text("Foo-Bar").must_match VALID_ID
|
14
|
+
DocuBot.id_from_text("foo bar").must_match VALID_ID
|
15
|
+
DocuBot.id_from_text(" foo").must_match VALID_ID
|
16
|
+
DocuBot.id_from_text("foo ").must_match VALID_ID
|
17
|
+
DocuBot.id_from_text(" foo ").must_match VALID_ID
|
18
|
+
DocuBot.id_from_text("foo:bar").must_match VALID_ID
|
19
|
+
DocuBot.id_from_text("foo.bar").must_match VALID_ID
|
20
|
+
DocuBot.id_from_text("foo!bar").must_match VALID_ID
|
21
|
+
DocuBot.id_from_text("foo?!bar").must_match VALID_ID
|
22
|
+
DocuBot.id_from_text("foo(bar)").must_match VALID_ID
|
23
|
+
DocuBot.id_from_text("(foo)bar").must_match VALID_ID
|
24
|
+
DocuBot.id_from_text("!foo bar").must_match VALID_ID
|
25
|
+
DocuBot.id_from_text("foo: bar").must_match VALID_ID
|
26
|
+
DocuBot.id_from_text("!!!").wont_match VALID_ID
|
27
|
+
end
|
28
|
+
end
|
data/spec/glossary.rb
CHANGED
@@ -13,8 +13,8 @@ describe "Glossary Scanner" do
|
|
13
13
|
@out, @err = capture_io do
|
14
14
|
@bundle = DocuBot::Bundle.new SAMPLES/'glossary'
|
15
15
|
@glossary = @bundle.glossary
|
16
|
-
@page = @bundle.
|
17
|
-
@fulldoc = Nokogiri::HTML( @page.to_html )
|
16
|
+
@page = @bundle.pages_by_title['Glossary'].first
|
17
|
+
@fulldoc = Nokogiri::HTML::DocumentFragment.parse( @page.to_html )
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -34,9 +34,9 @@ describe "Glossary Scanner" do
|
|
34
34
|
@glossary.entries.values.each do |defn|
|
35
35
|
defn.must_be_kind_of DocuBot::Page
|
36
36
|
end
|
37
|
-
@glossary.entries["Secret Term"].hide.must_equal true
|
37
|
+
@glossary.entries["Secret Term"].hide.as_boolean.must_equal true
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
it "supports iterating over the entries with each" do
|
41
41
|
count = 0
|
42
42
|
@glossary.each do |page,defn|
|
@@ -47,26 +47,28 @@ describe "Glossary Scanner" do
|
|
47
47
|
count.must_equal @all_terms.length
|
48
48
|
end
|
49
49
|
|
50
|
-
|
51
50
|
it "uses converters for page content" do
|
52
51
|
@expected_paragraphs.each do |term,paras|
|
53
|
-
@glossary.entries[term].nokodoc.xpath('
|
52
|
+
@glossary.entries[term].nokodoc.xpath('.//p').length.must_equal paras
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
56
|
it "supports a glossary template that generates HTML for terms" do
|
58
|
-
definitions = @fulldoc.xpath('
|
57
|
+
definitions = @fulldoc.xpath('.//dt')
|
59
58
|
@expected_paragraphs.each do |term,paras|
|
60
59
|
dt = definitions.find{ |node| node.inner_text==term }
|
61
60
|
dt.wont_be_nil
|
62
|
-
dt.next_element.xpath('.//p').length
|
61
|
+
if dt.next_element.xpath('.//p').length != paras
|
62
|
+
puts dt.next_element.to_html
|
63
|
+
end
|
64
|
+
dt.next_element.xpath('.//p').length.must_equal paras
|
63
65
|
end
|
64
66
|
end
|
65
|
-
|
67
|
+
|
66
68
|
it "does not include hidden pages in the output" do
|
67
|
-
definitions = @fulldoc.xpath('
|
69
|
+
definitions = @fulldoc.xpath('.//dt')
|
68
70
|
@hidden_terms.each do |term|
|
69
|
-
@fulldoc.at_xpath("
|
71
|
+
@fulldoc.at_xpath(".//dt[text()='#{term}']").must_be_nil
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|