bgotink-hyde 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []