bunto 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.markdown +59 -0
  4. data/bin/bunto +51 -0
  5. data/lib/bunto.rb +179 -0
  6. data/lib/bunto/cleaner.rb +105 -0
  7. data/lib/bunto/collection.rb +205 -0
  8. data/lib/bunto/command.rb +65 -0
  9. data/lib/bunto/commands/build.rb +77 -0
  10. data/lib/bunto/commands/clean.rb +42 -0
  11. data/lib/bunto/commands/doctor.rb +114 -0
  12. data/lib/bunto/commands/help.rb +31 -0
  13. data/lib/bunto/commands/new.rb +82 -0
  14. data/lib/bunto/commands/serve.rb +204 -0
  15. data/lib/bunto/commands/serve/servlet.rb +61 -0
  16. data/lib/bunto/configuration.rb +323 -0
  17. data/lib/bunto/converter.rb +48 -0
  18. data/lib/bunto/converters/identity.rb +21 -0
  19. data/lib/bunto/converters/markdown.rb +92 -0
  20. data/lib/bunto/converters/markdown/kramdown_parser.rb +117 -0
  21. data/lib/bunto/converters/markdown/rdiscount_parser.rb +33 -0
  22. data/lib/bunto/converters/markdown/redcarpet_parser.rb +102 -0
  23. data/lib/bunto/converters/smartypants.rb +34 -0
  24. data/lib/bunto/convertible.rb +297 -0
  25. data/lib/bunto/deprecator.rb +46 -0
  26. data/lib/bunto/document.rb +444 -0
  27. data/lib/bunto/drops/bunto_drop.rb +21 -0
  28. data/lib/bunto/drops/collection_drop.rb +22 -0
  29. data/lib/bunto/drops/document_drop.rb +27 -0
  30. data/lib/bunto/drops/drop.rb +176 -0
  31. data/lib/bunto/drops/site_drop.rb +38 -0
  32. data/lib/bunto/drops/unified_payload_drop.rb +25 -0
  33. data/lib/bunto/drops/url_drop.rb +83 -0
  34. data/lib/bunto/entry_filter.rb +72 -0
  35. data/lib/bunto/errors.rb +10 -0
  36. data/lib/bunto/excerpt.rb +127 -0
  37. data/lib/bunto/external.rb +59 -0
  38. data/lib/bunto/filters.rb +367 -0
  39. data/lib/bunto/frontmatter_defaults.rb +188 -0
  40. data/lib/bunto/generator.rb +3 -0
  41. data/lib/bunto/hooks.rb +101 -0
  42. data/lib/bunto/layout.rb +49 -0
  43. data/lib/bunto/liquid_extensions.rb +22 -0
  44. data/lib/bunto/liquid_renderer.rb +39 -0
  45. data/lib/bunto/liquid_renderer/file.rb +50 -0
  46. data/lib/bunto/liquid_renderer/table.rb +94 -0
  47. data/lib/bunto/log_adapter.rb +115 -0
  48. data/lib/bunto/mime.types +800 -0
  49. data/lib/bunto/page.rb +180 -0
  50. data/lib/bunto/plugin.rb +96 -0
  51. data/lib/bunto/plugin_manager.rb +95 -0
  52. data/lib/bunto/post.rb +329 -0
  53. data/lib/bunto/publisher.rb +21 -0
  54. data/lib/bunto/reader.rb +126 -0
  55. data/lib/bunto/readers/collection_reader.rb +20 -0
  56. data/lib/bunto/readers/data_reader.rb +69 -0
  57. data/lib/bunto/readers/layout_reader.rb +53 -0
  58. data/lib/bunto/readers/page_reader.rb +21 -0
  59. data/lib/bunto/readers/post_reader.rb +62 -0
  60. data/lib/bunto/readers/static_file_reader.rb +21 -0
  61. data/lib/bunto/regenerator.rb +175 -0
  62. data/lib/bunto/related_posts.rb +56 -0
  63. data/lib/bunto/renderer.rb +191 -0
  64. data/lib/bunto/site.rb +391 -0
  65. data/lib/bunto/static_file.rb +141 -0
  66. data/lib/bunto/stevenson.rb +58 -0
  67. data/lib/bunto/tags/highlight.rb +122 -0
  68. data/lib/bunto/tags/include.rb +190 -0
  69. data/lib/bunto/tags/post_url.rb +88 -0
  70. data/lib/bunto/url.rb +136 -0
  71. data/lib/bunto/utils.rb +287 -0
  72. data/lib/bunto/utils/ansi.rb +59 -0
  73. data/lib/bunto/utils/platforms.rb +30 -0
  74. data/lib/bunto/version.rb +3 -0
  75. data/lib/site_template/.gitignore +3 -0
  76. data/lib/site_template/_config.yml +21 -0
  77. data/lib/site_template/_includes/footer.html +38 -0
  78. data/lib/site_template/_includes/head.html +12 -0
  79. data/lib/site_template/_includes/header.html +27 -0
  80. data/lib/site_template/_includes/icon-github.html +1 -0
  81. data/lib/site_template/_includes/icon-github.svg +1 -0
  82. data/lib/site_template/_includes/icon-twitter.html +1 -0
  83. data/lib/site_template/_includes/icon-twitter.svg +1 -0
  84. data/lib/site_template/_layouts/default.html +20 -0
  85. data/lib/site_template/_layouts/page.html +14 -0
  86. data/lib/site_template/_layouts/post.html +15 -0
  87. data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +25 -0
  88. data/lib/site_template/_sass/_base.scss +206 -0
  89. data/lib/site_template/_sass/_layout.scss +242 -0
  90. data/lib/site_template/_sass/_syntax-highlighting.scss +71 -0
  91. data/lib/site_template/about.md +15 -0
  92. data/lib/site_template/css/main.scss +53 -0
  93. data/lib/site_template/feed.xml +30 -0
  94. data/lib/site_template/index.html +23 -0
  95. metadata +252 -0
@@ -0,0 +1,65 @@
1
+ module Bunto
2
+ class Command
3
+ class << self
4
+ # A list of subclasses of Bunto::Command
5
+ def subclasses
6
+ @subclasses ||= []
7
+ end
8
+
9
+ # Keep a list of subclasses of Bunto::Command every time it's inherited
10
+ # Called automatically.
11
+ #
12
+ # base - the subclass
13
+ #
14
+ # Returns nothing
15
+ def inherited(base)
16
+ subclasses << base
17
+ super(base)
18
+ end
19
+
20
+ # Run Site#process and catch errors
21
+ #
22
+ # site - the Bunto::Site object
23
+ #
24
+ # Returns nothing
25
+ def process_site(site)
26
+ site.process
27
+ rescue Bunto::Errors::FatalException => e
28
+ Bunto.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
29
+ Bunto.logger.error "", "------------------------------------"
30
+ Bunto.logger.error "", e.message
31
+ exit(1)
32
+ end
33
+
34
+ # Create a full Bunto configuration with the options passed in as overrides
35
+ #
36
+ # options - the configuration overrides
37
+ #
38
+ # Returns a full Bunto configuration
39
+ def configuration_from_options(options)
40
+ Bunto.configuration(options)
41
+ end
42
+
43
+ # Add common options to a command for building configuration
44
+ #
45
+ # c - the Bunto::Command to add these options to
46
+ #
47
+ # Returns nothing
48
+ def add_build_options(c)
49
+ c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
50
+ c.option 'destination', '-d', '--destination DESTINATION', 'The current folder will be generated into DESTINATION'
51
+ c.option 'source', '-s', '--source SOURCE', 'Custom source directory'
52
+ c.option 'future', '--future', 'Publishes posts with a future date'
53
+ c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
54
+ c.option 'watch', '-w', '--[no-]watch', 'Watch for changes and rebuild'
55
+ c.option 'force_polling', '--force_polling', 'Force watch to use polling'
56
+ c.option 'lsi', '--lsi', 'Use LSI for improved related posts'
57
+ c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder'
58
+ c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished'
59
+ c.option 'quiet', '-q', '--quiet', 'Silence output.'
60
+ c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
61
+ c.option 'incremental', '-I', '--incremental', 'Enable incremental rebuild.'
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,77 @@
1
+ module Bunto
2
+ module Commands
3
+ class Build < Command
4
+ class << self
5
+ # Create the Mercenary command for the Bunto CLI for this Command
6
+ def init_with_program(prog)
7
+ prog.command(:build) do |c|
8
+ c.syntax 'build [options]'
9
+ c.description 'Build your site'
10
+ c.alias :b
11
+
12
+ add_build_options(c)
13
+
14
+ c.action do |_, options|
15
+ options["serving"] = false
16
+ Bunto::Commands::Build.process(options)
17
+ end
18
+ end
19
+ end
20
+
21
+ # Build your bunto site
22
+ # Continuously watch if `watch` is set to true in the config.
23
+ def process(options)
24
+ # Adjust verbosity quickly
25
+ Bunto.logger.adjust_verbosity(options)
26
+
27
+ options = configuration_from_options(options)
28
+ site = Bunto::Site.new(options)
29
+
30
+ if options.fetch('skip_initial_build', false)
31
+ Bunto.logger.warn "Build Warning:", "Skipping the initial build. This may result in an out-of-date site."
32
+ else
33
+ build(site, options)
34
+ end
35
+
36
+ if options.fetch('detach', false)
37
+ Bunto.logger.info "Auto-regeneration:", "disabled when running server detached."
38
+ elsif options.fetch('watch', false)
39
+ watch(site, options)
40
+ else
41
+ Bunto.logger.info "Auto-regeneration:", "disabled. Use --watch to enable."
42
+ end
43
+ end
44
+
45
+ # Build your Bunto site.
46
+ #
47
+ # site - the Bunto::Site instance to build
48
+ # options - A Hash of options passed to the command
49
+ #
50
+ # Returns nothing.
51
+ def build(site, options)
52
+ t = Time.now
53
+ source = options['source']
54
+ destination = options['destination']
55
+ incremental = options['incremental']
56
+ Bunto.logger.info "Source:", source
57
+ Bunto.logger.info "Destination:", destination
58
+ Bunto.logger.info "Incremental build:", (incremental ? "enabled" : "disabled. Enable with --incremental")
59
+ Bunto.logger.info "Generating..."
60
+ process_site(site)
61
+ Bunto.logger.info "", "done in #{(Time.now - t).round(3)} seconds."
62
+ end
63
+
64
+ # Private: Watch for file changes and rebuild the site.
65
+ #
66
+ # site - A Bunto::Site instance
67
+ # options - A Hash of options passed to the command
68
+ #
69
+ # Returns nothing.
70
+ def watch(_site, options)
71
+ External.require_with_graceful_fail 'bunto-watch'
72
+ Bunto::Watcher.watch(options)
73
+ end
74
+ end # end of class << self
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,42 @@
1
+ module Bunto
2
+ module Commands
3
+ class Clean < Command
4
+ class << self
5
+ def init_with_program(prog)
6
+ prog.command(:clean) do |c|
7
+ c.syntax 'clean [subcommand]'
8
+ c.description 'Clean the site (removes site output and metadata file) without building.'
9
+
10
+ add_build_options(c)
11
+
12
+ c.action do |_, options|
13
+ Bunto::Commands::Clean.process(options)
14
+ end
15
+ end
16
+ end
17
+
18
+ def process(options)
19
+ options = configuration_from_options(options)
20
+ destination = options['destination']
21
+ metadata_file = File.join(options['source'], '.bunto-metadata')
22
+
23
+ if File.directory? destination
24
+ Bunto.logger.info "Cleaning #{destination}..."
25
+ FileUtils.rm_rf(destination)
26
+ Bunto.logger.info "", "done."
27
+ else
28
+ Bunto.logger.info "Nothing to do for #{destination}."
29
+ end
30
+
31
+ if File.file? metadata_file
32
+ Bunto.logger.info "Removing #{metadata_file}..."
33
+ FileUtils.rm_rf(metadata_file)
34
+ Bunto.logger.info "", "done."
35
+ else
36
+ Bunto.logger.info "Nothing to do for #{metadata_file}."
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,114 @@
1
+ module Bunto
2
+ module Commands
3
+ class Doctor < Command
4
+ class << self
5
+ def init_with_program(prog)
6
+ prog.command(:doctor) do |c|
7
+ c.syntax 'doctor'
8
+ c.description 'Search site and print specific deprecation warnings'
9
+ c.alias(:hyde)
10
+
11
+ c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
12
+
13
+ c.action do |_, options|
14
+ Bunto::Commands::Doctor.process(options)
15
+ end
16
+ end
17
+ end
18
+
19
+ def process(options)
20
+ site = Bunto::Site.new(configuration_from_options(options))
21
+ site.read
22
+
23
+ if healthy?(site)
24
+ Bunto.logger.info "Your test results", "are in. Everything looks fine."
25
+ else
26
+ abort
27
+ end
28
+ end
29
+
30
+ def healthy?(site)
31
+ [
32
+ fsnotify_buggy?(site),
33
+ !deprecated_relative_permalinks(site),
34
+ !conflicting_urls(site),
35
+ !urls_only_differ_by_case(site)
36
+ ].all?
37
+ end
38
+
39
+ def deprecated_relative_permalinks(site)
40
+ if site.config['relative_permalinks']
41
+ Bunto::Deprecator.deprecation_message "Your site still uses relative" \
42
+ " permalinks, which was removed in" \
43
+ " Bunto v3.0.0."
44
+ return true
45
+ end
46
+ end
47
+
48
+ def conflicting_urls(site)
49
+ conflicting_urls = false
50
+ urls = {}
51
+ urls = collect_urls(urls, site.pages, site.dest)
52
+ urls = collect_urls(urls, site.posts.docs, site.dest)
53
+ urls.each do |url, paths|
54
+ next unless paths.size > 1
55
+ conflicting_urls = true
56
+ Bunto.logger.warn "Conflict:", "The URL '#{url}' is the destination" \
57
+ " for the following pages: #{paths.join(", ")}"
58
+ end
59
+ conflicting_urls
60
+ end
61
+
62
+ def fsnotify_buggy?(_site)
63
+ return true unless Utils::Platforms.osx?
64
+ if Dir.pwd != `pwd`.strip
65
+ Bunto.logger.error " " + <<-STR.strip.gsub(/\n\s+/, "\n ")
66
+ We have detected that there might be trouble using fsevent on your
67
+ operating system, you can read https://github.com/thibaudgg/rb-fsevent/wiki/no-fsevents-fired-(OSX-bug)
68
+ for possible work arounds or you can work around it immediately
69
+ with `--force-polling`.
70
+ STR
71
+
72
+ false
73
+ end
74
+
75
+ true
76
+ end
77
+
78
+ def urls_only_differ_by_case(site)
79
+ urls_only_differ_by_case = false
80
+ urls = case_insensitive_urls(site.pages + site.docs_to_write, site.dest)
81
+ urls.each do |case_insensitive_url, real_urls|
82
+ next unless real_urls.uniq.size > 1
83
+ urls_only_differ_by_case = true
84
+ Bunto.logger.warn "Warning:", "The following URLs only differ" \
85
+ " by case. On a case-insensitive file system one of the URLs" \
86
+ " will be overwritten by the other: #{real_urls.join(", ")}"
87
+ end
88
+ urls_only_differ_by_case
89
+ end
90
+
91
+ private
92
+ def collect_urls(urls, things, destination)
93
+ things.each do |thing|
94
+ dest = thing.destination(destination)
95
+ if urls[dest]
96
+ urls[dest] << thing.path
97
+ else
98
+ urls[dest] = [thing.path]
99
+ end
100
+ end
101
+ urls
102
+ end
103
+
104
+ def case_insensitive_urls(things, destination)
105
+ things.inject({}) do |memo, thing|
106
+ dest = thing.destination(destination)
107
+ (memo[dest.downcase] ||= []) << dest
108
+ memo
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,31 @@
1
+ module Bunto
2
+ module Commands
3
+ class Help < Command
4
+ class << self
5
+ def init_with_program(prog)
6
+ prog.command(:help) do |c|
7
+ c.syntax 'help [subcommand]'
8
+ c.description 'Show the help message, optionally for a given subcommand.'
9
+
10
+ c.action do |args, _|
11
+ cmd = (args.first || "").to_sym
12
+ if args.empty?
13
+ puts prog
14
+ elsif prog.has_command? cmd
15
+ puts prog.commands[cmd]
16
+ else
17
+ invalid_command(prog, cmd)
18
+ abort
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def invalid_command(prog, cmd)
25
+ Bunto.logger.error "Error:", "Hmm... we don't know what the '#{cmd}' command is."
26
+ Bunto.logger.info "Valid commands:", prog.commands.keys.join(", ")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,82 @@
1
+ require 'erb'
2
+
3
+ module Bunto
4
+ module Commands
5
+ class New < Command
6
+ class << self
7
+ def init_with_program(prog)
8
+ prog.command(:new) do |c|
9
+ c.syntax 'new PATH'
10
+ c.description 'Creates a new Bunto site scaffold in PATH'
11
+
12
+ c.option 'force', '--force', 'Force creation even if PATH already exists'
13
+ c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
14
+
15
+ c.action do |args, options|
16
+ Bunto::Commands::New.process(args, options)
17
+ end
18
+ end
19
+ end
20
+
21
+ def process(args, options = {})
22
+ raise ArgumentError.new('You must specify a path.') if args.empty?
23
+
24
+ new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
25
+ FileUtils.mkdir_p new_blog_path
26
+ if preserve_source_location?(new_blog_path, options)
27
+ Bunto.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
28
+ end
29
+
30
+ if options["blank"]
31
+ create_blank_site new_blog_path
32
+ else
33
+ create_sample_files new_blog_path
34
+
35
+ File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
36
+ f.write(scaffold_post_content)
37
+ end
38
+ end
39
+
40
+ Bunto.logger.info "New bunto site installed in #{new_blog_path}."
41
+ end
42
+
43
+ def create_blank_site(path)
44
+ Dir.chdir(path) do
45
+ FileUtils.mkdir(%w(_layouts _posts _drafts))
46
+ FileUtils.touch("index.html")
47
+ end
48
+ end
49
+
50
+ def scaffold_post_content
51
+ ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
52
+ end
53
+
54
+ # Internal: Gets the filename of the sample post to be created
55
+ #
56
+ # Returns the filename of the sample post, as a String
57
+ def initialized_post_name
58
+ "_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-bunto.markdown"
59
+ end
60
+
61
+ private
62
+
63
+ def preserve_source_location?(path, options)
64
+ !options["force"] && !Dir["#{path}/**/*"].empty?
65
+ end
66
+
67
+ def create_sample_files(path)
68
+ FileUtils.cp_r site_template + '/.', path
69
+ FileUtils.rm File.expand_path(scaffold_path, path)
70
+ end
71
+
72
+ def site_template
73
+ File.expand_path("../../site_template", File.dirname(__FILE__))
74
+ end
75
+
76
+ def scaffold_path
77
+ "_posts/0000-00-00-welcome-to-bunto.markdown.erb"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,204 @@
1
+ module Bunto
2
+ module Commands
3
+ class Serve < Command
4
+ class << self
5
+ COMMAND_OPTIONS = {
6
+ "ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."],
7
+ "host" => ["host", "-H", "--host [HOST]", "Host to bind to"],
8
+ "open_url" => ["-o", "--open-url", "Launch your browser with your site."],
9
+ "detach" => ["-B", "--detach", "Run the server in the background (detach)"],
10
+ "ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."],
11
+ "port" => ["-P", "--port [PORT]", "Port to listen on"],
12
+ "baseurl" => ["-b", "--baseurl [URL]", "Base URL"],
13
+ "skip_initial_build" => ["skip_initial_build", "--skip-initial-build",
14
+ "Skips the initial site build which occurs before the server is started."]
15
+ }
16
+
17
+ #
18
+
19
+ def init_with_program(prog)
20
+ prog.command(:serve) do |cmd|
21
+ cmd.description "Serve your site locally"
22
+ cmd.syntax "serve [options]"
23
+ cmd.alias :server
24
+ cmd.alias :s
25
+
26
+ add_build_options(cmd)
27
+ COMMAND_OPTIONS.each do |key, val|
28
+ cmd.option key, *val
29
+ end
30
+
31
+ cmd.action do |_, opts|
32
+ opts["serving"] = true
33
+ opts["watch" ] = true unless opts.key?("watch")
34
+ Build.process(opts)
35
+ Serve.process(opts)
36
+ end
37
+ end
38
+ end
39
+
40
+ #
41
+
42
+ def process(opts)
43
+ opts = configuration_from_options(opts)
44
+ destination = opts["destination"]
45
+ setup(destination)
46
+
47
+ server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
48
+ server.mount(opts["baseurl"], Servlet, destination, file_handler_opts)
49
+ Bunto.logger.info "Server address:", server_address(server, opts)
50
+ launch_browser server, opts if opts["open_url"]
51
+ boot_or_detach server, opts
52
+ end
53
+
54
+ # Do a base pre-setup of WEBRick so that everything is in place
55
+ # when we get ready to party, checking for an setting up an error page
56
+ # and making sure our destination exists.
57
+
58
+ private
59
+ def setup(destination)
60
+ require_relative "serve/servlet"
61
+
62
+ FileUtils.mkdir_p(destination)
63
+ if File.exist?(File.join(destination, "404.html"))
64
+ WEBrick::HTTPResponse.class_eval do
65
+ def create_error_page
66
+ @header["Content-Type"] = "text/html; charset=UTF-8"
67
+ @body = IO.read(File.join(@config[:DocumentRoot], "404.html"))
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ #
74
+
75
+ private
76
+ def webrick_opts(opts)
77
+ opts = {
78
+ :BuntoOptions => opts,
79
+ :DoNotReverseLookup => true,
80
+ :MimeTypes => mime_types,
81
+ :DocumentRoot => opts["destination"],
82
+ :StartCallback => start_callback(opts["detach"]),
83
+ :BindAddress => opts["host"],
84
+ :Port => opts["port"],
85
+ :DirectoryIndex => %W(
86
+ index.htm
87
+ index.html
88
+ index.rhtml
89
+ index.cgi
90
+ index.xml
91
+ )
92
+ }
93
+
94
+ enable_ssl(opts)
95
+ enable_logging(opts)
96
+ opts
97
+ end
98
+
99
+ # Recreate NondisclosureName under utf-8 circumstance
100
+
101
+ private
102
+ def file_handler_opts
103
+ WEBrick::Config::FileHandler.merge({
104
+ :FancyIndexing => true,
105
+ :NondisclosureName => [
106
+ '.ht*', '~*'
107
+ ]
108
+ })
109
+ end
110
+
111
+ #
112
+
113
+ private
114
+ def server_address(server, opts)
115
+ address = server.config[:BindAddress]
116
+ baseurl = "#{opts["baseurl"]}/" if opts["baseurl"]
117
+ port = server.config[:Port]
118
+
119
+ "http://#{address}:#{port}#{baseurl}"
120
+ end
121
+
122
+ #
123
+
124
+ private
125
+ def launch_browser(server, opts)
126
+ command =
127
+ if Utils::Platforms.windows?
128
+ "start"
129
+ elsif Utils::Platforms.osx?
130
+ "open"
131
+ else
132
+ "xdg-open"
133
+ end
134
+ system command, server_address(server, opts)
135
+ end
136
+
137
+ # Keep in our area with a thread or detach the server as requested
138
+ # by the user. This method determines what we do based on what you
139
+ # ask us to do.
140
+
141
+ private
142
+ def boot_or_detach(server, opts)
143
+ if opts["detach"]
144
+ pid = Process.fork do
145
+ server.start
146
+ end
147
+
148
+ Process.detach(pid)
149
+ Bunto.logger.info "Server detached with pid '#{pid}'.", \
150
+ "Run `pkill -f bunto' or `kill -9 #{pid}' to stop the server."
151
+ else
152
+ t = Thread.new { server.start }
153
+ trap("INT") { server.shutdown }
154
+ t.join
155
+ end
156
+ end
157
+
158
+ # Make the stack verbose if the user requests it.
159
+
160
+ private
161
+ def enable_logging(opts)
162
+ opts[:AccessLog] = []
163
+ level = WEBrick::Log.const_get(opts[:BuntoOptions]["verbose"] ? :DEBUG : :WARN)
164
+ opts[:Logger] = WEBrick::Log.new($stdout, level)
165
+ end
166
+
167
+ # Add SSL to the stack if the user triggers --enable-ssl and they
168
+ # provide both types of certificates commonly needed. Raise if they
169
+ # forget to add one of the certificates.
170
+
171
+ private
172
+ def enable_ssl(opts)
173
+ return if !opts[:BuntoOptions]["ssl_cert"] && !opts[:BuntoOptions]["ssl_key"]
174
+ if !opts[:BuntoOptions]["ssl_cert"] || !opts[:BuntoOptions]["ssl_key"]
175
+ raise RuntimeError, "--ssl-cert or --ssl-key missing."
176
+ end
177
+
178
+ require "openssl"
179
+ require "webrick/https"
180
+ source_key = Bunto.sanitized_path(opts[:BuntoOptions]["source"], opts[:BuntoOptions]["ssl_key" ])
181
+ source_certificate = Bunto.sanitized_path(opts[:BuntoOptions]["source"], opts[:BuntoOptions]["ssl_cert"])
182
+ opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read(source_certificate))
183
+ opts[:SSLPrivateKey ] = OpenSSL::PKey::RSA.new(File.read(source_key))
184
+ opts[:EnableSSL] = true
185
+ end
186
+
187
+ private
188
+ def start_callback(detached)
189
+ unless detached
190
+ proc do
191
+ Bunto.logger.info("Server running...", "press ctrl-c to stop.")
192
+ end
193
+ end
194
+ end
195
+
196
+ private
197
+ def mime_types
198
+ file = File.expand_path('../mime.types', File.dirname(__FILE__))
199
+ WEBrick::HTTPUtils.load_mime_types(file)
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end