usmu 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2ce1d8bd5d6466dc1d6a3fd7bee6e296e53dc14
4
- data.tar.gz: 9bc408aade4f29424ab873ec38ba4efef844b9ec
3
+ metadata.gz: 9261434f327d1a56ce03785b20dd2ade1078901a
4
+ data.tar.gz: 3ad74fdce1d7f26fbe3dc3aebcffd95e4dbe78f0
5
5
  SHA512:
6
- metadata.gz: adfea26ea6f7bc59ae8e95f7eaf9a3e795b40744933e6321fe2dacc2be4fa23f1dc38273edba618e6a80901c75ccc880ee3cda095f0667f1e96a48a7016c68b0
7
- data.tar.gz: 9189d6c6248807abc95bd2c02b02f324b56eb89d99740565aac15b5339f6b2fc7e4586dd21c12cc9045321fdb18d456f285fd26fcd3d54c6b80a6976fcee48d2
6
+ metadata.gz: 48ef1c5da18dbe2406f196f03154e846c7f85c552b39cb3190abd69fd5fcc5d83ca7d74ff0e7bdcef351135b6da097ca09729840250ec702c88c20bef3a3b923
7
+ data.tar.gz: 7ad1d0fe258d9d137b0a671b9f55580696d9dc75919f709f2b1ca551c19ad3f9f0293f65d2ae27abf02183f310742f1a8dcdad6f355aed6e394005f6ff762b80
data/.gitignore CHANGED
@@ -2,7 +2,7 @@
2
2
  /.yardoc
3
3
  /Gemfile*.lock
4
4
  /_yardoc/
5
- /coverage/
5
+ /test/coverage/
6
6
  /doc/
7
7
  /pkg/
8
8
  /spec/reports/
data/.rspec CHANGED
@@ -1,5 +1,6 @@
1
1
  --color
2
2
  -I test/spec
3
+ -r turnip/rspec
3
4
  --require spec_helper
4
5
  --format documentation
5
6
  --no-profile
data/.simplecov ADDED
@@ -0,0 +1,4 @@
1
+ SimpleCov.start do
2
+ coverage_dir 'test/coverage'
3
+ add_filter 'test/'
4
+ end
data/.travis.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  language: ruby
2
2
  script: rake ci
3
3
  rvm:
4
+ - 1.9.3
4
5
  - 2.0
5
6
  - 2.1
6
7
  - ruby-head
@@ -13,6 +14,8 @@ gemfile:
13
14
  - Gemfile-jruby
14
15
  matrix:
15
16
  exclude:
17
+ - rvm: 1.9.3
18
+ gemfile: Gemfile-jruby
16
19
  - rvm: 2.0
17
20
  gemfile: Gemfile-jruby
18
21
  - rvm: 2.1
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,16 @@
1
+ ## Bug reports
2
+
3
+ If you have a bug report, please include as much information as possible to help us diagnose the issue:
4
+
5
+ * A log of the console output if available
6
+ * A backtrace or log file (--trace and --log)
7
+ * If possible, a link to the source code for the website that is causing issues or a small example site that shows the
8
+ same issues.
9
+
10
+ ## Contributing code to usmu
11
+
12
+ 1. Fork it
13
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
14
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
15
+ 4. Push to the branch (`git push origin my-new-feature`)
16
+ 5. Create a new Pull Request
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cmd: 'rspec', spec_paths: ['test/spec'] do
5
+ watch(%r{^test/spec/.+_spec\.rb$})
6
+ watch(%r{^lib/usmu/(.+)\.rb$}) { |m| "test/spec/#{m[1]}_spec.rb" }
7
+ watch(%r{^test/spec/support}) { 'test/spec' }
8
+ watch('test/spec/spec_helper.rb') { 'test/spec' }
9
+
10
+ # Turnip features and steps
11
+ #watch(%r{^spec/acceptance/(.+)\.feature$})
12
+ #watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
13
+ end
data/README.md CHANGED
@@ -35,16 +35,17 @@ slim:
35
35
  :pretty: true
36
36
  ```
37
37
 
38
- ## Contributing
38
+ ### Ruby Compatibility
39
39
 
40
- 1. Fork it
41
- 2. Create your feature branch (`git checkout -b my-new-feature`)
42
- 3. Commit your changes (`git commit -am 'Add some feature'`)
43
- 4. Push to the branch (`git push origin my-new-feature`)
44
- 5. Create a new Pull Request
40
+ Officially, we support MRI 1.9.3 and onwards, however we recommend the latest versions. [1.9.3 is no longer maintained][ruby-maint]
41
+ and is only supported here to help out the Rubinius and JRuby folks.
42
+
43
+ We only officially support MRI, however Travis does run against both Rubinius and JRuby to track compatibility and
44
+ there's a reasonable track record so far. Compatibility patches are very welcome.
45
45
 
46
46
  [gh-contrib]: https://github.com/usmu/usmu/graphs/contributors
47
47
  [gh-issues]: https://github.com/usmu/usmu/issues
48
48
  [license]: https://github.com/usmu/usmu/blob/master/LICENSE.md
49
49
  [tilt-support]: https://github.com/rtomayko/tilt/blob/master/README.md
50
50
  [template-options]: https://github.com/rtomayko/tilt/blob/master/docs/TEMPLATES.md
51
+ [ruby-maint]: https://bugs.ruby-lang.org/projects/ruby/wiki/ReleaseEngineering
data/Rakefile CHANGED
@@ -2,8 +2,6 @@ lib = File.expand_path('../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  require 'rspec/core/rake_task'
5
- require 'cucumber'
6
- require 'cucumber/rake/task'
7
5
  require 'usmu/version'
8
6
 
9
7
  def current_gems
@@ -11,23 +9,24 @@ def current_gems
11
9
  end
12
10
 
13
11
  RSpec::Core::RakeTask.new(:spec) do |t|
14
- t.pattern = 'test/spec/**/*_spec.rb'
15
- end
16
-
17
- Cucumber::Rake::Task.new(:features) do |t|
18
- t.cucumber_opts = 'test/features'
12
+ t.pattern = 'test/spec'
19
13
  end
20
14
 
21
15
  desc 'Run all test scripts'
22
- task :test => [:clean, :spec, :features]
16
+ task :test => [:clean, :spec]
23
17
 
24
18
  desc 'Run CI test suite'
25
19
  task :ci => [:test]
26
20
 
27
21
  desc 'Clean up after tests'
28
22
  task :clean do
29
- rm_r 'test/site/site' if File.exist? 'test/site/site'
30
- current_gems.each {|f| rm f }
23
+ [
24
+ 'test/coverage',
25
+ 'test/site/site',
26
+ current_gems,
27
+ ].flatten.each do |f|
28
+ rm_r f if File.exist? f
29
+ end
31
30
  end
32
31
 
33
32
  namespace :gem do
data/bin/usmu CHANGED
@@ -7,4 +7,8 @@ rescue LoadError
7
7
  require 'usmu/ui/console'
8
8
  end
9
9
 
10
- Usmu::Ui::Console.new(ARGV).execute
10
+ begin
11
+ Usmu::Ui::Console.new(ARGV).execute
12
+ rescue StandardError
13
+ exit 1
14
+ end
data/lib/usmu.rb CHANGED
@@ -1,3 +1,74 @@
1
+ require 'logging'
2
+ require 'rubygems'
3
+
4
+ Logging.init :debug, :info, :success, :warn, :error, :fatal
5
+ Logging.color_scheme(
6
+ 'console',
7
+ :lines => {
8
+ :success => :green,
9
+ :warn => :yellow,
10
+ :error => :red,
11
+ :fatal => :red,
12
+ },
13
+ )
14
+
15
+ # This module contains all the code for the Usmu site generator
16
+ module Usmu
17
+ @log = Logging.logger['Usmu']
18
+ @log.level = :all
19
+ @log.additive = false
20
+ @log.appenders = Logging.appenders.stdout(
21
+ 'usmu-stdout',
22
+ :level => :info,
23
+ :layout => Logging.layouts.pattern(
24
+ :pattern => '%m\n',
25
+ :color_scheme => 'console',
26
+ ),
27
+ )
28
+
29
+ # Enable logging of all events to the console
30
+ #
31
+ # @return [void]
32
+ def self.verbose_logging
33
+ Logging.appenders['usmu-stdout'].level = :all
34
+ nil
35
+ end
36
+
37
+ # Disable all log messages other than errors. Warnings will be suppressed.
38
+ #
39
+ # @return [void]
40
+ def self.quiet_logging
41
+ Logging.appenders['usmu-stdout'].level = :error
42
+ nil
43
+ end
44
+
45
+ # Adds a file-based logger
46
+ #
47
+ # @param [String] filename Filename of the file to log to.
48
+ # @return [void]
49
+ def self.add_file_logger(filename)
50
+ @log.add_appenders(Logging.appenders.file(filename, :filename => filename, :level => :all))
51
+ nil
52
+ end
53
+
54
+ # :nocov:
55
+ # This is primarily a testing helper
56
+
57
+ # Disables stdout logging across the application. This is used to hide stack traces but still log them to the file
58
+ # log if it is in use.
59
+ #
60
+ # @return [void]
61
+ def self.disable_stdout_logging
62
+ @log.remove_appenders('usmu-stdout')
63
+ nil
64
+ end
65
+ # :nocov:
66
+
67
+ def self.plugins
68
+ @plugins ||= Usmu::Plugin.new
69
+ end
70
+ end
71
+
1
72
  %W{
2
73
  usmu/version
3
74
  usmu/configuration
@@ -5,8 +76,6 @@
5
76
  usmu/layout
6
77
  usmu/page
7
78
  usmu/site_generator
79
+ usmu/plugin
80
+ usmu/plugin/core
8
81
  }.each { |f| require f }
9
-
10
- # This module contains all the code for the Usmu site generator
11
- module Usmu
12
- end
@@ -4,10 +4,12 @@ module Usmu
4
4
  # This class is used to represent a configuration file. This file should be a YAML file and called `usmu.yml`
5
5
  # by default.
6
6
  class Configuration
7
+ @log = Logging.logger[self]
8
+
7
9
  # @!attribute [r] config_file
8
10
  # @return [String] the name of the file used to load the configuration.
9
11
  attr_reader :config_file
10
- # @!attribute [r] config_file
12
+ # @!attribute [r] config_dir
11
13
  # @return [String] the folder that the configuration was loaded from.
12
14
  attr_reader :config_dir
13
15
 
@@ -15,6 +17,7 @@ module Usmu
15
17
  #
16
18
  # @return [Usmu::Configuration]
17
19
  def self.from_file(filename)
20
+ @log.debug("Loading configuration from #{filename}")
18
21
  from_hash(YAML.load_file(filename), filename)
19
22
  end
20
23
 
@@ -31,6 +34,12 @@ module Usmu
31
34
  get_path @config['source'] || 'src'
32
35
  end
33
36
 
37
+ # @!attribute [r] source_files
38
+ # @return [Array<String>] a list of renderable files in the source folder
39
+ def source_files
40
+ get_files source_path
41
+ end
42
+
34
43
  # @!attribute [r] destination_path
35
44
  # @return [String] the full path to the destination folder
36
45
  def destination_path
@@ -43,6 +52,12 @@ module Usmu
43
52
  get_path @config['layouts'] || 'layouts'
44
53
  end
45
54
 
55
+ # @!attribute [r] layouts_files
56
+ # @return [Array<String>] a list of renderable files in the layouts folder
57
+ def layouts_files
58
+ get_files layouts_path
59
+ end
60
+
46
61
  # An index accessor to directly access the configuration file. It should be noted that `['source']` and
47
62
  # `#source_path` and other similar pairs will have different values. `['source']` is the raw value from the
48
63
  # configuration file while the latter is a path on the system, potentially altered by the path from the current
@@ -63,6 +78,7 @@ module Usmu
63
78
  # @see Usmu::Configuration.from_file
64
79
  # @see Usmu::Configuration.from_hash
65
80
  def initialize(hash, config_path)
81
+ @log = Logging.logger[self]
66
82
  @config = hash
67
83
  @config_file = config_path
68
84
  @config_dir = config_path ? File.dirname(config_path) : nil
@@ -79,5 +95,28 @@ module Usmu
79
95
  File.join(@config_dir, path)
80
96
  end
81
97
  end
98
+
99
+ # Helper to determine if a filename is excluded according to the exclude configuration parameter.
100
+ #
101
+ # @return [Boolean]
102
+ def excluded?(filename)
103
+ flags = defined?(File::FNM_EXTGLOB) ? File::FNM_EXTGLOB | File::FNM_PATHNAME : File::FNM_PATHNAME
104
+ (@config['exclude'] || []).each do |f|
105
+ f += '**/*' if f[-1] == '/'
106
+ return true if File.fnmatch(f, filename, flags)
107
+ end
108
+ false
109
+ end
110
+
111
+ # Helper function to search a directory recursively and return a list of files that are renderable.
112
+ #
113
+ # @param [String] directory the directory to search
114
+ # @param [Boolean] layout is this directory a layouts_path
115
+ # @return [Array<Usmu::Layout>, Array<Usmu::StaticFile>] Either an array of Layouts or StaticFiles in the directory
116
+ def get_files(directory)
117
+ Dir["#{directory}/**/*"].select {|f| !f.match(/\.meta.yml$/) }.map do |f|
118
+ f[(directory.length + 1)..f.length]
119
+ end.select {|f| not excluded? f}
120
+ end
82
121
  end
83
122
  end
data/lib/usmu/layout.rb CHANGED
@@ -42,7 +42,8 @@ module Usmu
42
42
  end
43
43
  @metadata = metadata
44
44
 
45
- @parent = Layout.find_layout(configuration, metadata['layout'])
45
+ @parent = nil
46
+ @parent = Layout.find_layout(configuration, self.metadata['layout'])
46
47
  end
47
48
 
48
49
  # @!attribute [r] metadata
@@ -53,9 +54,9 @@ module Usmu
53
54
  # This will include any metadata from parent templates and default metadata
54
55
  def metadata
55
56
  if @parent.nil?
56
- @metadata.deep_merge(@configuration['default meta'] || {})
57
+ (@configuration['default meta'] || {}).dup.deep_merge!(@metadata)
57
58
  else
58
- @metadata.deep_merge(@parent.metadata)
59
+ @parent.metadata.deep_merge!(@metadata)
59
60
  end
60
61
  end
61
62
 
@@ -75,10 +76,25 @@ module Usmu
75
76
  end
76
77
  end
77
78
 
79
+ # @!attribute [r] input_path
80
+ # @return [String] the full path to the file in the source directory
81
+ def input_path
82
+ File.join(content_path, @name)
83
+ end
84
+
78
85
  # @!attribute [r] output_extension
79
86
  # @return [String] the extension to use with the output file.
80
87
  def output_extension
81
- 'html'
88
+ case @type
89
+ when 'erb', 'rhtml', 'erubis', 'liquid'
90
+ nil
91
+ when 'coffee'
92
+ 'js'
93
+ when 'less', 'sass', 'scss'
94
+ 'css'
95
+ else
96
+ 'html'
97
+ end
82
98
  end
83
99
 
84
100
  # @!attribute [r] output_filename
@@ -86,7 +102,11 @@ module Usmu
86
102
  #
87
103
  # Returns the filename to use for the output directory with any modifications to the input filename required.
88
104
  def output_filename
89
- @name[0..@name.rindex('.')] + output_extension
105
+ if output_extension
106
+ @name[0..@name.rindex('.')] + output_extension
107
+ else
108
+ @name[0..@name.rindex('.') - 1]
109
+ end
90
110
  end
91
111
 
92
112
  # Static method to create a layout for a given configuration by it's name if it exists. This differs from
@@ -100,13 +120,16 @@ module Usmu
100
120
  # that name is nilable and can also be passed in as an Usmu::Layout already for testing purposes.
101
121
  # @return [Usmu::Layout]
102
122
  def self.find_layout(configuration, name)
103
- if name.class.name == 'String'
123
+ if name === 'none'
124
+ nil
125
+ elsif name.class.name == 'String'
104
126
  Dir["#{configuration.layouts_path}/#{name}.*"].each do |f|
105
127
  filename = File.basename(f)
106
128
  if filename != "#{name}.meta.yml"
107
129
  return new(configuration, f[(configuration.layouts_path.length + 1)..f.length])
108
130
  end
109
131
  end
132
+ nil
110
133
  else
111
134
  name
112
135
  end
@@ -160,7 +183,7 @@ module Usmu
160
183
  #
161
184
  # @return [Hash]
162
185
  def get_variables(variables)
163
- variables.deep_merge(metadata).deep_merge({site: @configuration})
186
+ {site: @configuration}.deep_merge!(metadata).deep_merge!(variables)
164
187
  end
165
188
  end
166
189
  end
data/lib/usmu/page.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'usmu/layout'
1
2
 
2
3
  module Usmu
3
4
  # Represents a page in the source directory of the website.
@@ -0,0 +1,65 @@
1
+
2
+ module Usmu
3
+ class Plugin
4
+ def initialize
5
+ @log = Logging.logger['Usmu::Plugin']
6
+ end
7
+
8
+ # Loads all plugins that are available as gems. This is determined by looking at the gem's name. Anything prefixed
9
+ # with the string 'usmu-' will be recognised as a plugin. This will load the gem according to the RubyGems
10
+ # recommendations for naming schemes. A gem named `usmu-s3_uploader` will be loaded by requiring the path
11
+ # `'usmu/s3_uploader'` and then then the class `Usmu::S3Uploader` will be instantiated as the plugins interface.
12
+ #
13
+ # @return [void]
14
+ def load_plugins
15
+ loaded = []
16
+ @log.debug('Loading plugins')
17
+ @log.debug('Loaded Usmu::Plugin::Core')
18
+ plugins.push Usmu::Plugin::Core.new
19
+ Gem::Specification.find_all { |s| s.name =~ /^usmu-/ }.each do |spec|
20
+ load_path = spec.name.gsub('-', '/')
21
+ require load_path
22
+
23
+ unless loaded.include? load_path
24
+ loaded << load_path
25
+ klass = load_path.split('/').map {|s| s.split('_').map(&:capitalize).join }.join('::')
26
+ @log.debug("Loading plugin #{klass} from '#{load_path}'")
27
+ plugins.push plugin_get(klass)
28
+ end
29
+ end
30
+ @log.debug("Loaded: #{plugins.inspect}")
31
+ end
32
+
33
+ # @!attribute [r] plugins
34
+ # @return [Array] a list of all plugins discovered and loaded.
35
+ def plugins
36
+ @plugins ||= []
37
+ end
38
+
39
+ # Call all plugins and collate any data returned. nil can be returned explicitly to say this plugin has nothing to
40
+ # return.
41
+ # @param [Symbol] method The name of the method to call. This should be namespaced somehow. For example, a plugin
42
+ # called `usmu-s3` could use the method namespace `s3` and have a hook called `:s3_upload`
43
+ # @param [Array] args The arguments to pass through to plugins. Can be empty.
44
+ def invoke(method, *args)
45
+ @log.debug("Invoking plugin API #{method}")
46
+ plugins.map do |p|
47
+ if p.respond_to? method
48
+ @log.debug("Sending message to #{p.class.name}")
49
+ p.public_send method, *args
50
+ else
51
+ nil
52
+ end
53
+ end.select {|i| i}
54
+ end
55
+
56
+ private
57
+
58
+ def plugin_get(klass)
59
+ object.const_get(klass).new
60
+ rescue NameError
61
+ # Ruby 1.9.3, dowp
62
+ klass.split('::').reduce(Object) {|memo, o| memo.const_get o }.new
63
+ end
64
+ end
65
+ end