bgotink-hyde 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b35e2e38e70e2040272eb73e09c1723addeb037e
4
+ data.tar.gz: 649a9dc6e5865353fd824b0bda1d00c371912e09
5
+ SHA512:
6
+ metadata.gz: ba3173c30ede6cba47322d3758b5972f475ba9222ce37fd0ef032c2f5ce4e8ae0bbaf7d6d07c4d54d152776ff53e22ee31cfd040fc7857257eb254b354110d9e
7
+ data.tar.gz: ae6bcd9e3c0f1ce2b1d7fd0ce49bc25aaa58d0be1f7d3d26618f2c38430f49ca1bdffd33517dd34988fb4e339ca760a1db06566f118f20387cb2fa5feca6660c
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/History.md ADDED
@@ -0,0 +1,12 @@
1
+ ## HEAD
2
+
3
+ ### Major Enhancements
4
+ * copied and modified gemspec, rakefile etc. from [jekyll](//github.com/jekyll/jekyll)
5
+ * wrote `bin/hyde` based on `jekyll` script
6
+ * created build command
7
+ * created serve command
8
+ * use `mtime` to obtain a date to give jekyll
9
+ * allow usage of `hyde_data: `, which takes precedense over `mtime`
10
+
11
+ ## 0.0.0 / 2014-01-07
12
+ * Birthday! (no really, 23rd birthday)
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ TODO: fill in MIT license
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ Hyde is a user-friendly front-end for [Jekyll](//github.com/jekyll/jekyll).
2
+
3
+ ## Features
4
+
5
+ Hyde needs a Jekyll skeleton and will fill it in with posts.
6
+ The post format for Jekyll is `year-mo-da-title.ext`, whereas Hyde
7
+ uses the `mdate` of the file to obtain the date of the post.
data/Rakefile ADDED
@@ -0,0 +1,302 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rdoc'
4
+ require 'date'
5
+ require 'yaml'
6
+
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[lib]))
8
+
9
+ #############################################################################
10
+ #
11
+ # Helper functions
12
+ #
13
+ #############################################################################
14
+
15
+ def name
16
+ rubyforge_project
17
+ end
18
+
19
+ def main_file
20
+ Dir['lib/*.rb'].first
21
+ end
22
+
23
+ def version
24
+ line = File.read(main_file)[/^\s*VERSION\s*=\s*.*/]
25
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
26
+ end
27
+
28
+ def date
29
+ Date.today.to_s
30
+ end
31
+
32
+ def file_date
33
+ Date.today.strftime("%F")
34
+ end
35
+
36
+ def rubyforge_project
37
+ @project ||= gemspec_file.split('.').first
38
+ end
39
+
40
+ def gemspec_file
41
+ Dir['*.gemspec'].first
42
+ end
43
+
44
+ def gem_file
45
+ "#{rubyforge_project}-#{version}.gem"
46
+ end
47
+
48
+ def replace_header(head, header_name)
49
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
50
+ end
51
+
52
+ def normalize_bullets(markdown)
53
+ markdown.gsub(/\s{2}\*{1}/, "-")
54
+ end
55
+
56
+ def linkify_prs(markdown)
57
+ markdown.gsub(/#(\d+)/) do |word|
58
+ "[#{word}]({{ site.repository }}/issues/#{word.delete("#")})"
59
+ end
60
+ end
61
+
62
+ def linkify_users(markdown)
63
+ markdown.gsub(/(@\w+)/) do |username|
64
+ "[#{username}](https://github.com/#{username.delete("@")})"
65
+ end
66
+ end
67
+
68
+ def linkify(markdown)
69
+ linkify_users(linkify_prs(markdown))
70
+ end
71
+
72
+ def liquid_escape(markdown)
73
+ markdown.gsub(/(`{[{%].+[}%]}`)/, "{% raw %}\\1{% endraw %}")
74
+ end
75
+
76
+ def remove_head_from_history(markdown)
77
+ index = markdown =~ /^##\s+\d+\.\d+\.\d+/
78
+ markdown[index..-1]
79
+ end
80
+
81
+ def converted_history(markdown)
82
+ remove_head_from_history(liquid_escape(linkify(normalize_bullets(markdown))))
83
+ end
84
+
85
+ #############################################################################
86
+ #
87
+ # Standard tasks
88
+ #
89
+ #############################################################################
90
+
91
+ if RUBY_VERSION > '1.9' && ENV["TRAVIS"] == "true"
92
+ require 'coveralls/rake/task'
93
+ Coveralls::RakeTask.new
94
+
95
+ task :default => [:test, :features, 'coveralls:push']
96
+ else
97
+ task :default => [:test, :features]
98
+ end
99
+
100
+ require 'rake/testtask'
101
+ Rake::TestTask.new(:test) do |test|
102
+ test.libs << 'lib' << 'test'
103
+ test.pattern = 'test/**/test_*.rb'
104
+ test.verbose = true
105
+ end
106
+
107
+ require 'rdoc/task'
108
+ Rake::RDocTask.new do |rdoc|
109
+ rdoc.rdoc_dir = 'rdoc'
110
+ rdoc.title = "#{name} #{version}"
111
+ rdoc.rdoc_files.include('README*')
112
+ rdoc.rdoc_files.include('lib/**/*.rb')
113
+ end
114
+
115
+ # begin
116
+ # require 'cucumber/rake/task'
117
+ # Cucumber::Rake::Task.new(:features) do |t|
118
+ # t.profile = "travis"
119
+ # end
120
+ # Cucumber::Rake::Task.new(:"features:html", "Run Cucumber features and produce HTML output") do |t|
121
+ # t.profile = "html_report"
122
+ # end
123
+ # rescue LoadError
124
+ # desc 'Cucumber rake task not available'
125
+ # task :features do
126
+ # abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
127
+ # end
128
+ # end
129
+
130
+ desc "Open an irb session preloaded with this library"
131
+ task :console do
132
+ sh "irb -rubygems -r ./#{main_file}"
133
+ end
134
+
135
+ #############################################################################
136
+ #
137
+ # Site tasks - http://jekyllrb.com
138
+ #
139
+ #############################################################################
140
+
141
+ namespace :site do
142
+ desc "Generate and view the site locally"
143
+ task :preview do
144
+ require "launchy"
145
+
146
+ # Yep, it's a hack! Wait a few seconds for the Jekyll site to generate and
147
+ # then open it in a browser. Someday we can do better than this, I hope.
148
+ Thread.new do
149
+ sleep 4
150
+ puts "Opening in browser..."
151
+ Launchy.open("http://localhost:4000")
152
+ end
153
+
154
+ # Generate the site in server mode.
155
+ puts "Running Jekyll..."
156
+ Dir.chdir("site") do
157
+ sh "#{File.expand_path('bin/jekyll', File.dirname(__FILE__))} serve --watch"
158
+ end
159
+ end
160
+
161
+ desc "Update normalize.css library to the latest version and minify"
162
+ task :update_normalize_css do
163
+ Dir.chdir("site/css") do
164
+ sh 'curl "http://necolas.github.io/normalize.css/latest/normalize.css" -o "normalize.scss"'
165
+ sh 'sass "normalize.scss":"normalize.css" --style compressed'
166
+ sh 'rm "normalize.scss"'
167
+ end
168
+ end
169
+
170
+ desc "Commit the local site to the gh-pages branch and publish to GitHub Pages"
171
+ task :publish => [:history] do
172
+ # Ensure the gh-pages dir exists so we can generate into it.
173
+ puts "Checking for gh-pages dir..."
174
+ unless File.exist?("./gh-pages")
175
+ puts "No gh-pages directory found. Run the following commands first:"
176
+ puts " `git clone git@github.com:mojombo/jekyll gh-pages"
177
+ puts " `cd gh-pages"
178
+ puts " `git checkout gh-pages`"
179
+ exit(1)
180
+ end
181
+
182
+ # Ensure gh-pages branch is up to date.
183
+ Dir.chdir('gh-pages') do
184
+ sh "git pull origin gh-pages"
185
+ end
186
+
187
+ # Copy to gh-pages dir.
188
+ puts "Copying site to gh-pages branch..."
189
+ Dir.glob("site/*") do |path|
190
+ next if path.include? "_site"
191
+ sh "cp -R #{path} gh-pages/"
192
+ end
193
+
194
+ # Commit and push.
195
+ puts "Committing and pushing to GitHub Pages..."
196
+ sha = `git log`.match(/[a-z0-9]{40}/)[0]
197
+ Dir.chdir('gh-pages') do
198
+ sh "git add ."
199
+ sh "git commit -m 'Updating to #{sha}.'"
200
+ sh "git push origin gh-pages"
201
+ end
202
+ puts 'Done.'
203
+ end
204
+
205
+ desc "Create a nicely formatted history page for the jekyll site based on the repo history."
206
+ task :history do
207
+ if File.exist?("History.md")
208
+ history_file = File.read("History.md")
209
+ front_matter = {
210
+ "layout" => "docs",
211
+ "title" => "History",
212
+ "permalink" => "/docs/history/",
213
+ "prev_section" => "contributing"
214
+ }
215
+ Dir.chdir('site/docs/') do
216
+ File.open("history.md", "w") do |file|
217
+ file.write("#{front_matter.to_yaml}---\n\n")
218
+ file.write(converted_history(history_file))
219
+ end
220
+ end
221
+ else
222
+ abort "You seem to have misplaced your History.markdown file. I can haz?"
223
+ end
224
+ end
225
+
226
+ namespace :releases do
227
+ desc "Create new release post"
228
+ task :new, :version do |t, args|
229
+ raise "Specify a version: rake site:releases:new['1.2.3']" unless args.version
230
+ today = Time.new.strftime('%Y-%m-%d')
231
+ release = args.version.to_s
232
+ filename = "site/_posts/#{today}-jekyll-#{release.split('.').join('-')}-released.markdown"
233
+
234
+ File.open(filename, "wb") do |post|
235
+ post.puts("---")
236
+ post.puts("layout: news_item")
237
+ post.puts("title: 'Jekyll #{release} Released'")
238
+ post.puts("date: #{Time.new.strftime('%Y-%m-%d %H:%M:%S %z')}")
239
+ post.puts("author: ")
240
+ post.puts("version: #{release}")
241
+ post.puts("categories: [release]")
242
+ post.puts("---")
243
+ post.puts
244
+ post.puts
245
+ end
246
+
247
+ puts "Created #{filename}"
248
+ end
249
+ end
250
+ end
251
+
252
+ #############################################################################
253
+ #
254
+ # Packaging tasks
255
+ #
256
+ #############################################################################
257
+
258
+ task :release => :build do
259
+ unless `git branch` =~ /^(\* master|\* v1-stable)$/
260
+ puts "You must be on the master branch or the v1-stable branch to release!"
261
+ exit!
262
+ end
263
+ sh "git commit --allow-empty -m 'Release #{version}'"
264
+ sh "git tag v#{version}"
265
+ sh "git push origin master"
266
+ sh "git push origin v#{version}"
267
+ sh "gem push pkg/#{name}-#{version}.gem"
268
+ end
269
+
270
+ task :build => :gemspec do
271
+ sh "mkdir -p pkg"
272
+ sh "gem build #{gemspec_file}"
273
+ sh "mv #{gem_file} pkg"
274
+ end
275
+
276
+ task :gemspec do
277
+ # read spec file and split out manifest section
278
+ spec = File.read(gemspec_file)
279
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
280
+
281
+ # replace name version and date
282
+ replace_header(head, :name)
283
+ replace_header(head, :version)
284
+ replace_header(head, :date)
285
+ #comment this out if your rubyforge_project has a different name
286
+ replace_header(head, :rubyforge_project)
287
+
288
+ # determine file list from git ls-files
289
+ files = `git ls-files`.
290
+ split("\n").
291
+ sort.
292
+ reject { |file| file =~ /^\./ }.
293
+ reject { |file| file =~ /^(rdoc|pkg|coverage)/ }.
294
+ map { |file| " #{file}" }.
295
+ join("\n")
296
+
297
+ # piece file back together and write
298
+ manifest = " s.files = %w[\n#{files}\n ]\n"
299
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
300
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
301
+ puts "Updated #{gemspec_file}"
302
+ end
@@ -0,0 +1,69 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+ s.rubygems_version = '1.3.5'
5
+
6
+ s.name = 'bgotink-hyde'
7
+ s.version = '0.1.0'
8
+ s.license = 'MIT'
9
+ s.date = '2014-01-08'
10
+ s.rubyforge_project = 'bgotink-hyde'
11
+
12
+ s.summary = "A user-friendly front-end for Jekyll"
13
+ s.description = "Hyde is a simple front-end for Jekyll, the simple, blog-aware static site generator."
14
+
15
+ s.authors = ["Bram Gotink"]
16
+ s.email = 'bram@gotink.me'
17
+ s.homepage = 'http://github.com/bgotink/hyde'
18
+
19
+ s.require_paths = %w[lib]
20
+
21
+ s.executables = ["hyde"]
22
+
23
+ s.rdoc_options = ["--charset=UTF-8"]
24
+ s.extra_rdoc_files = %w[README.md LICENSE]
25
+
26
+ s.add_runtime_dependency('jekyll', "~> 1.4.2")
27
+ s.add_runtime_dependency('listen', "~> 1.3")
28
+ s.add_runtime_dependency('commander', "~> 4.1.3")
29
+ s.add_runtime_dependency('safe_yaml', "~> 0.9.7")
30
+
31
+ s.add_development_dependency('rake', "~> 10.1")
32
+ # s.add_development_dependency('rdoc', "~> 3.11")
33
+ # s.add_development_dependency('redgreen', "~> 1.2")
34
+ # s.add_development_dependency('shoulda', "~> 3.3.2")
35
+ # s.add_development_dependency('rr', "~> 1.1")
36
+ # s.add_development_dependency('cucumber', "~> 1.3")
37
+ # s.add_development_dependency('RedCloth', "~> 4.2")
38
+ # s.add_development_dependency('kramdown', "~> 1.2")
39
+ # s.add_development_dependency('rdiscount', "~> 1.6")
40
+ # s.add_development_dependency('launchy', "~> 2.3")
41
+ # s.add_development_dependency('simplecov', "~> 0.7")
42
+ # s.add_development_dependency('simplecov-gem-adapter', "~> 1.0.1")
43
+ # s.add_development_dependency('coveralls', "~> 0.7.0")
44
+ # s.add_development_dependency('mime-types', "~> 1.5")
45
+ # s.add_development_dependency('activesupport', '~> 3.2.13')
46
+ # s.add_development_dependency('jekyll_test_plugin')
47
+
48
+ # = MANIFEST =
49
+ s.files = %w[
50
+ Gemfile
51
+ History.md
52
+ LICENSE
53
+ README.md
54
+ Rakefile
55
+ bgotink-hyde.gemspec
56
+ bin/hyde
57
+ lib/hyde.rb
58
+ lib/hyde/command.rb
59
+ lib/hyde/commands/build.rb
60
+ lib/hyde/commands/serve.rb
61
+ lib/hyde/configuration.rb
62
+ lib/hyde/jekyllfile.rb
63
+ lib/hyde/site.rb
64
+ lib/hyde/stevenson.rb
65
+ ]
66
+ # = MANIFEST =
67
+
68
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
69
+ end
data/bin/hyde ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ STDOUT.sync = true
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
5
+
6
+ require 'commander/import'
7
+ require 'hyde'
8
+
9
+ program :name, 'Hyde'
10
+ program :version, Hyde::VERSION
11
+ program :description, 'A user-friendly front-end for Jekyll'
12
+
13
+ default_command :default
14
+
15
+ global_option '-s', '--source [DIR]', 'Source directory (defaults to ./_source)'
16
+ global_option '-j', '--jekyll [DIR]', 'Jekyll input directory (defaults to ./_jekyll)'
17
+ global_option '-k', '--jekyll-out [DIR]', 'Jekyll intermediate directory (defaults to ./_jekyll-out)'
18
+ global_option '-d', '--destination [DIR]', 'Output directory (defaults to ./_site)'
19
+
20
+ def add_build_options(c)
21
+ c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
22
+ c.option '--keep', 'Keep intermediate jekyll files'
23
+ c.option '-w', '--watch', 'Watch for changes and rebuild'
24
+ c.option '-V', '--verbose', 'Print verbose output.'
25
+ end
26
+
27
+ command :default do |c|
28
+ c.action do |args, options|
29
+ if args.empty?
30
+ command(:help).run
31
+ else
32
+ Hyde.logger.abort_with "Invalid command. Use --help for more information"
33
+ end
34
+ end
35
+ end
36
+
37
+ command :build do |c|
38
+ c.syntax = 'hyde build [options]'
39
+ c.description = 'build your site'
40
+
41
+ add_build_options(c)
42
+
43
+ c.action do |args, options|
44
+ options = Hyde.configuration(options.__hash__)
45
+ Hyde::Commands::Build.process(options)
46
+ end
47
+ end
48
+
49
+ command :serve do |c|
50
+ c.syntax = 'hyde serve [options]'
51
+ c.description = 'Serve your site locally'
52
+
53
+ add_build_options(c)
54
+
55
+ c.option '-B', '--detach', 'Run the server in the background (detach)'
56
+ c.option '-P', '--port [PORT]', 'Port to listen on'
57
+ c.option '-H', '--host [HOST]', 'Host to bind to'
58
+ c.option '-b', '--baseurl [URL]', 'Base URL'
59
+
60
+ c.action do |args, options|
61
+ options.default :serving => true
62
+
63
+ options = Hyde.configuration(options.__hash__)
64
+ Hyde::Commands::Build.process(options)
65
+ Hyde::Commands::Serve.process(options)
66
+ end
67
+ end
68
+ alias_command :server, :serve
@@ -0,0 +1,7 @@
1
+ module Hyde
2
+
3
+ class Command
4
+
5
+ end
6
+
7
+ end
@@ -0,0 +1,87 @@
1
+ module Hyde
2
+ module Commands
3
+ class Build < Command
4
+
5
+ def self.process(options)
6
+ site = Hyde::Site.new(options)
7
+
8
+ options['watching'] = true if options['watch']
9
+
10
+ self.build(site, options)
11
+ self.watch(site, options) if options['watch']
12
+ end
13
+
14
+ def self.build(site, options)
15
+ source = options['source']
16
+ jekyll = options['jekyll']
17
+ jekyll_out = options['jekyll-out']
18
+ destination = options['destination']
19
+
20
+ Hyde.logger.info "Source:", source
21
+ Hyde.logger.info "Jekyll input:", jekyll
22
+ Hyde.logger.info "Jekyll output:", jekyll_out
23
+ Hyde.logger.info "Destination:", destination
24
+
25
+ Hyde.logger.info "Running Jekyll...", ""
26
+
27
+ site.process
28
+
29
+ Hyde.logger.info "", "done."
30
+ end
31
+
32
+ def self.watch(site, options)
33
+ require 'listen'
34
+
35
+ # TODO check whether dest is in source?
36
+
37
+ source = options['source']
38
+ intermediary = options['jekyll-out']
39
+ destination = options['destination']
40
+
41
+ ignored = Array.new
42
+ %w[jekyll-out destination].each do |o|
43
+ begin
44
+ d = Pathname.new(options[o]).relative_path_from(Pathname.new(source)).to_s
45
+ ignored << Regexp.escape(d)
46
+ rescue ArgumentError
47
+ # nop
48
+ end
49
+ end
50
+
51
+ if ignored.empty?
52
+ ignored = nil
53
+ else
54
+ ignored = Regexp.new(ignored.join('|'))
55
+ end
56
+
57
+ Hyde.logger.info 'Auto-regeneration:', 'enabled'
58
+
59
+ listener = Listen::Listener.new(source, :ignore => ignored) do |modified, added, removed|
60
+ t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
61
+ n = modified.length + added.length + removed.length
62
+ Hyde.logger.info "Regenerating:", "#{n} files at #{t} "
63
+
64
+ site.process
65
+
66
+ Hyde.logger.info "", "done."
67
+ end
68
+ listener.start
69
+
70
+ unless options['serving']
71
+ trap("INT") do
72
+ options['watching'] = false
73
+
74
+ listener.stop
75
+ site.cleanup
76
+
77
+ puts " Halting auto-regeneration."
78
+ exit 0
79
+ end
80
+
81
+ loop { sleep 1000 }
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,9 @@
1
+ module Hyde
2
+ module Commands
3
+ class Serve < Hyde::Command
4
+ def self.process(options)
5
+ Jekyll::Commands::Serve.process(Hyde::jekyll_configuration(options))
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,116 @@
1
+ module Hyde
2
+ class Configuration < Hash
3
+
4
+ DEFAULTS = {
5
+ 'source' => Dir.pwd,
6
+ 'jekyll' => File.join(Dir.pwd, '_jekyll'),
7
+ 'jekyll-out' => File.join(Dir.pwd, '_jekyll-out'),
8
+ 'destination' => File.join(Dir.pwd, '_site'),
9
+
10
+ 'keep' => false,
11
+
12
+ 'encoding' => nil,
13
+
14
+ 'safe' => false,
15
+ 'detach' => false,
16
+
17
+ 'port' => Jekyll::Configuration::DEFAULTS['port'],
18
+ 'host' => Jekyll::Configuration::DEFAULTS['host']
19
+ }
20
+
21
+ # Public: Turn all keys into string
22
+ #
23
+ # Return a copy of the hash where all its keys are strings
24
+ def stringify_keys
25
+ reduce({}) { |hsh,(k,v)| hsh.merge(k.to_s => v) }
26
+ end
27
+
28
+ # Public: Directory of the Jekyll source folder
29
+ #
30
+ # override - the command-line options hash
31
+ #
32
+ # Returns the path to the Jekyll source directory
33
+ def source(override)
34
+ override['source'] || self['source'] || DEFAULTS['source']
35
+ end
36
+
37
+ def safe_load_file(filename)
38
+ case File.extname(filename)
39
+ when '.toml'
40
+ TOML.load_file(filename)
41
+ when /\.y(a)?ml/
42
+ YAML.safe_load_file(filename)
43
+ else
44
+ raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
45
+ end
46
+ end
47
+
48
+ # Public: Generate list of configuration files from the override
49
+ #
50
+ # override - the command-line options hash
51
+ #
52
+ # Returns an Array of config files
53
+ def config_files(override)
54
+ # Get configuration from <source>/_config.yml or <source>/<config_file>
55
+ config_files = override.delete('config')
56
+ if config_files.to_s.empty?
57
+ config_files = File.join(source(override), "_config.yml")
58
+ @default_config_file = true
59
+ end
60
+ config_files = [config_files] unless config_files.is_a? Array
61
+ config_files
62
+ end
63
+
64
+ # Public: Read configuration and return merged Hash
65
+ #
66
+ # file - the path to the YAML file to be read in
67
+ #
68
+ # Returns this configuration, overridden by the values in the file
69
+ def read_config_file(file)
70
+ next_config = safe_load_file(file)
71
+ raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow) unless next_config.is_a?(Hash)
72
+ Hyde.logger.info "Configuration file:", file
73
+ next_config
74
+ rescue SystemCallError
75
+ if @default_config_file
76
+ Hyde.logger.warn "Configuration file:", "none"
77
+ {}
78
+ else
79
+ Hyde.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
80
+ raise LoadError, "The Configuration file '#{file}' could not be found."
81
+ end
82
+ end
83
+
84
+ # Public: Read in a list of configuration files and merge with this hash
85
+ #
86
+ # files - the list of configuration file paths
87
+ #
88
+ # Returns the full configuration, with the defaults overridden by the values in the
89
+ # configuration files
90
+ def read_config_files(files)
91
+ configuration = clone
92
+
93
+ begin
94
+ files.each do |config_file|
95
+ new_config = read_config_file(config_file)
96
+ configuration = configuration.deep_merge(new_config)
97
+ end
98
+ rescue ArgumentError => err
99
+ Hyde.logger.warn "WARNING:", "Error reading configuration. " +
100
+ "Using defaults (and options)."
101
+ $stderr.puts "#{err}"
102
+ end
103
+
104
+ configuration.fix_common_issues.backwards_compatibilize
105
+ end
106
+
107
+ def fix_common_issues
108
+ clone
109
+ end
110
+
111
+ def backwards_compatibilize
112
+ clone
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,52 @@
1
+ module Hyde
2
+
3
+ class JekyllFile
4
+ attr_accessor :original, :destination
5
+
6
+ def initialize(location, destination)
7
+ self.original = File.absolute_path(location)
8
+ data = read_yaml(self.original)
9
+
10
+ name = File.basename(location)
11
+ time = if data['hyde_date']
12
+ Time.parse(data['hyde_date'])
13
+ else
14
+ File.mtime(location)
15
+ end
16
+
17
+ dest_file_name = "#{time.strftime('%Y-%m-%d')}-#{name}"
18
+
19
+ self.destination = File.join(destination, dest_file_name)
20
+ end
21
+
22
+ def write
23
+ File.symlink(self.original, self.destination)
24
+ end
25
+
26
+ private
27
+
28
+ # Read the YAML frontmatter.
29
+ #
30
+ # base - The String path to the dir containing the file.
31
+ # name - The String filename of the file.
32
+ # opts - optional parameter to File.read, default at site configs
33
+ #
34
+ # Returns nothing.
35
+ def read_yaml(file)
36
+ data = nil
37
+
38
+ begin
39
+ content = File.read_with_options(file, {})
40
+ if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
41
+ data = YAML.safe_load($1)
42
+ end
43
+ rescue SyntaxError => e
44
+ puts "YAML Exception reading #{File.join(base, name)}: #{e.message}"
45
+ rescue Exception => e
46
+ puts "Error reading file #{File.join(base, name)}: #{e.message}"
47
+ end
48
+
49
+ data ||= {}
50
+ end
51
+ end
52
+ end
data/lib/hyde/site.rb ADDED
@@ -0,0 +1,134 @@
1
+ module Hyde
2
+
3
+ class Site
4
+ attr_accessor :config, :map, :source, :jekyll_source, :dest, :time, :files
5
+
6
+ def initialize(config)
7
+ self.config = config
8
+
9
+ self.map = config['map'] || {}
10
+ self.source = File.expand_path(config['source'])
11
+ self.jekyll_source = File.expand_path(config['jekyll'])
12
+ self.dest = File.expand_path(config['jekyll-out'])
13
+
14
+ self.reset
15
+ self.setup
16
+ end
17
+
18
+ def process
19
+ self.reset
20
+ self.directories
21
+ self.read
22
+ self.write
23
+ self.build
24
+ self.cleanup
25
+ end
26
+
27
+ # reset the time
28
+ def reset
29
+ self.time = if self.config['time']
30
+ Time.parse(self.config['time'].to_s)
31
+ else
32
+ Time.now
33
+ end
34
+ end
35
+
36
+ # copy Jekyll source files
37
+ def setup
38
+ FileUtils.rm_rf(self.dest)
39
+ FileUtils.cp_r(self.jekyll_source, self.dest, :preserve => true)
40
+ end
41
+
42
+ # create the Hyde-to-Jekyll output directories
43
+ def directories
44
+ self.map.each do |source_d, dest_d|
45
+ source = File.join(self.source, source_d)
46
+ if File.exists?(source)
47
+ dest = File.join(self.dest, dest_d)
48
+ if File.exists?(dest)
49
+ Hyde.logger.abort_with 'Illegal file:' "Expected destination file #{dest_d}/_posts to be a directory but found a file" unless File.directory?(dest)
50
+ Hyde.logger.warn 'Destination exists:', "Destination directory #{dest_d} exists, deleting content" unless self.config['watching']
51
+
52
+ Dir[File.join(dest, '*')].each do |f|
53
+ FileUtils.rm_rf(f)
54
+ end
55
+ else
56
+ FileUtils.mkdir_p(dest)
57
+ end
58
+ else
59
+ Hyde.logger.warn 'File not found:', "Directory #{source_d} does not exist, skipping directory"
60
+ end
61
+ end
62
+ end
63
+
64
+ # read files
65
+ def read
66
+ self.files ||= Hash.new
67
+ self.map.each do |source_d, dest_d|
68
+ files = Hash.new
69
+ Hyde.logger.error 'Duplicate source:', "directory \"#{source_d}\"" if self.files[source_d]
70
+ self.files[source_d] = files
71
+
72
+ read_directory(source_d, files, File.join(self.dest, dest_d))
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def read_directory(directory, data, destination)
79
+ Dir[File.join(directory, '*')].sort.each do |file|
80
+ if File.directory?(file)
81
+ fdata = Hash.new
82
+ read_directory(file, fdata, destination)
83
+ data[File.basename(file)] = fdata
84
+ else
85
+ data[File.basename(file)] = JekyllFile.new(file, destination)
86
+ end
87
+ end
88
+ end
89
+
90
+ public
91
+
92
+ # write jekyll files
93
+ def write
94
+ self.files.each do |name, files|
95
+ write_recursive(files, File.join(self.dest, self.map[name]))
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def write_recursive(files, directory)
102
+ files.each do |name, file|
103
+ if file.is_a?(JekyllFile)
104
+ file.write
105
+ else
106
+ write_recursive(file, directory)
107
+ end
108
+ end
109
+ end
110
+
111
+ public
112
+
113
+ # cleanup
114
+ def cleanup
115
+ self.files = Hash.new
116
+ FileUtils.rm_rf(self.dest) unless self.config['keep'] or self.config['watching']
117
+ end
118
+
119
+ # runs Jekyll
120
+ def build
121
+ jekyll_options = Hash.new
122
+
123
+ %w[safe destination verbose].each do |c|
124
+ jekyll_options[c] = self.config[c] if self.config[c]
125
+ end
126
+
127
+ jekyll_options['source'] = self.dest
128
+
129
+ jekyll_options = Jekyll::configuration(jekyll_options)
130
+ Jekyll::Commands::Build.process(jekyll_options)
131
+ end
132
+ end
133
+
134
+ end
@@ -0,0 +1,18 @@
1
+ module Jekyll
2
+
3
+ class Stevenson
4
+ def formatted_topic(topic)
5
+ "J " + "#{topic} ".rjust(22)
6
+ end
7
+ end
8
+
9
+ end
10
+
11
+ module Hyde
12
+
13
+ class Stevenson < Jekyll::Stevenson
14
+ def formatted_topic(topic)
15
+ "H " + "#{topic} ".rjust(22)
16
+ end
17
+ end
18
+ end
data/lib/hyde.rb ADDED
@@ -0,0 +1,57 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ require 'jekyll'
4
+
5
+ def require_all(directory)
6
+ glob = File.join(File.dirname(__FILE__), directory, '*.rb')
7
+ Dir[glob].each do |f|
8
+ require f
9
+ end
10
+ end
11
+
12
+ require 'hyde/configuration'
13
+ require 'hyde/jekyllfile'
14
+ require 'hyde/site'
15
+ require 'hyde/command'
16
+ require 'hyde/stevenson'
17
+
18
+ require_all 'hyde/commands'
19
+
20
+ module Hyde
21
+ VERSION = '0.1.0'
22
+
23
+ # Public: Generate a Hyde configuration Hash by merging the default
24
+ # options with anything in _config.yml, and adding the given options on top.
25
+ #
26
+ # override - A Hash of config directives that override any options in both
27
+ # the defaults and the config file. See Hyde::Configuration::DEFAULTS for a
28
+ # list of option names and their defaults.
29
+ #
30
+ # Returns the final configuration Hash.
31
+ def self.configuration(override)
32
+ config = Configuration[Configuration::DEFAULTS]
33
+ override = Configuration[override].stringify_keys
34
+ config = config.read_config_files(config.config_files(override))
35
+
36
+ # Merge DEFAULTS < _config.yml < override
37
+ config = config.deep_merge(override).stringify_keys
38
+ set_timezone(config['timezone']) if config['timezone']
39
+
40
+ config
41
+ end
42
+
43
+ def self.jekyll_configuration(configuration)
44
+ config = Jekyll::Configuration[Jekyll::Configuration::DEFAULTS]
45
+ override = Jekyll::Configuration[{
46
+ 'source' => configuration['jekyll-out'],
47
+ 'destination' => configuration['destination']
48
+ }].stringify_keys
49
+ config = config.read_config_files(config.config_files(override))
50
+
51
+ config.stringify_keys
52
+ end
53
+
54
+ def self.logger
55
+ @logger ||= Stevenson.new
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bgotink-hyde
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Bram Gotink
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: listen
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: commander
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 4.1.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 4.1.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: safe_yaml
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.7
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.7
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '10.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '10.1'
83
+ description: Hyde is a simple front-end for Jekyll, the simple, blog-aware static
84
+ site generator.
85
+ email: bram@gotink.me
86
+ executables:
87
+ - hyde
88
+ extensions: []
89
+ extra_rdoc_files:
90
+ - README.md
91
+ - LICENSE
92
+ files:
93
+ - Gemfile
94
+ - History.md
95
+ - LICENSE
96
+ - README.md
97
+ - Rakefile
98
+ - bgotink-hyde.gemspec
99
+ - bin/hyde
100
+ - lib/hyde.rb
101
+ - lib/hyde/command.rb
102
+ - lib/hyde/commands/build.rb
103
+ - lib/hyde/commands/serve.rb
104
+ - lib/hyde/configuration.rb
105
+ - lib/hyde/jekyllfile.rb
106
+ - lib/hyde/site.rb
107
+ - lib/hyde/stevenson.rb
108
+ homepage: http://github.com/bgotink/hyde
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options:
114
+ - --charset=UTF-8
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project: bgotink-hyde
129
+ rubygems_version: 2.2.1
130
+ signing_key:
131
+ specification_version: 2
132
+ summary: A user-friendly front-end for Jekyll
133
+ test_files: []