bunto 1.0.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.
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