rdaux 0.1.0
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/.gitignore +18 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +22 -0
- data/README.md +44 -0
- data/Rakefile +1 -0
- data/bin/rdaux +41 -0
- data/lib/rdaux/cli.rb +37 -0
- data/lib/rdaux/container.rb +103 -0
- data/lib/rdaux/logging_listener.rb +19 -0
- data/lib/rdaux/notifier.rb +17 -0
- data/lib/rdaux/renderer.rb +45 -0
- data/lib/rdaux/version.rb +3 -0
- data/lib/rdaux/web/application.rb +40 -0
- data/lib/rdaux/web/server.rb +44 -0
- data/lib/rdaux/web/site/generator.rb +66 -0
- data/lib/rdaux/web/site.rb +86 -0
- data/lib/rdaux/web/views/docs.erb +11 -0
- data/lib/rdaux/web/views/nav.erb +10 -0
- data/lib/rdaux/web/views/site.erb +102 -0
- data/lib/rdaux.rb +2 -0
- data/public/css/bootstrap-responsive.css +1109 -0
- data/public/css/bootstrap-responsive.min.css +9 -0
- data/public/css/bootstrap.css +6167 -0
- data/public/css/bootstrap.min.css +9 -0
- data/public/css/pygments.css +61 -0
- data/public/img/ditaa/.gitignore +0 -0
- data/public/img/glyphicons-halflings-white.png +0 -0
- data/public/img/glyphicons-halflings.png +0 -0
- data/public/js/bootstrap.js +2280 -0
- data/public/js/bootstrap.min.js +6 -0
- data/public/js/html5shiv.min.js +8 -0
- data/public/js/jquery.min.js +6 -0
- data/rdaux.gemspec +34 -0
- data/vendor/ditaa/COPYING +340 -0
- data/vendor/ditaa/HISTORY +16 -0
- data/vendor/ditaa/ditaa0_9.jar +0 -0
- metadata +235 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rdaux (0.1.0)
|
5
|
+
avalanche-cli (= 0.1.0)
|
6
|
+
posix-spawn (= 0.3.6)
|
7
|
+
pygments.rb (= 0.5.1)
|
8
|
+
redcarpet (= 3.0.0)
|
9
|
+
sinatra (= 1.3.3)
|
10
|
+
tilt (= 1.4.1)
|
11
|
+
unicorn (= 4.6.2)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
avalanche-cli (0.1.0)
|
17
|
+
kgio (2.8.0)
|
18
|
+
minitest (5.0.6)
|
19
|
+
posix-spawn (0.3.6)
|
20
|
+
pygments.rb (0.5.1)
|
21
|
+
posix-spawn (~> 0.3.6)
|
22
|
+
yajl-ruby (~> 1.1.0)
|
23
|
+
rack (1.5.2)
|
24
|
+
rack-protection (1.5.0)
|
25
|
+
rack
|
26
|
+
raindrops (0.11.0)
|
27
|
+
rake (10.1.0)
|
28
|
+
redcarpet (3.0.0)
|
29
|
+
sinatra (1.3.3)
|
30
|
+
rack (~> 1.3, >= 1.3.6)
|
31
|
+
rack-protection (~> 1.2)
|
32
|
+
tilt (~> 1.3, >= 1.3.3)
|
33
|
+
tilt (1.4.1)
|
34
|
+
unicorn (4.6.2)
|
35
|
+
kgio (~> 2.6)
|
36
|
+
rack
|
37
|
+
raindrops (~> 0.7)
|
38
|
+
yajl-ruby (1.1.0)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
bundler (~> 1.3)
|
45
|
+
minitest
|
46
|
+
rake
|
47
|
+
rdaux!
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Bulat Shakirzyanov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# RDaux
|
2
|
+
|
3
|
+
RDaux creates beautiful documentation websites from markdown files.
|
4
|
+
It is inspired by daux.io and uses redcarpet with pygments.rb to process
|
5
|
+
github-flavored markdown files into beautiful documentation websites and
|
6
|
+
supports ASCII art with help of [Ditaa](http://sourceforge.net/projects/ditaa/).
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
RDaux is a rubygem, install it by running the following in your shell:
|
11
|
+
|
12
|
+
```bash
|
13
|
+
> gem install rdaux
|
14
|
+
```
|
15
|
+
|
16
|
+
### Requirements
|
17
|
+
|
18
|
+
RDaux requires Python 2.5+ for Pygments and Java 1.5+ for ditaa.
|
19
|
+
Make sure those tools are installed and available in the `$PATH`
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
After RDaux has been installed, you can begin using it from your cli:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
> rdaux -h
|
27
|
+
Usage: rdaux [--version] [--help] command [options] [args]
|
28
|
+
|
29
|
+
Available rdaux commands are:
|
30
|
+
serve Dynamically serve html documentation from a given directory
|
31
|
+
generate Generates static html site using docs from given directory
|
32
|
+
|
33
|
+
Common options:
|
34
|
+
-h, --help Show this message
|
35
|
+
-v, --version Show version
|
36
|
+
```
|
37
|
+
|
38
|
+
As you can see, RDaux can dynamically serve documentation from your markdown
|
39
|
+
sources or it can generate a static documentation website. You can determine
|
40
|
+
options available to each subcommand by running:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
> rdaux <subcommand> -h|--help
|
44
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/rdaux
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
root_path = File.expand_path(__FILE__ + '/../..')
|
4
|
+
|
5
|
+
['lib', 'bundle'].each do |path|
|
6
|
+
dir = root_path + '/' + path
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
|
13
|
+
Dir.chdir(root_path) { require 'bundler/setup' }
|
14
|
+
|
15
|
+
require 'avalanche/cli'
|
16
|
+
require 'rdaux'
|
17
|
+
require 'rdaux/version'
|
18
|
+
require 'rdaux/cli'
|
19
|
+
|
20
|
+
extend RDaux::CLI
|
21
|
+
|
22
|
+
app = Avalanche::CLI::Application.new('rdaux', RDaux::VERSION)
|
23
|
+
|
24
|
+
app.command('serve [options] PATH', 'Dynamically serve html documentation from a given directory', {
|
25
|
+
:title => ['--title TITLE', 'Website title (e.g. RDaux)'],
|
26
|
+
:description => ['--description DESCRIPTION', 'Website description, displayed under title'],
|
27
|
+
:author => ['--author AUTHOR', 'Website author, defaults to $USER'],
|
28
|
+
:log_level => ['--log-level LEVEL', ['debug', 'info', 'warn', 'error', 'fatal'], 'Log level'],
|
29
|
+
:bind => ['--bind ADDRESS', 'IP and port or a unix domain socket to bind on (e.g. localhost:8080 or /var/run/socket.sock)'],
|
30
|
+
:workers => ['--workers NUM', Integer, 'Number of unicorn worker processes to use, defaults to 4']
|
31
|
+
}, command(:start_serving))
|
32
|
+
|
33
|
+
app.command('generate [options] PATH', 'Generates static html site using docs from given directory', {
|
34
|
+
:title => ['--title TITLE', 'Website title (e.g. RDaux)'],
|
35
|
+
:description => ['--description DESCRIPTION', 'Website description, displayed under title'],
|
36
|
+
:author => ['--author AUTHOR', 'Website author, defaults to $USER'],
|
37
|
+
:log_level => ['--log-level LEVEL', ['debug', 'info', 'warn', 'error', 'fatal'], 'Log level'],
|
38
|
+
:output_path => ['--output-path PATH', 'Path to store generated files in, defaults to site/ directory, next to the PATH given']
|
39
|
+
}, command(:generate_site))
|
40
|
+
|
41
|
+
app.run(ARGV)
|
data/lib/rdaux/cli.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rdaux/container'
|
3
|
+
|
4
|
+
module RDaux
|
5
|
+
module CLI
|
6
|
+
include RDaux::Container
|
7
|
+
|
8
|
+
attr_reader :options, :directory
|
9
|
+
|
10
|
+
def command(method)
|
11
|
+
Proc.new do |opts, args|
|
12
|
+
process_options(opts)
|
13
|
+
send(method, *args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_options(options)
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def use_directory(directory)
|
22
|
+
raise 'PATH is a required argument to serve command' if directory.nil?
|
23
|
+
|
24
|
+
@directory = Pathname(directory)
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_serving(directory = nil)
|
28
|
+
use_directory(directory)
|
29
|
+
webserver.serve(website)
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_site(directory = nil)
|
33
|
+
use_directory(directory)
|
34
|
+
generator.generate_static(website)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'redcarpet'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require 'rdaux/notifier'
|
5
|
+
require 'rdaux/web/application'
|
6
|
+
require 'rdaux/web/server'
|
7
|
+
require 'rdaux/web/site'
|
8
|
+
require 'rdaux/web/site/generator'
|
9
|
+
require 'rdaux/renderer'
|
10
|
+
require 'rdaux/logging_listener'
|
11
|
+
|
12
|
+
module RDaux
|
13
|
+
module Container
|
14
|
+
def webapp
|
15
|
+
@webapp ||= with_config(Web::Application) do |app|
|
16
|
+
app.set(:markdown, markdown)
|
17
|
+
app.set(:ditaa_jar, ditaa_jar)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def webserver
|
22
|
+
@webserver ||= with_logging(Web::Server.new(webapp, logger, public_folder, options))
|
23
|
+
end
|
24
|
+
|
25
|
+
def website
|
26
|
+
@website ||= Web::Site.new(title, description, author, directory)
|
27
|
+
end
|
28
|
+
|
29
|
+
def generator
|
30
|
+
@generator ||= with_logging(Web::Site::Generator.new(markdown, views_dir, public_folder, ditaa_jar, target_dir))
|
31
|
+
end
|
32
|
+
|
33
|
+
def logger
|
34
|
+
with_config(Logger.new($stderr)) do |l|
|
35
|
+
l.level = log_level
|
36
|
+
l.formatter = proc { |s, d, p, m| "%s | %-10s %s\n" % [d.strftime("%T,%L"), "[#{s}]", m] }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def log_level
|
41
|
+
Logger.const_get(@options.fetch(:log_level, 'info').upcase)
|
42
|
+
end
|
43
|
+
|
44
|
+
def logging_listener
|
45
|
+
@logging_listener ||= LoggingListener.new(logger)
|
46
|
+
end
|
47
|
+
|
48
|
+
def public_folder
|
49
|
+
File.expand_path(__FILE__ + '/../../../public')
|
50
|
+
end
|
51
|
+
|
52
|
+
def ditaa_jar
|
53
|
+
File.expand_path(__FILE__ + '/../../../vendor/ditaa/ditaa0_9.jar')
|
54
|
+
end
|
55
|
+
|
56
|
+
def markdown
|
57
|
+
Redcarpet::Markdown.new(Renderer.new({
|
58
|
+
:filter_html => true,
|
59
|
+
:images_dir => public_folder,
|
60
|
+
:ditaa_root => '/img/ditaa'
|
61
|
+
}), {
|
62
|
+
:no_intra_emphasis => true,
|
63
|
+
:tables => true,
|
64
|
+
:fenced_code_blocks => true,
|
65
|
+
:autolink => true,
|
66
|
+
:space_after_headers => true,
|
67
|
+
:superscript => true,
|
68
|
+
:underline => true,
|
69
|
+
:highlight => true
|
70
|
+
})
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def views_dir
|
76
|
+
File.expand_path(__FILE__ + '/../web/views')
|
77
|
+
end
|
78
|
+
|
79
|
+
def title
|
80
|
+
options.fetch(:title, "RDaux")
|
81
|
+
end
|
82
|
+
|
83
|
+
def description
|
84
|
+
options.fetch(:description) { "Documentation for <em>#{directory.relative_path_from(Pathname(ENV['PWD']))}</em>" }
|
85
|
+
end
|
86
|
+
|
87
|
+
def author
|
88
|
+
options.fetch(:author) { ENV['USER'] }
|
89
|
+
end
|
90
|
+
|
91
|
+
def target_dir
|
92
|
+
Pathname(options.fetch(:output_path) { directory + '../site/' })
|
93
|
+
end
|
94
|
+
|
95
|
+
def with_logging(obj)
|
96
|
+
with_config(obj) {|o| o.add_listener(logging_listener)}
|
97
|
+
end
|
98
|
+
|
99
|
+
def with_config(obj)
|
100
|
+
obj.tap {|o| yield(o)}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RDaux
|
2
|
+
class LoggingListener
|
3
|
+
def initialize(logger)
|
4
|
+
@logger = logger
|
5
|
+
end
|
6
|
+
|
7
|
+
def creating_application(path)
|
8
|
+
@logger.debug("Creating application for: #{path}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def adding_file(path)
|
12
|
+
@logger.debug("Adding file: #{path}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def adding_directory(path)
|
16
|
+
@logger.debug("Adding directory: #{path}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RDaux
|
2
|
+
module Notifier
|
3
|
+
def notifier_initialize
|
4
|
+
@__listeners__ = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_listener(listener)
|
8
|
+
@__listeners__ << listener
|
9
|
+
end
|
10
|
+
|
11
|
+
def broadcast(event, *args)
|
12
|
+
@__listeners__.each do |listener|
|
13
|
+
listener.__send__(event, *args) if listener.respond_to?(event)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'pygments'
|
3
|
+
|
4
|
+
module RDaux
|
5
|
+
class Renderer < Redcarpet::Render::SmartyHTML
|
6
|
+
def initialize(options)
|
7
|
+
@images_dir = options.delete(:images_dir) { raise ":images_dir is a required option" }
|
8
|
+
@ditaa_root = options.delete(:ditaa_root) { raise ":ditaa_root is a required option" }
|
9
|
+
|
10
|
+
super(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def block_code(code, language)
|
14
|
+
case language
|
15
|
+
when nil
|
16
|
+
"<pre><code>#{code}</code></pre>"
|
17
|
+
when 'ditaa'
|
18
|
+
ascii2png(code)
|
19
|
+
else
|
20
|
+
highlight(code, language)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def highlight(code, language)
|
27
|
+
markup = Pygments.highlight(code, :lexer => language)
|
28
|
+
markup = markup.sub(/<div class="highlight"><pre>/,'<pre><code class="' + language + '">')
|
29
|
+
markup = markup.sub(/<\/pre><\/div>/,"</code></pre>")
|
30
|
+
markup
|
31
|
+
rescue MentosError
|
32
|
+
"<pre><code class=\"#{language}\">#{code}</code></pre>"
|
33
|
+
end
|
34
|
+
|
35
|
+
def ascii2png(code)
|
36
|
+
image_id = Digest::MD5.hexdigest(code)
|
37
|
+
png_path = @images_dir + @ditaa_root + "/#{image_id}.txt"
|
38
|
+
txt_path = @images_dir + @ditaa_root + "/#{image_id}.txt"
|
39
|
+
|
40
|
+
File.open(txt_path, 'w+') { |f| f.write(code) } unless File.exists?(png_path)
|
41
|
+
|
42
|
+
"<img src=\"#{@ditaa_root}/#{image_id}.png\" alt=\"Text Diagram\" class=\"img-rounded img-polaroid ditaa\">"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'posix/spawn'
|
2
|
+
require 'sinatra/base'
|
3
|
+
|
4
|
+
module RDaux
|
5
|
+
module Web
|
6
|
+
class Application < Sinatra::Base
|
7
|
+
attr_reader :current_section
|
8
|
+
|
9
|
+
enable :logging
|
10
|
+
|
11
|
+
get '/img/ditaa/:id.png/?' do |id|
|
12
|
+
txt_path = settings.public_folder + "/img/ditaa/#{id}.txt"
|
13
|
+
png_path = settings.public_folder + "/img/ditaa/#{id}.png"
|
14
|
+
|
15
|
+
halt(404) unless File.exists?(txt_path)
|
16
|
+
|
17
|
+
Process::waitpid(POSIX::Spawn.spawn("java", '-jar', settings.ditaa_jar, txt_path, png_path))
|
18
|
+
File.unlink(txt_path)
|
19
|
+
|
20
|
+
send_file(png_path, :status => 201)
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/' do
|
24
|
+
erb(:site)
|
25
|
+
end
|
26
|
+
|
27
|
+
def site
|
28
|
+
settings.site || halt(500)
|
29
|
+
end
|
30
|
+
|
31
|
+
def markdown
|
32
|
+
settings.markdown || halt(500)
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_markdown(markup)
|
36
|
+
markdown.render(markup)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'unicorn'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module RDaux
|
6
|
+
module Web
|
7
|
+
class Server
|
8
|
+
include Notifier
|
9
|
+
|
10
|
+
def initialize(app, logger, static_dir, options)
|
11
|
+
@app = app
|
12
|
+
@logger = logger
|
13
|
+
@static_dir = static_dir
|
14
|
+
@options = options
|
15
|
+
|
16
|
+
notifier_initialize
|
17
|
+
end
|
18
|
+
|
19
|
+
def serve(website)
|
20
|
+
with_duplicate_static_dir do |dir|
|
21
|
+
@app.configure do
|
22
|
+
@app.set(:site, website)
|
23
|
+
@app.set(:public_folder, dir)
|
24
|
+
end
|
25
|
+
|
26
|
+
Unicorn::HttpServer.new(@app, {
|
27
|
+
:listeners => @options.fetch(:bind, 'localhost:8080'),
|
28
|
+
:worker_processes => @options.fetch(:workers, 4),
|
29
|
+
:logger => @logger
|
30
|
+
}).start.join
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def with_duplicate_static_dir
|
37
|
+
Dir.mktmpdir('rdaux') do |dir|
|
38
|
+
FileUtils.cp_r(@static_dir + '/.', dir)
|
39
|
+
yield(dir)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'posix/spawn'
|
3
|
+
|
4
|
+
module RDaux
|
5
|
+
module Web
|
6
|
+
class Site
|
7
|
+
class Generator
|
8
|
+
include Notifier
|
9
|
+
|
10
|
+
def initialize(markdown, views_dir, static_dir, ditaa_jar, target_dir)
|
11
|
+
@markdown = markdown
|
12
|
+
@views_dir = views_dir
|
13
|
+
@static_dir = static_dir
|
14
|
+
@ditaa_jar = ditaa_jar
|
15
|
+
@target_dir = target_dir
|
16
|
+
|
17
|
+
@cached_templates = {}
|
18
|
+
notifier_initialize
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_static(website)
|
22
|
+
with_duplicate_static_dir do |dir|
|
23
|
+
File.open("#{dir}/index.html", 'w+') do |f|
|
24
|
+
f.write(erb(:site, :locals => {:site => website}))
|
25
|
+
end
|
26
|
+
|
27
|
+
Dir.glob("#{dir}/img/ditaa/*.txt").each do |txt_path|
|
28
|
+
Process::waitpid(POSIX::Spawn.spawn("java", '-jar', @ditaa_jar, txt_path))
|
29
|
+
File.unlink(txt_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
if File.directory?(@target_dir)
|
33
|
+
FileUtils.cp_r("#{dir}/.", @target_dir)
|
34
|
+
else
|
35
|
+
FileUtils.mv(dir, @target_dir)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def with_duplicate_static_dir
|
43
|
+
dir = Dir.mktmpdir('rdaux')
|
44
|
+
|
45
|
+
FileUtils.cp_r("#{@static_dir}/.", dir)
|
46
|
+
yield(dir)
|
47
|
+
ensure
|
48
|
+
FileUtils.remove_entry_secure(dir) if File.directory?(dir)
|
49
|
+
end
|
50
|
+
|
51
|
+
def erb(view, options)
|
52
|
+
unless @cached_templates.has_key?(view)
|
53
|
+
@cached_templates[view] = Tilt[:erb].new("#{@views_dir}/#{view}.erb", 1, {
|
54
|
+
:default_encoding => 'UTF-8'
|
55
|
+
})
|
56
|
+
end
|
57
|
+
@cached_templates[view].render(self, options.fetch(:locals, {}))
|
58
|
+
end
|
59
|
+
|
60
|
+
def render_markdown(markup)
|
61
|
+
@markdown.render(markup)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module RDaux
|
2
|
+
module Web
|
3
|
+
class Site
|
4
|
+
attr_reader :title, :description, :author, :root
|
5
|
+
|
6
|
+
class Section
|
7
|
+
attr_reader :key
|
8
|
+
attr_writer :contents
|
9
|
+
attr_accessor :sections
|
10
|
+
|
11
|
+
def initialize(key)
|
12
|
+
@key = key
|
13
|
+
end
|
14
|
+
|
15
|
+
def title
|
16
|
+
@title ||= @key.split('-').map(&:capitalize).join(' ')
|
17
|
+
end
|
18
|
+
|
19
|
+
def contents
|
20
|
+
@contents && @contents.read
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_children?
|
24
|
+
@sections && !@sections.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_contents?
|
28
|
+
!@contents.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(title, description, author, root)
|
33
|
+
@title = title
|
34
|
+
@description = description
|
35
|
+
@author = author
|
36
|
+
@root = root
|
37
|
+
end
|
38
|
+
|
39
|
+
def sections
|
40
|
+
find_sections(@root)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def find_sections(root)
|
46
|
+
root.children.inject({}) do |sections, path|
|
47
|
+
unless path.symlink?
|
48
|
+
if path.file? && path.extname == '.md'
|
49
|
+
key = basename_to_key(base_filename(path))
|
50
|
+
section = get_or_create_section(key, sections)
|
51
|
+
|
52
|
+
section.contents = path
|
53
|
+
elsif path.directory? && !path.basename.to_s.start_with?('.')
|
54
|
+
key = basename_to_key(base_dirname(path))
|
55
|
+
section = get_or_create_section(key, sections)
|
56
|
+
|
57
|
+
section.sections = find_sections(path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
sections
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_or_create_section(key, sections)
|
66
|
+
unless sections.has_key?(key)
|
67
|
+
sections[key] = Section.new(key)
|
68
|
+
end
|
69
|
+
|
70
|
+
sections[key]
|
71
|
+
end
|
72
|
+
|
73
|
+
def basename_to_key(basename)
|
74
|
+
basename.split(/[\_\- ]/).map(&:downcase).join('-')
|
75
|
+
end
|
76
|
+
|
77
|
+
def base_filename(path)
|
78
|
+
path.sub_ext('').basename.to_s.sub(/^[0-9]*[\_\-]?/, '')
|
79
|
+
end
|
80
|
+
|
81
|
+
def base_dirname(path)
|
82
|
+
path.basename.to_s.sub(/^[0-9]*[\_\-]?/, '')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% for key, section in sections %>
|
2
|
+
<a name="<%= base %><%= section.key %>"></a>
|
3
|
+
<% if section.has_contents? %>
|
4
|
+
<section class="docs-section">
|
5
|
+
<%= render_markdown(section.contents) %>
|
6
|
+
</section>
|
7
|
+
<% end %>
|
8
|
+
<% if section.has_children? %>
|
9
|
+
<%= erb(:docs, :locals => { :sections => section.sections, :base => section.key + '.' }) %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% for key, section in sections %>
|
2
|
+
<li>
|
3
|
+
<a href="#<%= base %><%= section.key %>" title="<%= section.title %>"><i class="icon-chevron-right"></i><%= section.title %></a>
|
4
|
+
<% if section.has_children? %>
|
5
|
+
<ul class="nav nav-list">
|
6
|
+
<%= erb(:nav, :locals => { :sections => section.sections, :base => section.key + '.' }) %>
|
7
|
+
</ul>
|
8
|
+
<% end %>
|
9
|
+
</li>
|
10
|
+
<% end %>
|