arthurgeek-kitabu 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +59 -0
- data/License.txt +20 -0
- data/README.markdown +220 -0
- data/Rakefile +68 -0
- data/TODO.txt +2 -0
- data/app_generators/kitabu/USAGE +5 -0
- data/app_generators/kitabu/kitabu_generator.rb +68 -0
- data/app_generators/kitabu/templates/Rakefile +3 -0
- data/app_generators/kitabu/templates/config.yml +8 -0
- data/app_generators/kitabu/templates/css/active4d.css +114 -0
- data/app_generators/kitabu/templates/css/blackboard.css +88 -0
- data/app_generators/kitabu/templates/css/dawn.css +121 -0
- data/app_generators/kitabu/templates/css/eiffel.css +121 -0
- data/app_generators/kitabu/templates/css/idle.css +62 -0
- data/app_generators/kitabu/templates/css/iplastic.css +80 -0
- data/app_generators/kitabu/templates/css/lazy.css +73 -0
- data/app_generators/kitabu/templates/css/mac_classic.css +123 -0
- data/app_generators/kitabu/templates/css/slush_poppies.css +85 -0
- data/app_generators/kitabu/templates/css/sunburst.css +180 -0
- data/app_generators/kitabu/templates/layouts/boom/layout.css +469 -0
- data/app_generators/kitabu/templates/layouts/boom/layout.html +37 -0
- data/app_generators/kitabu/templates/user.css +0 -0
- data/bin/kitabu +17 -0
- data/kitabu.gemspec +79 -0
- data/lib/kitabu.rb +18 -0
- data/lib/kitabu/base.rb +332 -0
- data/lib/kitabu/blackcloth.rb +165 -0
- data/lib/kitabu/redcloth.rb +963 -0
- data/lib/kitabu/tasks.rb +119 -0
- data/themes/active4d.css +114 -0
- data/themes/all_hallows_eve.css +72 -0
- data/themes/amy.css +147 -0
- data/themes/blackboard.css +88 -0
- data/themes/brilliance_black.css +605 -0
- data/themes/brilliance_dull.css +599 -0
- data/themes/cobalt.css +149 -0
- data/themes/dawn.css +121 -0
- data/themes/eiffel.css +121 -0
- data/themes/espresso_libre.css +109 -0
- data/themes/idle.css +62 -0
- data/themes/iplastic.css +80 -0
- data/themes/lazy.css +73 -0
- data/themes/mac_classic.css +123 -0
- data/themes/magicwb_amiga.css +104 -0
- data/themes/pastels_on_dark.css +188 -0
- data/themes/slush_poppies.css +85 -0
- data/themes/spacecadet.css +51 -0
- data/themes/sunburst.css +180 -0
- data/themes/twilight.css +137 -0
- data/themes/zenburnesque.css +91 -0
- metadata +144 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
2
|
+
"http://www.w3.org/TR/html4/strict.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
6
|
+
<link rel="stylesheet" type="text/css" href="../templates/layout.css"/>
|
7
|
+
<link rel="stylesheet" type="text/css" href="../templates/syntax.css"/>
|
8
|
+
<link rel="stylesheet" type="text/css" href="../templates/user.css"/>
|
9
|
+
|
10
|
+
<meta name="author" content="<%%= authors.join(', ') %>" />
|
11
|
+
<meta name="subject" content="<%%= subject %>" />
|
12
|
+
<meta name="keywords" content="<%%= keywords %>" />
|
13
|
+
</head>
|
14
|
+
<body>
|
15
|
+
<div class="frontcover"></div>
|
16
|
+
<div class="halftitlepage">
|
17
|
+
<h1 class="no-toc"><%%= title %></h1>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div class="titlepage">
|
21
|
+
<h1 class="no-toc"><%%= title %></h1>
|
22
|
+
<p class="no-toc"><%%= authors.join('<br/>') %></p>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class="imprint">
|
26
|
+
<p><%%= copyright %></p>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div class="chapters">
|
30
|
+
<%%= contents %>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div class="white_page"></div>
|
34
|
+
<div class="white_page"></div>
|
35
|
+
<div class="backcover"></div>
|
36
|
+
</body>
|
37
|
+
</html>
|
File without changes
|
data/bin/kitabu
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubigen'
|
5
|
+
|
6
|
+
if %w(-v --version).include? ARGV.first
|
7
|
+
require 'kitabu/version'
|
8
|
+
puts "#{File.basename($0)} #{Kitabu::VERSION::STRING}"
|
9
|
+
exit(0)
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rubigen/scripts/generate'
|
13
|
+
source = RubiGen::PathSource.new(:application,
|
14
|
+
File.join(File.dirname(__FILE__), "../app_generators"))
|
15
|
+
RubiGen::Base.reset_sources
|
16
|
+
RubiGen::Base.append_sources source
|
17
|
+
RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'kitabu')
|
data/kitabu.gemspec
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# WARNING : RAKE AUTO-GENERATED FILE. DO NOT MANUALLY EDIT!
|
2
|
+
# RUN : 'rake gem:update_gemspec'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.date = "Fri Aug 01 05:56:29 -0300 2008"
|
6
|
+
s.executables = ["kitabu"]
|
7
|
+
s.authors = ["Nando Vieira"]
|
8
|
+
s.required_rubygems_version = ">= 0"
|
9
|
+
s.version = "0.2.0"
|
10
|
+
s.files = ["Rakefile",
|
11
|
+
"kitabu.gemspec",
|
12
|
+
"History.txt",
|
13
|
+
"License.txt",
|
14
|
+
"README.markdown",
|
15
|
+
"TODO.txt",
|
16
|
+
"app_generators/kitabu",
|
17
|
+
"app_generators/kitabu/kitabu_generator.rb",
|
18
|
+
"app_generators/kitabu/templates",
|
19
|
+
"app_generators/kitabu/templates/config.yml",
|
20
|
+
"app_generators/kitabu/templates/css",
|
21
|
+
"app_generators/kitabu/templates/css/active4d.css",
|
22
|
+
"app_generators/kitabu/templates/css/blackboard.css",
|
23
|
+
"app_generators/kitabu/templates/css/dawn.css",
|
24
|
+
"app_generators/kitabu/templates/css/eiffel.css",
|
25
|
+
"app_generators/kitabu/templates/css/idle.css",
|
26
|
+
"app_generators/kitabu/templates/css/iplastic.css",
|
27
|
+
"app_generators/kitabu/templates/css/lazy.css",
|
28
|
+
"app_generators/kitabu/templates/css/mac_classic.css",
|
29
|
+
"app_generators/kitabu/templates/css/slush_poppies.css",
|
30
|
+
"app_generators/kitabu/templates/css/sunburst.css",
|
31
|
+
"app_generators/kitabu/templates/layouts",
|
32
|
+
"app_generators/kitabu/templates/layouts/boom",
|
33
|
+
"app_generators/kitabu/templates/layouts/boom/layout.css",
|
34
|
+
"app_generators/kitabu/templates/layouts/boom/layout.html",
|
35
|
+
"app_generators/kitabu/templates/Rakefile",
|
36
|
+
"app_generators/kitabu/templates/user.css",
|
37
|
+
"app_generators/kitabu/USAGE",
|
38
|
+
"bin/kitabu",
|
39
|
+
"lib/kitabu",
|
40
|
+
"lib/kitabu/base.rb",
|
41
|
+
"lib/kitabu/blackcloth.rb",
|
42
|
+
"lib/kitabu/redcloth.rb",
|
43
|
+
"lib/kitabu/tasks.rb",
|
44
|
+
"lib/kitabu.rb",
|
45
|
+
"themes/active4d.css",
|
46
|
+
"themes/all_hallows_eve.css",
|
47
|
+
"themes/amy.css",
|
48
|
+
"themes/blackboard.css",
|
49
|
+
"themes/brilliance_black.css",
|
50
|
+
"themes/brilliance_dull.css",
|
51
|
+
"themes/cobalt.css",
|
52
|
+
"themes/dawn.css",
|
53
|
+
"themes/eiffel.css",
|
54
|
+
"themes/espresso_libre.css",
|
55
|
+
"themes/idle.css",
|
56
|
+
"themes/iplastic.css",
|
57
|
+
"themes/lazy.css",
|
58
|
+
"themes/mac_classic.css",
|
59
|
+
"themes/magicwb_amiga.css",
|
60
|
+
"themes/pastels_on_dark.css",
|
61
|
+
"themes/slush_poppies.css",
|
62
|
+
"themes/spacecadet.css",
|
63
|
+
"themes/sunburst.css",
|
64
|
+
"themes/twilight.css",
|
65
|
+
"themes/zenburnesque.css"]
|
66
|
+
s.has_rdoc = false
|
67
|
+
s.requirements = ["Install the Oniguruma RE library and ultraviolet gem to get Syntax Highlighting (only for TextMate users)"]
|
68
|
+
s.email = ["fnando.vieira@gmail.com"]
|
69
|
+
s.name = "kitabu"
|
70
|
+
s.bindir = "bin"
|
71
|
+
s.homepage = "http://github.com/fnando/kitabu"
|
72
|
+
s.summary = "A framework for creating e-books from Markdown/Textile text markup using Ruby."
|
73
|
+
s.description = "A framework for creating e-books from Markdown/Textile text markup using Ruby. Using the Prince PDF generator, you'll be able to get high quality PDFs. Mac users that have Textmate installed can have source code highlighted with his favorite theme."
|
74
|
+
s.add_dependency "rubigen", ">= 0"
|
75
|
+
s.add_dependency "discount", ">= 0"
|
76
|
+
s.add_dependency "hpricot", ">= 0"
|
77
|
+
s.add_dependency "unicode", ">= 0"
|
78
|
+
s.require_paths = ["lib"]
|
79
|
+
end
|
data/lib/kitabu.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "yaml"
|
6
|
+
require "erb"
|
7
|
+
require "ostruct"
|
8
|
+
require "rexml/streamlistener"
|
9
|
+
require "rexml/document"
|
10
|
+
require "hpricot"
|
11
|
+
|
12
|
+
require "kitabu/base"
|
13
|
+
|
14
|
+
begin
|
15
|
+
require "ruby-debug"
|
16
|
+
rescue LoadError => e
|
17
|
+
nil
|
18
|
+
end
|
data/lib/kitabu/base.rb
ADDED
@@ -0,0 +1,332 @@
|
|
1
|
+
module Kitabu
|
2
|
+
module Markup
|
3
|
+
def self.content_for(options)
|
4
|
+
source_file = File.join(KITABU_ROOT, 'code', options[:source_file].to_s)
|
5
|
+
code = options[:code]
|
6
|
+
|
7
|
+
if options[:source_file] && File.exists?(source_file)
|
8
|
+
file = File.new(source_file)
|
9
|
+
|
10
|
+
if options[:from_line] && options[:to_line]
|
11
|
+
from_line = options[:from_line].to_i - 1
|
12
|
+
to_line = options[:to_line].to_i
|
13
|
+
offset = to_line - from_line
|
14
|
+
code = file.readlines.slice(from_line, offset).join
|
15
|
+
elsif block_name = options[:block_name]
|
16
|
+
re = %r(# ?begin: ?#{block_name} ?(?:[^\r\n]+)?\r?\n(.*?)\r?\n([^\r\n]+)?# ?end: #{block_name})sim
|
17
|
+
file.read.gsub(re) { |block| code = $1 }
|
18
|
+
else
|
19
|
+
code = file.read
|
20
|
+
code = code.gsub(/</, '<').gsub(/>/, '>').gsub(/&/, '&')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# no code? set to default
|
25
|
+
code ||= options[:code]
|
26
|
+
|
27
|
+
# normalize indentation
|
28
|
+
line = StringIO.new(code).readlines[0]
|
29
|
+
|
30
|
+
if line =~ /^(\t+)/
|
31
|
+
char = "\t"
|
32
|
+
size = $1.length
|
33
|
+
elsif line =~ /^( +)/
|
34
|
+
char = " "
|
35
|
+
size = $1.length
|
36
|
+
end
|
37
|
+
|
38
|
+
code.gsub! %r(^#{char}{#{size}}), "" if size.to_i > 0
|
39
|
+
|
40
|
+
# remove all line stubs
|
41
|
+
code.gsub! %r(^[\t ]*__$), ""
|
42
|
+
|
43
|
+
# return
|
44
|
+
code
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.syntax(code, syntax='plain_text')
|
48
|
+
# get chosen theme
|
49
|
+
theme = Kitabu::Base.config['theme']
|
50
|
+
theme = Kitabu::Base.default_theme unless Kitabu::Base.theme?(theme)
|
51
|
+
|
52
|
+
# get syntax
|
53
|
+
syntax = Kitabu::Base.default_syntax unless Kitabu::Base.syntax?(syntax)
|
54
|
+
|
55
|
+
Uv.parse(code, "xhtml", syntax, false, theme)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module Base
|
60
|
+
DEFAULT_LAYOUT = 'boom'
|
61
|
+
DEFAULT_THEME = 'eiffel'
|
62
|
+
DEFAULT_SYNTAX = 'plain_text'
|
63
|
+
GEM_ROOT = File.expand_path(File.dirname(__FILE__) + "/../../")
|
64
|
+
|
65
|
+
def self.html_path
|
66
|
+
KITABU_ROOT + "/output/#{app_name}.html"
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.pdf_path
|
70
|
+
KITABU_ROOT + "/output/#{app_name}.pdf"
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.template_path
|
74
|
+
KITABU_ROOT + "/templates/layout.html"
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.config_path
|
78
|
+
KITABU_ROOT + "/config.yml"
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.text_dir
|
82
|
+
KITABU_ROOT + "/text"
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.config
|
86
|
+
@config ||= YAML::load_file(config_path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.parse_layout(contents)
|
90
|
+
template = File.new(template_path).read
|
91
|
+
contents, toc = self.table_of_contents(contents)
|
92
|
+
cfg = config.merge(:contents => contents, :toc => toc)
|
93
|
+
env = OpenStruct.new(cfg)
|
94
|
+
|
95
|
+
ERB.new(template).result env.instance_eval{binding}
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.table_of_contents(contents)
|
99
|
+
return [contents, nil] unless Object.const_defined?('Hpricot') && Object.const_defined?('Unicode')
|
100
|
+
|
101
|
+
doc = Hpricot(contents)
|
102
|
+
counter = {}
|
103
|
+
|
104
|
+
(doc/"h2, h3, h4, h5, h6").each do |node|
|
105
|
+
title = node.inner_text
|
106
|
+
permalink = Kitabu::Base.to_permalink(title)
|
107
|
+
|
108
|
+
# initialize and increment counter
|
109
|
+
counter[permalink] ||= 0
|
110
|
+
counter[permalink] += 1
|
111
|
+
|
112
|
+
# set a incremented permalink if more than one occurrence
|
113
|
+
# is found
|
114
|
+
permalink = "#{permalink}-#{counter[permalink]}" if counter[permalink] > 1
|
115
|
+
|
116
|
+
node.set_attribute(:id, permalink)
|
117
|
+
end
|
118
|
+
|
119
|
+
contents = doc.to_html
|
120
|
+
io = StringIO.new(contents)
|
121
|
+
toc = Toc.new
|
122
|
+
REXML::Document.parse_stream(io, toc)
|
123
|
+
|
124
|
+
[contents, toc.to_s]
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.generate_pdf
|
128
|
+
IO.popen('prince %s -o %s' % [html_path, pdf_path])
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.generate_html
|
132
|
+
# all parsed markdown file holder
|
133
|
+
contents = ""
|
134
|
+
|
135
|
+
# first, get all chapters; then, get all parsed markdown
|
136
|
+
# files from this chapter and group them into a <div class="chapter"> tag
|
137
|
+
Dir.entries(text_dir).sort.each do |dirname|
|
138
|
+
# ignore files and some directories
|
139
|
+
next if %w(. .. .svn .git).include?(dirname) || File.file?(text_dir + "/#{dirname}")
|
140
|
+
|
141
|
+
# gets all parsed markdown files to wrap in a
|
142
|
+
# chapter element
|
143
|
+
chapter = ""
|
144
|
+
|
145
|
+
# merge all markdown and textile files into a single list
|
146
|
+
markup_files = Dir["#{text_dir}/#{dirname}/**/*.markdown"] + Dir["#{text_dir}/#{dirname}/**/*.textile"]
|
147
|
+
|
148
|
+
# no files, so skip it!
|
149
|
+
next if markup_files.empty?
|
150
|
+
|
151
|
+
markup_files.sort.each do |markup_file|
|
152
|
+
# get the file contents
|
153
|
+
markup_contents = File.new(markup_file).read
|
154
|
+
|
155
|
+
# instantiate a markup object
|
156
|
+
begin
|
157
|
+
if markup_file =~ /\.textile$/
|
158
|
+
markup = BlackCloth.new(markup_contents)
|
159
|
+
else
|
160
|
+
markup = Discount.new(markup_contents)
|
161
|
+
end
|
162
|
+
rescue Exception => e
|
163
|
+
puts "Skipping #{markup_file} (#{e.message})"
|
164
|
+
next
|
165
|
+
end
|
166
|
+
|
167
|
+
# convert the markup into html
|
168
|
+
parsed_contents = markup.to_html
|
169
|
+
|
170
|
+
if Object.const_defined?('Uv')
|
171
|
+
if markup.respond_to?(:syntax_blocks)
|
172
|
+
# textile
|
173
|
+
parsed_contents.gsub!(/@syntax:([0-9]+)/m) do |m|
|
174
|
+
syntax, code = markup.syntax_blocks[$1.to_i]
|
175
|
+
Kitabu::Markup.syntax(code, syntax)
|
176
|
+
end
|
177
|
+
else
|
178
|
+
# markdown
|
179
|
+
parsed_contents.gsub! /<pre><code>(.*?)<\/code><\/pre>/m do |block|
|
180
|
+
code = $1.gsub(/</, '<').gsub(/>/, '>').gsub(/&/, '&')
|
181
|
+
code_lines = StringIO.new(code).readlines
|
182
|
+
syntax_settings = code_lines.first
|
183
|
+
|
184
|
+
syntax = 'plain_text'
|
185
|
+
|
186
|
+
if syntax_settings =~ /syntax\(.*?\)\./
|
187
|
+
code = code_lines.slice(1, code_lines.size).join
|
188
|
+
|
189
|
+
# syntax
|
190
|
+
m, syntax = *syntax_settings.match(/syntax\(([^ #]+).*?\)./)
|
191
|
+
|
192
|
+
# file name
|
193
|
+
m, source_file = *syntax_settings.match(/syntax\(.*?\)\. +(.*?)$/)
|
194
|
+
|
195
|
+
# get line interval
|
196
|
+
m, from_line, to_line = *syntax_settings.match(/syntax\(.*? ([0-9]+),([0-9]+)\)/)
|
197
|
+
|
198
|
+
# get block name
|
199
|
+
m, block_name = *syntax_settings.match(/syntax\(.*?#([0-9a-z_]+)\)/)
|
200
|
+
|
201
|
+
code = Kitabu::Markup.content_for({
|
202
|
+
:code => code,
|
203
|
+
:from_line => from_line,
|
204
|
+
:to_line => to_line,
|
205
|
+
:block_name => block_name,
|
206
|
+
:source_file => source_file
|
207
|
+
})
|
208
|
+
|
209
|
+
Kitabu::Markup.syntax(code, syntax)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
chapter << (parsed_contents + "\n\n")
|
216
|
+
end
|
217
|
+
|
218
|
+
contents << '<div class="chapter">%s</div>' % chapter
|
219
|
+
end
|
220
|
+
|
221
|
+
# save html file
|
222
|
+
File.open(html_path, 'w+') do |f|
|
223
|
+
f << Kitabu::Base.parse_layout(contents)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.app_name
|
228
|
+
ENV['KITABU_NAME'] || 'kitabu'
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.theme?(theme_name)
|
232
|
+
themes.include?(theme_name)
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.syntax?(syntax_name)
|
236
|
+
syntaxes.include?(syntax_name)
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.default_theme
|
240
|
+
DEFAULT_THEME
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.default_syntax
|
244
|
+
DEFAULT_SYNTAX
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.default_layout
|
248
|
+
DEFAULT_LAYOUT
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.syntaxes
|
252
|
+
Uv.syntaxes
|
253
|
+
end
|
254
|
+
|
255
|
+
def self.layouts
|
256
|
+
@layouts ||= begin
|
257
|
+
dir = File.join(GEM_ROOT, "app_generators/kitabu/templates/layouts/")
|
258
|
+
Dir.entries(dir).reject{|p| p =~ /^\.+$/ }.sort
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def self.themes
|
263
|
+
@themes ||= begin
|
264
|
+
filter = File.join(GEM_ROOT, "app_generators/kitabu/templates/css/*.css")
|
265
|
+
Dir[filter].collect{|path| File.basename(path).gsub(/\.css$/, '') }.sort
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.to_permalink(str)
|
270
|
+
str = Unicode.normalize_KD(str).gsub(/[^\x00-\x7F]/n,'')
|
271
|
+
str = str.gsub(/[^-_\s\w]/, ' ').downcase.squeeze(' ').tr(' ', '-')
|
272
|
+
str = str.gsub(/-+/, '-').gsub(/^-+/, '').gsub(/-+$/, '')
|
273
|
+
str
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
class Toc
|
278
|
+
include REXML::StreamListener
|
279
|
+
|
280
|
+
def initialize
|
281
|
+
@toc = ""
|
282
|
+
@previous_level = 0
|
283
|
+
@tag = nil
|
284
|
+
@stack = []
|
285
|
+
end
|
286
|
+
|
287
|
+
def header?(tag=nil)
|
288
|
+
tag ||= @tag_name
|
289
|
+
return false unless tag.to_s =~ /h[2-6]/
|
290
|
+
@tag_name = tag
|
291
|
+
return true
|
292
|
+
end
|
293
|
+
|
294
|
+
def in_header?
|
295
|
+
@in_header
|
296
|
+
end
|
297
|
+
|
298
|
+
def tag_start(name, attrs)
|
299
|
+
@tag_name = name
|
300
|
+
return unless header?(name)
|
301
|
+
@in_header = true
|
302
|
+
@current_level = name.gsub!(/[^2-6]/, '').to_i
|
303
|
+
@stack << @current_level
|
304
|
+
@id = attrs["id"]
|
305
|
+
|
306
|
+
@toc << %(<ul class="level#{@current_level}">) if @current_level > @previous_level
|
307
|
+
@toc << %(</li></ul>) * (@previous_level - @current_level) if @current_level < @previous_level
|
308
|
+
@toc << %(</li>) if @current_level <= @previous_level
|
309
|
+
@toc << %(<li>)
|
310
|
+
end
|
311
|
+
|
312
|
+
def tag_end(name)
|
313
|
+
return unless header?(name)
|
314
|
+
@in_header = false
|
315
|
+
@previous_level = @current_level
|
316
|
+
end
|
317
|
+
|
318
|
+
def text(str)
|
319
|
+
return unless in_header?
|
320
|
+
@toc << %(<a href="##{@id}"><span>#{str}</span></a>)
|
321
|
+
end
|
322
|
+
|
323
|
+
def method_missing(*args)
|
324
|
+
end
|
325
|
+
|
326
|
+
def to_s
|
327
|
+
@toc + (%(</li></ul>) * (@stack.last - 1))
|
328
|
+
rescue
|
329
|
+
""
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|