jekyll 2.0.0.alpha.1 → 2.0.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jekyll might be problematic. Click here for more details.

Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -0
  3. data/.travis.yml +27 -0
  4. data/History.markdown +66 -1
  5. data/LICENSE +2 -2
  6. data/README.markdown +2 -2
  7. data/Rakefile +4 -44
  8. data/bin/jekyll +10 -113
  9. data/docs/jp/CONTRIBUTING.jp.markdown +93 -0
  10. data/docs/jp/README.jp.markdown +69 -0
  11. data/features/create_sites.feature +12 -12
  12. data/features/drafts.feature +23 -2
  13. data/features/embed_filters.feature +7 -5
  14. data/features/include_tag.feature +7 -7
  15. data/features/markdown.feature +4 -4
  16. data/features/pagination.feature +2 -2
  17. data/features/permalinks.feature +7 -7
  18. data/features/post_data.feature +21 -21
  19. data/features/post_excerpts.feature +6 -6
  20. data/features/site_configuration.feature +17 -17
  21. data/features/site_data.feature +15 -15
  22. data/features/step_definitions/jekyll_steps.rb +4 -4
  23. data/features/support/env.rb +2 -2
  24. data/jekyll.gemspec +17 -284
  25. data/lib/jekyll.rb +21 -5
  26. data/lib/jekyll/command.rb +72 -20
  27. data/lib/jekyll/commands/build.rb +82 -58
  28. data/lib/jekyll/commands/docs.rb +30 -0
  29. data/lib/jekyll/commands/doctor.rb +18 -1
  30. data/lib/jekyll/commands/new.rb +19 -6
  31. data/lib/jekyll/commands/serve.rb +80 -49
  32. data/lib/jekyll/configuration.rb +3 -3
  33. data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -1
  34. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +1 -0
  35. data/lib/jekyll/convertible.rb +19 -21
  36. data/lib/jekyll/draft.rb +5 -0
  37. data/lib/jekyll/excerpt.rb +5 -5
  38. data/lib/jekyll/layout.rb +2 -2
  39. data/lib/jekyll/layout_reader.rb +15 -2
  40. data/lib/jekyll/page.rb +17 -17
  41. data/lib/jekyll/post.rb +33 -33
  42. data/lib/jekyll/related_posts.rb +5 -5
  43. data/lib/jekyll/site.rb +84 -85
  44. data/lib/jekyll/static_file.rb +13 -0
  45. data/lib/jekyll/stevenson.rb +1 -1
  46. data/lib/jekyll/tags/highlight.rb +16 -6
  47. data/lib/jekyll/tags/include.rb +17 -17
  48. data/lib/jekyll/url.rb +2 -0
  49. data/lib/jekyll/utils.rb +79 -0
  50. data/lib/jekyll/version.rb +3 -0
  51. data/lib/site_template/_config.yml +3 -1
  52. data/lib/site_template/_includes/footer.html +61 -0
  53. data/lib/site_template/_includes/head.html +12 -0
  54. data/lib/site_template/_includes/header.html +27 -0
  55. data/lib/site_template/_layouts/default.html +9 -34
  56. data/lib/site_template/_layouts/page.html +14 -0
  57. data/lib/site_template/_layouts/post.html +11 -5
  58. data/lib/site_template/_posts/0000-00-00-this-post-demonstrates-post-content-styles.md +88 -0
  59. data/lib/site_template/about/index.md +10 -0
  60. data/lib/site_template/css/main.css +333 -100
  61. data/lib/site_template/feed.xml +21 -0
  62. data/lib/site_template/index.html +8 -4
  63. data/lib/site_template/projects/index.md +14 -0
  64. data/script/cibuild +0 -1
  65. data/script/rebund +1 -1
  66. data/site/_includes/analytics.html +2 -2
  67. data/site/_includes/css/normalize.css +1 -1
  68. data/site/_includes/css/style.css +28 -4
  69. data/site/_includes/docs_option.html +1 -1
  70. data/site/_includes/docs_ul.html +3 -3
  71. data/site/_includes/footer.html +1 -1
  72. data/site/_includes/header.html +2 -2
  73. data/site/_includes/news_item.html +1 -1
  74. data/site/_includes/primary-nav-items.html +4 -4
  75. data/site/_includes/section_nav.html +2 -2
  76. data/site/_includes/top.html +6 -7
  77. data/site/_layouts/news_item.html +1 -1
  78. data/site/_posts/2013-07-25-jekyll-1-0-4-released.markdown +1 -1
  79. data/site/_posts/2013-07-25-jekyll-1-1-2-released.markdown +1 -1
  80. data/site/_posts/2013-09-14-jekyll-1-2-1-released.markdown +1 -1
  81. data/site/_posts/2014-03-24-jekyll-1-5-0-released.markdown +19 -0
  82. data/site/docs/assets.md +14 -0
  83. data/site/docs/configuration.md +65 -56
  84. data/site/docs/contributing.md +7 -2
  85. data/site/docs/deployment-methods.md +1 -1
  86. data/site/docs/github-pages.md +1 -1
  87. data/site/docs/history.md +21 -0
  88. data/site/docs/index.md +7 -1
  89. data/site/docs/installation.md +28 -0
  90. data/site/docs/migrations.md +1 -1
  91. data/site/docs/plugins.md +6 -0
  92. data/site/docs/structure.md +3 -3
  93. data/site/docs/templates.md +44 -44
  94. data/site/docs/usage.md +1 -1
  95. data/site/docs/variables.md +15 -2
  96. data/site/favicon.png +0 -0
  97. data/site/feed.xml +0 -1
  98. data/site/img/article-footer.png +0 -0
  99. data/site/img/footer-arrow.png +0 -0
  100. data/site/img/footer-logo.png +0 -0
  101. data/site/img/logo-2x.png +0 -0
  102. data/site/img/octojekyll.png +0 -0
  103. data/site/img/tube.png +0 -0
  104. data/site/img/tube1x.png +0 -0
  105. data/site/index.html +5 -5
  106. data/site/js/modernizr-2.7.1.min.js +4 -0
  107. data/test/helper.rb +11 -0
  108. data/test/source/_drafts/draft-properties.text +11 -0
  109. data/test/source/_posts/2011-04-12-md-extension.md +1 -1
  110. data/test/source/_posts/2014-01-06-permalink-traversal.md +5 -0
  111. data/test/source/exploit.md +5 -0
  112. data/test/source/static_files.html +4 -0
  113. data/test/test_configuration.rb +2 -2
  114. data/test/test_draft.rb +56 -0
  115. data/test/test_excerpt.rb +2 -2
  116. data/test/test_filters.rb +1 -1
  117. data/test/test_generated_site.rb +10 -1
  118. data/test/test_kramdown.rb +1 -1
  119. data/test/test_layout_reader.rb +17 -0
  120. data/test/test_page.rb +10 -0
  121. data/test/test_pager.rb +4 -2
  122. data/test/test_path_sanitization.rb +14 -0
  123. data/test/test_post.rb +12 -1
  124. data/test/test_sass.rb +1 -64
  125. data/test/test_site.rb +26 -1
  126. data/test/test_tags.rb +39 -2
  127. data/test/{test_core_ext.rb → test_utils.rb} +12 -12
  128. metadata +200 -86
  129. data/lib/jekyll/converters/sass.rb +0 -58
  130. data/lib/jekyll/core_ext.rb +0 -55
  131. data/lib/site_template/css/syntax.css +0 -60
  132. data/site/js/modernizr-2.5.3.min.js +0 -4
@@ -27,10 +27,10 @@ require 'liquid'
27
27
  require 'maruku'
28
28
  require 'colorator'
29
29
  require 'toml'
30
- require 'sass'
31
30
 
32
31
  # internal requires
33
- require 'jekyll/core_ext'
32
+ require 'jekyll/version'
33
+ require 'jekyll/utils'
34
34
  require 'jekyll/stevenson'
35
35
  require 'jekyll/deprecator'
36
36
  require 'jekyll/configuration'
@@ -64,12 +64,11 @@ require_all 'jekyll/tags'
64
64
 
65
65
  # plugins
66
66
  require 'jekyll-coffeescript'
67
+ require 'jekyll-sass-converter'
67
68
 
68
69
  SafeYAML::OPTIONS[:suppress_warnings] = true
69
70
 
70
71
  module Jekyll
71
- VERSION = '2.0.0.alpha.1'
72
-
73
72
  # Public: Generate a Jekyll configuration Hash by merging the default
74
73
  # options with anything in _config.yml, and adding the given options on top.
75
74
  #
@@ -84,7 +83,7 @@ module Jekyll
84
83
  config = config.read_config_files(config.config_files(override))
85
84
 
86
85
  # Merge DEFAULTS < _config.yml < override
87
- config = config.deep_merge(override).stringify_keys
86
+ config = Utils.deep_merge_hashes(config, override).stringify_keys
88
87
  set_timezone(config['timezone']) if config['timezone']
89
88
 
90
89
  config
@@ -102,4 +101,21 @@ module Jekyll
102
101
  def self.logger
103
102
  @logger ||= Stevenson.new
104
103
  end
104
+
105
+ # Public: File system root
106
+ #
107
+ # Returns the root of the filesystem as a Pathname
108
+ def self.fs_root
109
+ @fs_root ||= "/"
110
+ end
111
+
112
+ def self.sanitized_path(base_directory, questionable_path)
113
+ clean_path = File.expand_path(questionable_path, fs_root)
114
+ clean_path.gsub!(/\w\:\//, '/')
115
+ unless clean_path.start_with?(base_directory)
116
+ File.join(base_directory, clean_path)
117
+ else
118
+ clean_path
119
+ end
120
+ end
105
121
  end
@@ -1,27 +1,79 @@
1
1
  module Jekyll
2
2
  class Command
3
- def self.globs(source, destination)
4
- Dir.chdir(source) do
5
- dirs = Dir['*'].select { |x| File.directory?(x) }
6
- dirs -= [destination, File.expand_path(destination), File.basename(destination)]
7
- dirs = dirs.map { |x| "#{x}/**/*" }
8
- dirs += ['*']
3
+
4
+ class << self
5
+
6
+ # A list of subclasses of Jekyll::Command
7
+ def subclasses
8
+ @subclasses ||= []
9
+ end
10
+
11
+ # Keep a list of subclasses of Jekyll::Command every time it's inherited
12
+ # Called automatically.
13
+ #
14
+ # base - the subclass
15
+ #
16
+ # Returns nothing
17
+ def inherited(base)
18
+ subclasses << base
19
+ super(base)
20
+ end
21
+
22
+ # Listing of all directories (globbed to include subfiles and folders)
23
+ #
24
+ # source - the source path
25
+ # destination - the destination path
26
+ #
27
+ # Returns an Array of directory globs in the source, excluding the destination
28
+ def globs(source, destination)
29
+ Dir.chdir(source) do
30
+ dirs = Dir['*'].select { |x| File.directory?(x) }
31
+ dirs -= [destination, File.expand_path(destination), File.basename(destination)]
32
+ dirs = dirs.map { |x| "#{x}/**/*" }
33
+ dirs += ['*']
34
+ end
35
+ end
36
+
37
+ # Run Site#process and catch errors
38
+ #
39
+ # site - the Jekyll::Site object
40
+ #
41
+ # Returns nothing
42
+ def process_site(site)
43
+ site.process
44
+ rescue Jekyll::FatalException => e
45
+ Jekyll.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
46
+ Jekyll.logger.error "", "------------------------------------"
47
+ Jekyll.logger.error "", e.message
48
+ exit(1)
49
+ end
50
+
51
+ # Create a full Jekyll configuration with the options passed in as overrides
52
+ #
53
+ # options - the configuration overrides
54
+ #
55
+ # Returns a full Jekyll configuration
56
+ def configuration_from_options(options)
57
+ Jekyll.configuration(options)
58
+ end
59
+
60
+ # Add common options to a command for building configuration
61
+ #
62
+ # c - the Jekyll::Command to add these options to
63
+ #
64
+ # Returns nothing
65
+ def add_build_options(c)
66
+ c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
67
+ c.option 'future', '--future', 'Publishes posts with a future date'
68
+ c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
69
+ c.option 'watch', '-w', '--watch', 'Watch for changes and rebuild'
70
+ c.option 'lsi', '--lsi', 'Use LSI for improved related posts'
71
+ c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder'
72
+ c.option 'quiet', '-q', '--quiet', 'Silence output.'
73
+ c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
9
74
  end
10
- end
11
75
 
12
- # Static: Run Site#process and catch errors
13
- #
14
- # site - the Jekyll::Site object
15
- #
16
- # Returns nothing
17
- def self.process_site(site)
18
- site.process
19
- rescue Jekyll::FatalException => e
20
- puts
21
- Jekyll.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
22
- Jekyll.logger.error "", "------------------------------------"
23
- Jekyll.logger.error "", e.message
24
- exit(1)
25
76
  end
77
+
26
78
  end
27
79
  end
@@ -1,72 +1,96 @@
1
1
  module Jekyll
2
2
  module Commands
3
3
  class Build < Command
4
- def self.process(options)
5
- site = Jekyll::Site.new(options)
6
-
7
- Jekyll.logger.log_level = Jekyll::Stevenson::ERROR if options['quiet']
8
-
9
- self.build(site, options)
10
- self.watch(site, options) if options['watch']
11
- end
12
-
13
- # Private: Build the site from source into destination.
14
- #
15
- # site - A Jekyll::Site instance
16
- # options - A Hash of options passed to the command
17
- #
18
- # Returns nothing.
19
- def self.build(site, options)
20
- source = options['source']
21
- destination = options['destination']
22
- Jekyll.logger.info "Source:", source
23
- Jekyll.logger.info "Destination:", destination
24
- print Jekyll.logger.formatted_topic "Generating..."
25
- self.process_site(site)
26
- puts "done."
27
- end
28
-
29
- # Private: Watch for file changes and rebuild the site.
30
- #
31
- # site - A Jekyll::Site instance
32
- # options - A Hash of options passed to the command
33
- #
34
- # Returns nothing.
35
- def self.watch(site, options)
36
- require 'listen'
37
-
38
- source = options['source']
39
- destination = options['destination']
40
-
41
- begin
42
- dest = Pathname.new(destination).relative_path_from(Pathname.new(source)).to_s
43
- ignored = Regexp.new(Regexp.escape(dest))
44
- rescue ArgumentError
45
- # Destination is outside the source, no need to ignore it.
46
- ignored = nil
4
+
5
+ class << self
6
+
7
+ # Create the Mercenary command for the Jekyll CLI for this Command
8
+ def init_with_program(prog)
9
+ prog.command(:build) do |c|
10
+ c.syntax 'build [options]'
11
+ c.description 'Build your site'
12
+
13
+ add_build_options(c)
14
+
15
+ c.action do |args, options|
16
+ options["serving"] = false
17
+ Jekyll::Commands::Build.process(options)
18
+ end
19
+ end
47
20
  end
48
21
 
49
- Jekyll.logger.info "Auto-regeneration:", "enabled"
22
+ # Build your jekyll site
23
+ # Continuously watch if `watch` is set to true in the config.
24
+ def process(options)
25
+ options = configuration_from_options(options)
26
+ site = Jekyll::Site.new(options)
50
27
 
51
- listener = Listen::Listener.new(source, :ignore => ignored) do |modified, added, removed|
52
- t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
53
- n = modified.length + added.length + removed.length
54
- print Jekyll.logger.formatted_topic("Regenerating:") + "#{n} files at #{t} "
55
- self.process_site(site)
56
- puts "...done."
28
+ Jekyll.logger.log_level = Jekyll::Stevenson::ERROR if options['quiet']
29
+
30
+ build(site, options)
31
+ watch(site, options) if options['watch']
32
+ end
33
+
34
+ # Build your Jekyll site.
35
+ #
36
+ # site - the Jekyll::Site instance to build
37
+ # options - the
38
+ #
39
+ # Returns nothing.
40
+ def build(site, options)
41
+ source = options['source']
42
+ destination = options['destination']
43
+ Jekyll.logger.info "Source:", source
44
+ Jekyll.logger.info "Destination:", destination
45
+ Jekyll.logger.info "Generating..."
46
+ process_site(site)
47
+ Jekyll.logger.info "", "done."
57
48
  end
58
- listener.start
59
49
 
60
- unless options['serving']
61
- trap("INT") do
62
- listener.stop
63
- puts " Halting auto-regeneration."
64
- exit 0
50
+ # Private: Watch for file changes and rebuild the site.
51
+ #
52
+ # site - A Jekyll::Site instance
53
+ # options - A Hash of options passed to the command
54
+ #
55
+ # Returns nothing.
56
+ def watch(site, options)
57
+ require 'listen'
58
+
59
+ source = options['source']
60
+ destination = options['destination']
61
+
62
+ begin
63
+ dest = Pathname.new(destination).relative_path_from(Pathname.new(source)).to_s
64
+ ignored = Regexp.new(Regexp.escape(dest))
65
+ rescue ArgumentError
66
+ # Destination is outside the source, no need to ignore it.
67
+ ignored = nil
68
+ end
69
+
70
+ Jekyll.logger.info "Auto-regeneration:", "enabled"
71
+
72
+ listener = Listen.to(source, :ignore => ignored) do |modified, added, removed|
73
+ t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
74
+ n = modified.length + added.length + removed.length
75
+ print Jekyll.logger.formatted_topic("Regenerating:") + "#{n} files at #{t} "
76
+ process_site(site)
77
+ puts "...done."
65
78
  end
79
+ listener.start
66
80
 
67
- loop { sleep 1000 }
81
+ unless options['serving']
82
+ trap("INT") do
83
+ listener.stop
84
+ puts " Halting auto-regeneration."
85
+ exit 0
86
+ end
87
+
88
+ loop { sleep 1000 }
89
+ end
68
90
  end
69
- end
91
+
92
+ end # end of class << self
93
+
70
94
  end
71
95
  end
72
96
  end
@@ -0,0 +1,30 @@
1
+ module Jekyll
2
+ module Commands
3
+ class Docs < Command
4
+
5
+ class << self
6
+
7
+ def init_with_program(prog)
8
+ prog.command(:docs) do |c|
9
+ c.syntax 'docs'
10
+ c.description "Launch local server with docs for Jekyll v#{Jekyll::VERSION}"
11
+
12
+ c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
13
+ c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
14
+
15
+ c.action do |args, options|
16
+ options.merge!({
17
+ 'source' => File.expand_path("../../../site", File.dirname(__FILE__)),
18
+ 'destination' => File.expand_path("../../../site/_site", File.dirname(__FILE__))
19
+ })
20
+ Jekyll::Commands::Build.process(options)
21
+ Jekyll::Commands::Serve.process(options)
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -2,8 +2,23 @@ module Jekyll
2
2
  module Commands
3
3
  class Doctor < Command
4
4
  class << self
5
+
6
+ def init_with_program(prog)
7
+ prog.command(:doctor) do |c|
8
+ c.syntax 'doctor'
9
+ c.description 'Search site and print specific deprecation warnings'
10
+ c.alias(:hyde)
11
+
12
+ c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
13
+
14
+ c.action do |args, options|
15
+ Jekyll::Commands::Doctor.process(options)
16
+ end
17
+ end
18
+ end
19
+
5
20
  def process(options)
6
- site = Jekyll::Site.new(options)
21
+ site = Jekyll::Site.new(configuration_from_options(options))
7
22
  site.read
8
23
 
9
24
  if healthy?(site)
@@ -61,7 +76,9 @@ module Jekyll
61
76
  end
62
77
  urls
63
78
  end
79
+
64
80
  end
81
+
65
82
  end
66
83
  end
67
84
  end
@@ -3,23 +3,36 @@ require 'erb'
3
3
  module Jekyll
4
4
  module Commands
5
5
  class New < Command
6
+ def self.init_with_program(prog)
7
+ prog.command(:new) do |c|
8
+ c.syntax 'new PATH'
9
+ c.description 'Creates a new Jekyll site scaffold in PATH'
10
+
11
+ c.option 'force', '--force', 'Force creation even if PATH already exists'
12
+ c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
13
+
14
+ c.action do |args, options|
15
+ Jekyll::Commands::New.process(args, options)
16
+ end
17
+ end
18
+ end
19
+
6
20
  def self.process(args, options = {})
7
21
  raise ArgumentError.new('You must specify a path.') if args.empty?
8
22
 
9
23
  new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
10
24
  FileUtils.mkdir_p new_blog_path
11
25
  if preserve_source_location?(new_blog_path, options)
12
- Jekyll.logger.error "Conflict:", "#{new_blog_path} exists and is not empty."
13
- exit(1)
26
+ Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
14
27
  end
15
28
 
16
- if options[:blank]
29
+ if options["blank"]
17
30
  create_blank_site new_blog_path
18
31
  else
19
32
  create_sample_files new_blog_path
20
33
 
21
- File.open(File.expand_path(self.initialized_post_name, new_blog_path), "w") do |f|
22
- f.write(self.scaffold_post_content)
34
+ File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
35
+ f.write(scaffold_post_content)
23
36
  end
24
37
  end
25
38
 
@@ -47,7 +60,7 @@ module Jekyll
47
60
  private
48
61
 
49
62
  def self.preserve_source_location?(path, options)
50
- !options[:force] && !Dir["#{path}/**/*"].empty?
63
+ !options["force"] && !Dir["#{path}/**/*"].empty?
51
64
  end
52
65
 
53
66
  def self.create_sample_files(path)
@@ -2,74 +2,105 @@
2
2
  module Jekyll
3
3
  module Commands
4
4
  class Serve < Command
5
- def self.process(options)
6
- require 'webrick'
7
- include WEBrick
8
5
 
9
- destination = options['destination']
6
+ class << self
10
7
 
11
- FileUtils.mkdir_p(destination)
8
+ def init_with_program(prog)
9
+ prog.command(:serve) do |c|
10
+ c.syntax 'serve [options]'
11
+ c.description 'Serve your site locally'
12
+ c.alias :server
12
13
 
13
- # monkey patch WEBrick using custom 404 page (/404.html)
14
- if File.exists?(File.join(destination, '404.html'))
15
- WEBrick::HTTPResponse.class_eval do
16
- def create_error_page
17
- @body = IO.read(File.join(@config[:DocumentRoot], '404.html'))
14
+ add_build_options(c)
15
+
16
+ c.option 'detach', '-B', '--detach', 'Run the server in the background (detach)'
17
+ c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
18
+ c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
19
+ c.option 'baseurl', '-b', '--baseurl [URL]', 'Base URL'
20
+
21
+ c.action do |args, options|
22
+ options["serving"] ||= true
23
+ Jekyll::Commands::Build.process(options)
24
+ Jekyll::Commands::Serve.process(options)
18
25
  end
19
26
  end
20
27
  end
21
28
 
22
- # recreate NondisclosureName under utf-8 circumstance
23
- fh_option = WEBrick::Config::FileHandler
24
- fh_option[:NondisclosureName] = ['.ht*','~*']
29
+ # Boot up a WEBrick server which points to the compiled site's root.
30
+ def process(options)
31
+ options = configuration_from_options(options)
32
+
33
+ require 'webrick'
34
+
35
+ destination = options['destination']
36
+
37
+ FileUtils.mkdir_p(destination)
38
+
39
+ # monkey patch WEBrick using custom 404 page (/404.html)
40
+ if File.exists?(File.join(destination, '404.html'))
41
+ WEBrick::HTTPResponse.class_eval do
42
+ def create_error_page
43
+ @body = IO.read(File.join(@config[:DocumentRoot], '404.html'))
44
+ end
45
+ end
46
+ end
47
+
48
+ # recreate NondisclosureName under utf-8 circumstance
49
+ fh_option = WEBrick::Config::FileHandler
50
+ fh_option[:NondisclosureName] = ['.ht*','~*']
51
+
52
+ s = WEBrick::HTTPServer.new(webrick_options(options))
25
53
 
26
- s = HTTPServer.new(webrick_options(options))
54
+ s.config.store(:DirectoryIndex, s.config[:DirectoryIndex] << "index.xml")
27
55
 
28
- s.mount(options['baseurl'], HTTPServlet::FileHandler, destination, fh_option)
56
+ s.mount(options['baseurl'], WEBrick::HTTPServlet::FileHandler, destination, fh_option)
29
57
 
30
- Jekyll.logger.info "Server address:", "http://#{s.config[:BindAddress]}:#{s.config[:Port]}"
58
+ Jekyll.logger.info "Server address:", "http://#{s.config[:BindAddress]}:#{s.config[:Port]}"
31
59
 
32
- if options['detach'] # detach the server
33
- pid = Process.fork { s.start }
34
- Process.detach(pid)
35
- Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
36
- else # create a new server thread, then join it with current terminal
37
- t = Thread.new { s.start }
38
- trap("INT") { s.shutdown }
39
- t.join()
60
+ if options['detach'] # detach the server
61
+ pid = Process.fork { s.start }
62
+ Process.detach(pid)
63
+ Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
64
+ else # create a new server thread, then join it with current terminal
65
+ t = Thread.new { s.start }
66
+ trap("INT") { s.shutdown }
67
+ t.join
68
+ end
40
69
  end
41
- end
42
70
 
43
- def self.webrick_options(config)
44
- opts = {
45
- :DocumentRoot => config['destination'],
46
- :Port => config['port'],
47
- :BindAddress => config['host'],
48
- :MimeTypes => self.mime_types,
49
- :DoNotReverseLookup => true,
50
- :StartCallback => start_callback(config['detach'])
51
- }
52
-
53
- if !config['verbose']
54
- opts.merge!({
55
- :AccessLog => [],
56
- :Logger => Log::new([], Log::WARN)
57
- })
71
+ def webrick_options(config)
72
+ opts = {
73
+ :DocumentRoot => config['destination'],
74
+ :Port => config['port'],
75
+ :BindAddress => config['host'],
76
+ :MimeTypes => mime_types,
77
+ :DoNotReverseLookup => true,
78
+ :StartCallback => start_callback(config['detach'])
79
+ }
80
+
81
+ if !config['verbose']
82
+ opts.merge!({
83
+ :AccessLog => [],
84
+ :Logger => WEBrick::Log.new([], WEBrick::Log::WARN)
85
+ })
86
+ end
87
+
88
+ opts
58
89
  end
59
90
 
60
- opts
61
- end
91
+ def start_callback(detached)
92
+ unless detached
93
+ Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
94
+ end
95
+ end
62
96
 
63
- def self.start_callback(detached)
64
- unless detached
65
- Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
97
+ def mime_types
98
+ mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
99
+ WEBrick::HTTPUtils::load_mime_types(mime_types_file)
66
100
  end
67
- end
68
101
 
69
- def self.mime_types
70
- mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
71
- WEBrick::HTTPUtils::load_mime_types(mime_types_file)
72
102
  end
103
+
73
104
  end
74
105
  end
75
106
  end