nesta 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -11
  3. data/.hound.yml +2 -0
  4. data/.travis.yml +2 -1
  5. data/CHANGES +43 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +18 -23
  8. data/lib/nesta/app.rb +0 -5
  9. data/lib/nesta/commands.rb +5 -288
  10. data/lib/nesta/commands/command.rb +58 -0
  11. data/lib/nesta/commands/demo.rb +1 -0
  12. data/lib/nesta/commands/demo/content.rb +38 -0
  13. data/lib/nesta/commands/edit.rb +21 -0
  14. data/lib/nesta/commands/new.rb +57 -0
  15. data/lib/nesta/commands/plugin.rb +1 -0
  16. data/lib/nesta/commands/plugin/create.rb +82 -0
  17. data/lib/nesta/commands/theme.rb +3 -0
  18. data/lib/nesta/commands/theme/create.rb +36 -0
  19. data/lib/nesta/commands/theme/enable.rb +22 -0
  20. data/lib/nesta/commands/theme/install.rb +29 -0
  21. data/lib/nesta/config.rb +1 -6
  22. data/lib/nesta/models.rb +18 -20
  23. data/lib/nesta/version.rb +1 -1
  24. data/nesta.gemspec +1 -0
  25. data/smoke-test.sh +24 -19
  26. data/spec/commands/demo/content_spec.rb +65 -0
  27. data/spec/commands/edit_spec.rb +27 -0
  28. data/spec/commands/new_spec.rb +88 -0
  29. data/spec/commands/plugin/create_spec.rb +97 -0
  30. data/spec/commands/system_spec.rb +25 -0
  31. data/spec/commands/theme/create_spec.rb +41 -0
  32. data/spec/commands/theme/enable_spec.rb +44 -0
  33. data/spec/commands/theme/install_spec.rb +56 -0
  34. data/spec/config_spec.rb +3 -3
  35. data/spec/models_spec.rb +43 -25
  36. data/spec/page_spec.rb +18 -2
  37. data/spec/spec_helper.rb +23 -0
  38. data/templates/Gemfile +1 -1
  39. data/templates/plugins/Gemfile +4 -0
  40. data/templates/plugins/README.md +13 -0
  41. data/templates/plugins/Rakefile +58 -0
  42. data/templates/plugins/gitignore +3 -0
  43. data/templates/plugins/lib/init.rb +13 -0
  44. data/templates/plugins/lib/required.rb +3 -0
  45. data/templates/plugins/lib/version.rb +5 -0
  46. data/templates/plugins/plugin.gemspec +28 -0
  47. data/views/analytics.haml +9 -10
  48. data/views/master.sass +1 -1
  49. metadata +53 -5
  50. data/spec/commands_spec.rb +0 -395
@@ -0,0 +1,58 @@
1
+ module Nesta
2
+ module Commands
3
+ class UsageError < RuntimeError; end
4
+
5
+ module Command
6
+ def run_process(*args)
7
+ system(*args)
8
+ if ! $?.success?
9
+ message = if $?.exitstatus == 127
10
+ "#{args[0]} not found"
11
+ else
12
+ "'#{args.join(' ')}' failed with status #{$?.exitstatus}"
13
+ end
14
+ $stderr.puts "Error: #{message}"
15
+ exit 1
16
+ end
17
+ end
18
+
19
+ def fail(message)
20
+ $stderr.puts "Error: #{message}"
21
+ exit 1
22
+ end
23
+
24
+ def template_root
25
+ File.expand_path('../../../templates', File.dirname(__FILE__))
26
+ end
27
+
28
+ def copy_template(src, dest)
29
+ FileUtils.mkdir_p(File.dirname(dest))
30
+ template = ERB.new(File.read(File.join(template_root, src)), nil, "-")
31
+ File.open(dest, 'w') { |file| file.puts template.result(binding) }
32
+ end
33
+
34
+ def copy_templates(templates)
35
+ templates.each { |src, dest| copy_template(src, dest) }
36
+ end
37
+
38
+ def update_config_yaml(pattern, replacement)
39
+ configured = false
40
+ File.open(Nesta::Config.yaml_path, 'r+') do |file|
41
+ output = ''
42
+ file.each_line do |line|
43
+ if configured
44
+ output << line
45
+ else
46
+ output << line.sub(pattern, replacement)
47
+ configured = true if line =~ pattern
48
+ end
49
+ end
50
+ output << "#{replacement}\n" unless configured
51
+ file.pos = 0
52
+ file.print(output)
53
+ file.truncate(file.pos)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path('demo/content', File.dirname(__FILE__))
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ module Demo
6
+ class Content
7
+ include Command
8
+
9
+ def initialize(*args)
10
+ @dir = 'content-demo'
11
+ end
12
+
13
+ def clone_or_update_repository
14
+ repository = 'git://github.com/gma/nesta-demo-content.git'
15
+ path = Nesta::Path.local(@dir)
16
+ if File.exist?(path)
17
+ FileUtils.cd(path) { run_process('git', 'pull', 'origin', 'master') }
18
+ else
19
+ run_process('git', 'clone', repository, path)
20
+ end
21
+ end
22
+
23
+ def configure_git_to_ignore_repo
24
+ excludes = Nesta::Path.local('.git/info/exclude')
25
+ if File.exist?(excludes) && File.read(excludes).scan(@dir).empty?
26
+ File.open(excludes, 'a') { |file| file.puts @dir }
27
+ end
28
+ end
29
+
30
+ def execute
31
+ clone_or_update_repository
32
+ configure_git_to_ignore_repo
33
+ update_config_yaml(/^\s*#?\s*content:.*/, "content: #{@dir}")
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ class Edit
6
+ include Command
7
+
8
+ def initialize(*args)
9
+ @filename = Nesta::Config.page_path(args.shift)
10
+ end
11
+
12
+ def execute
13
+ editor = ENV.fetch('EDITOR')
14
+ rescue IndexError
15
+ $stderr.puts "No editor: set EDITOR environment variable"
16
+ else
17
+ run_process(editor, @filename)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path('command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ class New
6
+ include Command
7
+
8
+ def initialize(*args)
9
+ path = args.shift
10
+ options = args.shift || {}
11
+ path.nil? && (raise UsageError.new('path not specified'))
12
+ if File.exist?(path)
13
+ raise RuntimeError.new("#{path} already exists")
14
+ end
15
+ @path = path
16
+ @options = options
17
+ end
18
+
19
+ def make_directories
20
+ %w[content/attachments content/pages].each do |dir|
21
+ FileUtils.mkdir_p(File.join(@path, dir))
22
+ end
23
+ end
24
+
25
+ def have_rake_tasks?
26
+ @options['vlad']
27
+ end
28
+
29
+ def create_repository
30
+ FileUtils.cd(@path) do
31
+ File.open('.gitignore', 'w') do |file|
32
+ file.puts %w[._* .*.swp .bundle .DS_Store .sass-cache].join("\n")
33
+ end
34
+ run_process('git', 'init')
35
+ run_process('git', 'add', '.')
36
+ run_process('git', 'commit', '-m', 'Initial commit')
37
+ end
38
+ end
39
+
40
+ def execute
41
+ make_directories
42
+ templates = {
43
+ 'config.ru' => "#{@path}/config.ru",
44
+ 'config/config.yml' => "#{@path}/config/config.yml",
45
+ 'index.haml' => "#{@path}/content/pages/index.haml",
46
+ 'Gemfile' => "#{@path}/Gemfile"
47
+ }
48
+ templates['Rakefile'] = "#{@path}/Rakefile" if have_rake_tasks?
49
+ if @options['vlad']
50
+ templates['config/deploy.rb'] = "#{@path}/config/deploy.rb"
51
+ end
52
+ copy_templates(templates)
53
+ create_repository if @options['git']
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path('plugin/create', File.dirname(__FILE__))
@@ -0,0 +1,82 @@
1
+ require File.expand_path('../command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ module Plugin
6
+ class Create
7
+ include Command
8
+
9
+ def initialize(*args)
10
+ name = args.shift
11
+ name.nil? && (raise UsageError.new('name not specified'))
12
+ @name = name
13
+ @gem_name = "nesta-plugin-#{name}"
14
+ if File.exist?(@gem_name)
15
+ raise RuntimeError.new("#{@gem_name} already exists")
16
+ end
17
+ end
18
+
19
+ def lib_path(*parts)
20
+ File.join(@gem_name, 'lib', *parts)
21
+ end
22
+
23
+ def module_name
24
+ module_names.join('::')
25
+ end
26
+
27
+ def nested_module_definition_with_version
28
+ indent_level = 2
29
+ indent_with = ' '
30
+
31
+ lines = module_names.map { |name| "module #{name}\n" }
32
+ indent_levels = 0.upto(module_names.size - 1).to_a
33
+
34
+ lines << "VERSION = '0.1.0'\n"
35
+ indent_levels << module_names.size
36
+
37
+ (module_names.size - 1).downto(0).each do |indent_level|
38
+ lines << "end\n"
39
+ indent_levels << indent_level
40
+ end
41
+
42
+ ''.tap do |code|
43
+ lines.each_with_index do |line, i|
44
+ code << ' ' * (indent_levels[i] + 2) + line
45
+ end
46
+ end
47
+ end
48
+
49
+ def make_directories
50
+ FileUtils.mkdir_p(File.join(@gem_name, 'lib', @gem_name))
51
+ end
52
+
53
+ def gem_path(path)
54
+ File.join(@gem_name, path)
55
+ end
56
+
57
+ def execute
58
+ make_directories
59
+ copy_templates(
60
+ 'plugins/README.md' => gem_path('README.md'),
61
+ 'plugins/gitignore' => gem_path('.gitignore'),
62
+ 'plugins/plugin.gemspec' => gem_path("#{@gem_name}.gemspec"),
63
+ 'plugins/Gemfile' => gem_path('Gemfile'),
64
+ 'plugins/lib/required.rb' => gem_path("lib/#{@gem_name}.rb"),
65
+ 'plugins/lib/version.rb' => gem_path("lib/#{@gem_name}/version.rb"),
66
+ 'plugins/lib/init.rb' => gem_path("lib/#{@gem_name}/init.rb"),
67
+ 'plugins/Rakefile' => gem_path('Rakefile')
68
+ )
69
+ Dir.chdir(@gem_name) do
70
+ run_process('git', 'init')
71
+ run_process('git', 'add', '.')
72
+ end
73
+ end
74
+
75
+ private
76
+ def module_names
77
+ @name.split('-').map { |name| name.capitalize }
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ require File.expand_path('theme/create', File.dirname(__FILE__))
2
+ require File.expand_path('theme/enable', File.dirname(__FILE__))
3
+ require File.expand_path('theme/install', File.dirname(__FILE__))
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ module Theme
6
+ class Create
7
+ include Command
8
+
9
+ def initialize(*args)
10
+ name = args.shift
11
+ options = args.shift || {}
12
+ name.nil? && (raise UsageError.new('name not specified'))
13
+ @name = name
14
+ @theme_path = Nesta::Path.themes(@name)
15
+ fail("#{@theme_path} already exists") if File.exist?(@theme_path)
16
+ end
17
+
18
+ def make_directories
19
+ FileUtils.mkdir_p(File.join(@theme_path, 'public', @name))
20
+ FileUtils.mkdir_p(File.join(@theme_path, 'views'))
21
+ end
22
+
23
+ def execute
24
+ make_directories
25
+ copy_templates(
26
+ 'themes/README.md' => "#{@theme_path}/README.md",
27
+ 'themes/app.rb' => "#{@theme_path}/app.rb",
28
+ 'themes/views/layout.haml' => "#{@theme_path}/views/layout.haml",
29
+ 'themes/views/page.haml' => "#{@theme_path}/views/page.haml",
30
+ 'themes/views/master.sass' => "#{@theme_path}/views/master.sass"
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ module Theme
6
+ class Enable
7
+ include Command
8
+
9
+ def initialize(*args)
10
+ name = args.shift
11
+ options = args.shift || {}
12
+ name.nil? && (raise UsageError.new('name not specified'))
13
+ @name = name
14
+ end
15
+
16
+ def execute
17
+ update_config_yaml(/^\s*#?\s*theme:.*/, "theme: #{@name}")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../command', File.dirname(__FILE__))
2
+
3
+ module Nesta
4
+ module Commands
5
+ module Theme
6
+ class Install
7
+ include Command
8
+
9
+ def initialize(*args)
10
+ url = args.shift
11
+ options = args.shift || {}
12
+ url.nil? && (raise UsageError.new('URL not specified'))
13
+ @url = url
14
+ @name = File.basename(url, '.git').sub(/nesta-theme-/, '')
15
+ end
16
+
17
+ def execute
18
+ run_process('git', 'clone', @url, "themes/#{@name}")
19
+ FileUtils.rm_r(File.join("themes/#{@name}", '.git'))
20
+ enable
21
+ end
22
+
23
+ def enable
24
+ Enable.new(@name).execute
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -90,18 +90,13 @@ module Nesta
90
90
  end
91
91
  private_class_method :yaml_exists?
92
92
 
93
- def self.can_use_yaml?
94
- ENV.keys.grep(/^NESTA/).empty? && yaml_exists?
95
- end
96
- private_class_method :can_use_yaml?
97
-
98
93
  def self.from_hash(hash, setting)
99
94
  hash.fetch(setting) { raise NotDefined.new(setting) }
100
95
  end
101
96
  private_class_method :from_hash
102
97
 
103
98
  def self.from_yaml(setting)
104
- raise NotDefined.new(setting) unless can_use_yaml?
99
+ raise NotDefined.new(setting) unless yaml_exists?
105
100
  self.yaml_conf ||= YAML::load(ERB.new(IO.read(yaml_path)).result)
106
101
  env_config = self.yaml_conf.fetch(Nesta::App.environment.to_s, {})
107
102
  begin
@@ -1,10 +1,10 @@
1
1
  require 'time'
2
2
 
3
- Tilt.register Tilt::MarukuTemplate, 'mdown'
4
- Tilt.register Tilt::KramdownTemplate, 'mdown'
5
- Tilt.register Tilt::BlueClothTemplate, 'mdown'
6
- Tilt.register Tilt::RDiscountTemplate, 'mdown'
7
- Tilt.register Tilt::RedcarpetTemplate, 'mdown'
3
+ Tilt.register Tilt::MarukuTemplate, 'mdown', 'md'
4
+ Tilt.register Tilt::KramdownTemplate, 'mdown', 'md'
5
+ Tilt.register Tilt::BlueClothTemplate, 'mdown', 'md'
6
+ Tilt.register Tilt::RDiscountTemplate, 'mdown', 'md'
7
+ Tilt.register Tilt::RedcarpetTemplate, 'mdown', 'md'
8
8
 
9
9
  module Nesta
10
10
  class HeadingNotSet < RuntimeError; end
@@ -12,7 +12,7 @@ module Nesta
12
12
  class MetadataParseError < RuntimeError; end
13
13
 
14
14
  class FileModel
15
- FORMATS = [:mdown, :haml, :textile]
15
+ FORMATS = [:mdown, :md, :haml, :textile]
16
16
  @@page_cache = {}
17
17
  @@filename_cache = {}
18
18
 
@@ -113,7 +113,7 @@ module Nesta
113
113
  (metadata('template') || 'page').to_sym
114
114
  end
115
115
 
116
- def to_html(scope = nil)
116
+ def to_html(scope = Object.new)
117
117
  convert_to_html(@format, scope, markup)
118
118
  end
119
119
 
@@ -128,7 +128,7 @@ module Nesta
128
128
  def keywords
129
129
  metadata('keywords')
130
130
  end
131
-
131
+
132
132
  def metadata(key)
133
133
  @metadata[key]
134
134
  end
@@ -220,7 +220,7 @@ module Nesta
220
220
 
221
221
  def heading
222
222
  regex = case @format
223
- when :mdown
223
+ when :mdown, :md
224
224
  /^#\s*(.*?)(\s*#+|$)/
225
225
  when :haml
226
226
  /^\s*%h1\s+(.*)/
@@ -236,7 +236,7 @@ module Nesta
236
236
  rescue HeadingNotSet
237
237
  raise LinkTextNotSet, "Need to link to '#{abspath}' but can't get link text"
238
238
  end
239
-
239
+
240
240
  def title
241
241
  metadata('title') || link_text
242
242
  rescue LinkTextNotSet
@@ -265,13 +265,13 @@ module Nesta
265
265
  def summary
266
266
  if summary_text = metadata("summary")
267
267
  summary_text.gsub!('\n', "\n")
268
- convert_to_html(@format, nil, summary_text)
268
+ convert_to_html(@format, Object.new, summary_text)
269
269
  end
270
270
  end
271
271
 
272
272
  def body_markup
273
273
  case @format
274
- when :mdown
274
+ when :mdown, :md
275
275
  markup.sub(/^#[^#].*$\r?\n(\r?\n)?/, '')
276
276
  when :haml
277
277
  markup.sub(/^\s*%h1\s+.*$\r?\n(\r?\n)?/, '')
@@ -280,23 +280,20 @@ module Nesta
280
280
  end
281
281
  end
282
282
 
283
- def body(scope = nil)
283
+ def body(scope = Object.new)
284
284
  convert_to_html(@format, scope, body_markup)
285
285
  end
286
286
 
287
287
  def categories
288
288
  paths = category_strings.map { |specifier| specifier.sub(/:-?\d+$/, '') }
289
- pages = valid_paths(paths).map { |p| Page.find_by_path(p) }
290
- pages.sort do |x, y|
291
- x.link_text.downcase <=> y.link_text.downcase
292
- end
289
+ valid_paths(paths).map { |p| Page.find_by_path(p) }
293
290
  end
294
291
 
295
292
  def priority(category)
296
293
  category_string = category_strings.detect do |string|
297
294
  string =~ /^#{category}([,:\s]|$)/
298
295
  end
299
- category_string && category_string.split(':', 2)[-1].to_i
296
+ category_string && category_string.split(':', 2)[-1].to_i
300
297
  end
301
298
 
302
299
  def parent
@@ -309,6 +306,7 @@ module Nesta
309
306
  return parent unless parent.nil?
310
307
  parent_path = File.dirname(parent_path)
311
308
  end
309
+ return categories.first unless categories.empty?
312
310
  Page.load('index')
313
311
  end
314
312
  end
@@ -384,15 +382,15 @@ module Nesta
384
382
  rescue EOFError
385
383
  else
386
384
  page = Page.load(path.strip)
385
+ current_depth = path.scan(INDENT).size
387
386
  if page
388
- current_depth = path.scan(INDENT).size
389
387
  if current_depth > depth
390
388
  sub_menu_for_depth(menu, depth) << [page]
391
389
  else
392
390
  sub_menu_for_depth(menu, current_depth) << page
393
391
  end
394
- append_menu_item(menu, file, current_depth)
395
392
  end
393
+ append_menu_item(menu, file, current_depth)
396
394
  end
397
395
 
398
396
  def self.sub_menu_for_depth(menu, depth)