trac-export-wiki 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Loren Segal
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,36 @@
1
+ # Trac Wiki Exporter
2
+
3
+ ## Synopsis
4
+
5
+ Exports wiki pages in Trac as HTML pages organized in categories for easy
6
+ local viewing.
7
+
8
+ ## Installing
9
+
10
+ $ [sudo] gem install trac-export-wiki
11
+
12
+ ## Using
13
+
14
+ To use this script, you need to create a `config.yaml` file that tells the
15
+ exporter which pages you want to export under which categories. You can
16
+ see a sample config.yaml file in the "examples" directory. Once you've
17
+ created your configuration file, you can call the script with:
18
+
19
+ $ trac-export-wiki config.yaml
20
+
21
+ This will download the wiki pages from your site into your current directory.
22
+ If you want to put your files in a `docs` directory, make sure to cd there
23
+ first:
24
+
25
+ $ mkdir docs
26
+ $ cd docs
27
+ $ trac-export-wiki ../config.yaml
28
+
29
+ You can specify some parameters on the command-line, see `trac-export-wiki --help`
30
+ for a list of options. Specifically, you may want to only regenerate the index
31
+ page, or not generate the index page. This is done with `-i` or `-n` respectively.
32
+
33
+ ## License & Author
34
+
35
+ This library is written by Loren Segal and released under the MIT license.
36
+ See the `LICENSE` file attached with this archive.
@@ -0,0 +1,33 @@
1
+ require 'rbconfig'
2
+
3
+ WINDOWS = (Config::CONFIG['host_os'] =~ /mingw|win32|cygwin/ ? true : false) rescue false
4
+ SUDO = WINDOWS ? '' : 'sudo'
5
+
6
+ task :default => :specs
7
+
8
+ desc "Builds the gem"
9
+ task :gem do
10
+ load 'trac-export-wiki.gemspec'
11
+ Gem::Builder.new(SPEC).build
12
+ end
13
+
14
+ desc "Installs the gem"
15
+ task :install => :gem do
16
+ sh "#{SUDO} gem install trac-export-wiki-1.0.0.gem --no-rdoc --no-ri"
17
+ end
18
+
19
+ begin
20
+ require 'spec'
21
+ require 'spec/rake/spectask'
22
+
23
+ desc "Run all specs"
24
+ Spec::Rake::SpecTask.new("specs") do |t|
25
+ $DEBUG = true if ENV['DEBUG']
26
+ t.spec_opts = ["--format", "specdoc", "--colour"]
27
+ t.spec_opts += ["--require", File.join(File.dirname(__FILE__), 'spec', 'spec_helper')]
28
+ t.spec_files = Dir["spec/**/*_spec.rb"].sort
29
+ end
30
+ task :spec => :specs
31
+ rescue LoadError
32
+ warn "warn: RSpec tests not available. `gem install rspec` to enable them."
33
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__)) + "/../lib/trac-export-wiki"
3
+ TracWiki::CLI.new.run(*ARGV)
@@ -0,0 +1,42 @@
1
+ #username: username_here
2
+ #password: password_here
3
+ base_url: http://example.com/trac/soen490
4
+ pages:
5
+ mgmt:
6
+ - BiWeeklyStatusReport
7
+ - Proposal
8
+ - ActivityPlan
9
+ - RiskManagement
10
+ - ProcessDocumentation
11
+ - ImpactAnalysis
12
+ research:
13
+ - CachingStrategies
14
+ - CachingEvaluation
15
+ - LoadBalancing
16
+ - PlanForDistributedReq
17
+ - ProversBenchmark
18
+ - ProfilingResults
19
+ reqs:
20
+ - VisionDocument
21
+ - SupplementarySpecification
22
+ - InstallationAndCommissioning
23
+ - Glossary
24
+ design:
25
+ - Jml4-LogicalView
26
+ - FirstPrototype
27
+ - Jml4Disco-LogicalView
28
+ - Jml4Disco-PhysicalView
29
+ - Jml4Disco-UseCaseView
30
+ - DevelopmentView
31
+ test:
32
+ - TestPlan
33
+ - BoogieTraceability
34
+ - PerformanceReport
35
+ categories:
36
+ mgmt: 'Management, Planning & Risk Analysis Docs'
37
+ research: 'Research & Potential Strategies Docs'
38
+ reqs: 'Requirements Docs'
39
+ design: 'Design & Architecture'
40
+ test: 'Testing & Implementation'
41
+ wiki_title: JML4 Disco Documentation
42
+ wiki_title_prefix: Disco
@@ -0,0 +1,58 @@
1
+ # The base URL to the trac page (excluding /wiki)
2
+ base_url: http://example.com/trac/myproject
3
+
4
+ # Optional authentication information, uncomment below.
5
+ # You can also specify this information via the command-line (-u/-p).
6
+ #username: username_here
7
+ #password: password_here
8
+
9
+ # The list of pages within separated categories
10
+ # The category should be listed first, followed by a list of pages
11
+ pages:
12
+ # Make sure to include the category short-name first
13
+ mgmt:
14
+ - BiWeeklyStatusReport
15
+ - Proposal
16
+ - ActivityPlan
17
+ - RiskManagement
18
+ - ProcessDocumentation
19
+ - ImpactAnalysis
20
+ research:
21
+ - CachingStrategies
22
+ - CachingEvaluation
23
+ - LoadBalancing
24
+ - PlanForDistributedReq
25
+ - ProversBenchmark
26
+ - ProfilingResults
27
+ reqs:
28
+ - VisionDocument
29
+ - SupplementarySpecification
30
+ - InstallationAndCommissioning
31
+ - Glossary
32
+ design:
33
+ - Jml4-LogicalView
34
+ - FirstPrototype
35
+ - Jml4Disco-LogicalView
36
+ - Jml4Disco-PhysicalView
37
+ - Jml4Disco-UseCaseView
38
+ - DevelopmentView
39
+ test:
40
+ - TestPlan
41
+ - BoogieTraceability
42
+ - PerformanceReport
43
+
44
+ # The full titles and order of the category short-names. These titles will be
45
+ # listed in the order they are given on the index.html page.
46
+ categories:
47
+ mgmt: 'Management, Planning & Risk Analysis Docs'
48
+ research: 'Research & Potential Strategies Docs'
49
+ reqs: 'Requirements Docs'
50
+ design: 'Design & Architecture'
51
+ test: 'Testing & Implementation'
52
+
53
+ # The wiki title listed on the index.html page
54
+ wiki_title: JML4 Disco Documentation
55
+
56
+ # The wiki short title used in the <title> of individual wiki pages
57
+ # in the form: "SHORT_TITLE - WIKI_PAGE_TITLE"
58
+ wiki_title_prefix: Disco
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/ruby
2
+ require 'net/https'
3
+ require 'open-uri'
4
+ require 'hpricot'
5
+ require 'fileutils'
6
+ require 'optparse'
7
+
8
+ module TracWiki
9
+ class HashStruct < Hash
10
+ def self.[](*hash)
11
+ case hash.first
12
+ when Hash
13
+ super(*hash.first.map {|k, v| [k.to_sym, v] }.flatten(1))
14
+ else
15
+ i = 0
16
+ super(*hash.map {|e| e = i % 2 == 0 ? e.to_sym : e; i += 1; e })
17
+ end
18
+ end
19
+
20
+ def []=(key, value)
21
+ super(key.to_sym, value)
22
+ end
23
+
24
+ def method_missing(sym, *args, &block)
25
+ if has_key?(sym.to_sym)
26
+ self[sym.to_sym]
27
+ else
28
+ super
29
+ end
30
+ end
31
+ end
32
+
33
+ DefaultConfiguration = HashStruct[
34
+ :username => nil,
35
+ :password => nil,
36
+ :base_url => nil,
37
+ :destination_path => '.',
38
+ :pages => {},
39
+ :categories => [],
40
+ :wiki_title => "Trac Wiki Pages",
41
+ :wiki_title_prefix => "Wiki",
42
+ :no_index => false,
43
+ :only_index => false,
44
+ ].freeze
45
+
46
+ class CLI
47
+ attr_accessor :config
48
+
49
+ def initialize
50
+ self.config = DefaultConfiguration.dup
51
+ end
52
+
53
+ def run(*args)
54
+ args = args.dup
55
+ opts = OptionParser.new
56
+ opts.banner = "Usage: trac-export-wiki [options] config.yaml"
57
+ opts.on('-u', '--username USERNAME') {|username| config[:username] = username }
58
+ opts.on('-p', '--password PASSWORD') {|password| config[:password] = password }
59
+ opts.on('-b', '--base-url URL') {|url| config[:base_url] = url }
60
+ opts.on('-t', '--wiki-title TITLE') {|title| config[:wiki_title] = title }
61
+ opts.on('-T', '--wiki-title-prefix TITLE') {|title| config[:wiki_title_prefix] = title }
62
+ opts.on('-i', '--only-index') { config[:only_index] = true }
63
+ opts.on('-n', '--no-index') { config[:no_index] = true }
64
+ opts.parse!(args)
65
+ parse_from_yaml(args.first) if args.size > 0
66
+ Exporter.new(config).export
67
+ end
68
+
69
+ private
70
+
71
+ def parse_from_yaml(file)
72
+ require 'yaml'
73
+ config.update HashStruct[YAML.load_file(file)]
74
+ end
75
+ end
76
+
77
+ class Exporter
78
+ # common HTML elements to remove (expressed with css selectors)
79
+ ELEMENTS_TO_REMOVE = ["html > head > link",
80
+ "html > head > style",
81
+ "html > head > script",
82
+ "html > body > script",
83
+ "div#banner",
84
+ "div#header",
85
+ "div#search",
86
+ "div#ctxtnav",
87
+ "div#metanav",
88
+ "div#mainnav",
89
+ "div.buttons",
90
+ "div#altlinks",
91
+ "div#footer",
92
+ "h3#tkt-changes-hdr",
93
+ "ul.tkt-chg-list"]
94
+
95
+ attr_accessor :config
96
+
97
+ def initialize(config = DefaultConfiguration)
98
+ self.config = config
99
+ end
100
+
101
+ def export
102
+ write_pages unless config.only_index
103
+ generate_index unless config.no_index
104
+ end
105
+
106
+ private
107
+
108
+ def write_pages
109
+ config.pages.each do |category, page_names|
110
+ page_names.each do |page|
111
+ print "Exporting \"" + page + "\"... "
112
+ Page.new(page, category).export(config)
113
+ puts "done."
114
+ end
115
+ end
116
+ end
117
+
118
+ def generate_index
119
+ print "Exporting index..."
120
+ index = <<-eof
121
+ <html>
122
+ <head>
123
+ <title>#{config.wiki_title}</title>
124
+ </head>
125
+ <body>
126
+ <h1>#{config.wiki_title}</h1>
127
+ eof
128
+ config.categories.each do |line|
129
+ cat, name = *line
130
+ index += "<h2>#{name}</h2>\n"
131
+ index += "<ul>\n"
132
+ config.pages.select {|k,v| k == cat }.each do |cat, docs|
133
+ docs.each do |doc|
134
+ fname = Page.new(doc, cat).filename
135
+ index += "<li><a href='#{fname}'>#{doc}</a>\n"
136
+ end
137
+ end
138
+ index += "</ul>\n"
139
+ end
140
+ index += <<-eof
141
+ </body>
142
+ </html>
143
+ eof
144
+ File.open('index.html', "w") { |f| f.write(index) }
145
+
146
+ puts "done."
147
+ end
148
+ end
149
+
150
+ class Page
151
+ attr_accessor :page_title, :category, :filename, :config
152
+
153
+ def initialize(page_title, category = nil)
154
+ self.page_title = page_title
155
+ self.category = category
156
+ self.filename = File.join(*[category, page_title.gsub(/([a-z])([A-Z])/,'\1-\2').split(/\?/).first.downcase + '.html'].compact)
157
+ end
158
+
159
+ def export(config)
160
+ self.config = config
161
+
162
+ # load the wiki page
163
+ doc = Hpricot(read_asset(page_title))
164
+
165
+ # search for each element and remove it from the doc
166
+ Exporter::ELEMENTS_TO_REMOVE.each { |e| doc.search(e).remove }
167
+
168
+ # set title
169
+ doc.search("html > head").at("title").inner_html = "#{config.wiki_title_prefix} - " + page_title.gsub(/([a-z])([A-Z])/,'\1 \2')
170
+
171
+ # add link to css
172
+ updir = "../" * category.split(/\//).size
173
+ css = %Q(<link rel="stylesheet" type="text/css" href="#{updir}style.css" />)
174
+ charset = %Q(<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />)
175
+ doc.search("html > head").append(css + charset)
176
+
177
+ # give toc's parent ol a class
178
+ ol = doc.search("html > body > div.wiki-toc > ol").first
179
+ ol.raw_attributes = ol.attributes.to_hash.merge('class' => 'top-most') unless ol.nil?
180
+
181
+ # change the toc's li's class names
182
+ doc.search("html > body > div.wiki-toc > ol").search("li.active").set(:class => 'toc') rescue nil
183
+
184
+ # create category directory if it does not exist
185
+ FileUtils.mkdir_p(File.dirname(filename)) rescue nil
186
+
187
+ # find all images
188
+ doc.search("//img").each do |img|
189
+ imgfile = img.attributes['src']
190
+ short_imgfile = File.basename(imgfile).split(/\?/).first
191
+
192
+ # change image attribute in source
193
+ img.raw_attributes = img.attributes.to_hash.merge("src" => File.join('images', short_imgfile))
194
+
195
+ # make image directory
196
+ outdir = File.join(File.dirname(filename), 'images')
197
+ FileUtils.mkdir_p(outdir)
198
+
199
+ # write image to file
200
+ begin
201
+ uri = URI.parse(config.base_url)
202
+ contents = read_asset(imgfile, "#{uri.scheme}://#{uri.host}")
203
+ File.open(File.join(outdir, short_imgfile), "wb") do |f|
204
+ f.write(contents)
205
+ end
206
+ rescue OpenURI::HTTPError
207
+ end
208
+ end
209
+
210
+ # write HTML to file
211
+ File.open(filename, "w") { |f| f.write(doc.to_html) }
212
+ print "wrote #{filename}... "
213
+ rescue StandardError => bang
214
+ print "(Oops! " + bang.message + ") "
215
+ end
216
+
217
+ private
218
+
219
+ def read_asset(asset, base = nil)
220
+ base ||= File.join(config.base_url, "wiki")
221
+ open(File.join(base, asset), open_options).read
222
+ end
223
+
224
+ def open_options
225
+ @open_options ||= config.username ?
226
+ {:http_basic_authentication => [config.username, config.password]} : {}
227
+ end
228
+ end
229
+ end
230
+
231
+ class Net::HTTP
232
+ alias :old_verify_mode :verify_mode=
233
+ def verify_mode=(x) old_verify_mode(OpenSSL::SSL::VERIFY_NONE) end
234
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trac-export-wiki
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Loren Segal
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-11 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: hpricot
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Exports Trac wiki pages as local HTML files
34
+ email: lsegal@soen.ca
35
+ executables:
36
+ - trac-export-wiki
37
+ extensions: []
38
+
39
+ extra_rdoc_files: []
40
+
41
+ files:
42
+ - bin/trac-export-wiki
43
+ - lib/trac-export-wiki.rb
44
+ - examples/config.yaml
45
+ - examples/config.yaml.sample
46
+ - LICENSE
47
+ - README.md
48
+ - Rakefile
49
+ has_rdoc: yard
50
+ homepage: http://github.com/lsegal/trac-export-wiki
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project: trac-export-wiki
77
+ rubygems_version: 1.3.7
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Exports Trac wiki pages as local HTML files.
81
+ test_files: []
82
+