awestructx 0.4.0 → 0.4.1.x1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/lib/awestruct/astruct_mixin.rb +13 -3
  2. data/lib/awestruct/cli/auto.rb +18 -4
  3. data/lib/awestruct/cli/deploy.rb +38 -0
  4. data/lib/awestruct/cli/invoker.rb +12 -1
  5. data/lib/awestruct/config.rb +10 -0
  6. data/lib/awestruct/dependencies.rb +102 -0
  7. data/lib/awestruct/deploy/github_pages_deploy.rb +61 -0
  8. data/lib/awestruct/deploy/rsync_deploy.rb +51 -0
  9. data/lib/awestruct/deployers.rb +15 -0
  10. data/lib/awestruct/engine.rb +49 -13
  11. data/lib/awestruct/extensions/atomizer.rb +3 -3
  12. data/lib/awestruct/extensions/minify.rb +21 -23
  13. data/lib/awestruct/extensions/posts.rb +4 -4
  14. data/lib/awestruct/extensions/sitemap.rb +1 -0
  15. data/lib/awestruct/handler_chains.rb +15 -32
  16. data/lib/awestruct/handlers/asciidoc_handler.rb +57 -0
  17. data/lib/awestruct/handlers/base_handler.rb +23 -4
  18. data/lib/awestruct/handlers/coffeescript_handler.rb +48 -0
  19. data/lib/awestruct/handlers/erb_handler.rb +44 -0
  20. data/lib/awestruct/handlers/file_handler.rb +6 -3
  21. data/lib/awestruct/handlers/front_matter_handler.rb +5 -0
  22. data/lib/awestruct/handlers/haml_handler.rb +14 -2
  23. data/lib/awestruct/handlers/layout_handler.rb +4 -2
  24. data/lib/awestruct/handlers/markdown_handler.rb +14 -0
  25. data/lib/awestruct/handlers/orgmode_handler.rb +48 -0
  26. data/lib/awestruct/handlers/page_delegating_handler.rb +54 -0
  27. data/lib/awestruct/handlers/restructuredtext_handler.rb +67 -0
  28. data/lib/awestruct/handlers/sass_handler.rb +7 -0
  29. data/lib/awestruct/handlers/scss_handler.rb +7 -0
  30. data/lib/awestruct/handlers/textile_handler.rb +15 -0
  31. data/lib/awestruct/layouts.rb +1 -0
  32. data/lib/awestruct/page.rb +27 -14
  33. data/lib/awestruct/page_loader.rb +15 -5
  34. data/lib/awestruct/pipeline.rb +7 -0
  35. data/lib/awestruct/version.rb +1 -1
  36. data/lib/guard/awestruct.rb +1 -1
  37. metadata +173 -267
@@ -1,4 +1,6 @@
1
1
 
2
+ require 'awestruct/dependencies'
3
+
2
4
  module Awestruct
3
5
 
4
6
  module AStructMixin
@@ -21,7 +23,7 @@ module Awestruct
21
23
 
22
24
  def [](key)
23
25
  r = super( key ) || super( key.to_sym ) || super( key.to_s )
24
- transform_entry( r )
26
+ transform_entry( key, r )
25
27
  end
26
28
 
27
29
  def method_missing(sym, *args, &blk)
@@ -46,8 +48,11 @@ module Awestruct
46
48
  end
47
49
  end
48
50
 
51
+ UNTRACKED_KEYS = [
52
+ :url,
53
+ ]
49
54
 
50
- def transform_entry(entry)
55
+ def transform_entry(for_key, entry)
51
56
  r = case(entry)
52
57
  when AStructMixin
53
58
  entry
@@ -55,10 +60,15 @@ module Awestruct
55
60
  #AStruct.new( entry )
56
61
  entry.extend( AStructMixin )
57
62
  when Array
58
- entry.map!{|i| transform_entry(i)}
63
+ entry.map!{|i| transform_entry( for_key, i)}
59
64
  else
60
65
  entry
61
66
  end
67
+ if ( self.is_a? Awestruct::Page )
68
+ unless UNTRACKED_KEYS.include? for_key.to_sym
69
+ Awestruct::Dependencies.track_dependency( self )
70
+ end
71
+ end
62
72
  r
63
73
  end
64
74
 
@@ -4,17 +4,31 @@ module Awestruct
4
4
  module CLI
5
5
  class Auto
6
6
 
7
- def initialize(path)
8
- @path = path
7
+ def initialize(config)
8
+ @config = config
9
9
  end
10
10
 
11
11
  def run()
12
12
  Guard.setup
13
- Guard.start( :guardfile=>File.dirname(__FILE__) + '/Guardfile',
14
- :watchdir=>@path,
13
+ Guard.start( :guardfile_contents=>guardfile_contents,
14
+ :watchdir=>@config.dir,
15
15
  :watch_all_modifications=>true )
16
16
  end
17
17
 
18
+ def guardfile_contents
19
+ ignored = [
20
+ "'.awestruct'",
21
+ "'#{File.basename( @config.tmp_dir )}'",
22
+ "'#{File.basename( @config.output_dir )}'",
23
+ ]
24
+ c = ''
25
+ c += "guard :awestruct do\n"
26
+ c += " watch %r(.*)\n"
27
+ c += " ignore_paths #{ignored.join(', ')}"
28
+ c += "end\n"
29
+ c
30
+ end
18
31
  end
32
+
19
33
  end
20
34
  end
@@ -0,0 +1,38 @@
1
+ require 'awestruct/deploy/rsync_deploy'
2
+ require 'awestruct/deploy/github_pages_deploy'
3
+
4
+ module Awestruct
5
+ module CLI
6
+
7
+ class Deploy
8
+
9
+ attr_accessor :site_config
10
+ attr_accessor :deploy_config
11
+
12
+ def initialize(site_config, deploy_config)
13
+ @site_config = site_config
14
+ @deploy_config = deploy_config
15
+ end
16
+
17
+ def run()
18
+ deploy_type = :rsync
19
+
20
+ if ( deploy_config['host'] == 'github_pages' )
21
+ deploy_type = :github_pages
22
+ end
23
+
24
+ deployer_class = Awestruct::Deployers.instance[ deploy_type ]
25
+
26
+ if ( deployer_class.nil? )
27
+ $stderr.puts "Unable to locate correct deployer for #{deploy_type}"
28
+ return
29
+ end
30
+
31
+ deployer = deployer_class.new( site_config, deploy_config )
32
+ deployer.run
33
+
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -3,6 +3,7 @@ require 'awestruct/cli/options'
3
3
  require 'awestruct/cli/generate'
4
4
  require 'awestruct/cli/auto'
5
5
  require 'awestruct/cli/server'
6
+ require 'awestruct/cli/deploy'
6
7
 
7
8
  require 'pathname'
8
9
 
@@ -64,6 +65,7 @@ module Awestruct
64
65
 
65
66
  def setup_config()
66
67
  @config = Awestruct::Config.new( Dir.pwd )
68
+ @config.track_dependencies = true if ( options.auto )
67
69
  end
68
70
 
69
71
  def invoke_init()
@@ -73,6 +75,7 @@ module Awestruct
73
75
  end
74
76
 
75
77
  def invoke_force()
78
+ FileUtils.rm_rf( File.join( config.dir, '.awestruct', 'dependency-cache' ) )
76
79
  FileUtils.rm_rf( config.output_dir )
77
80
  end
78
81
 
@@ -81,10 +84,18 @@ module Awestruct
81
84
  end
82
85
 
83
86
  def invoke_deploy()
87
+ deploy_config = profile[ 'deploy' ]
88
+
89
+ if ( deploy_config.nil? )
90
+ $stderr.puts "No configuration for 'deploy'"
91
+ return
92
+ end
93
+
94
+ Awestruct::CLI::Deploy.new( config, deploy_config ).run
84
95
  end
85
96
 
86
97
  def invoke_auto()
87
- run_in_thread( Awestruct::CLI::Auto.new( config.dir ) )
98
+ run_in_thread( Awestruct::CLI::Auto.new( config ) )
88
99
  end
89
100
 
90
101
  def invoke_server()
@@ -12,6 +12,10 @@ module Awestruct
12
12
  attr_accessor :skin_dir
13
13
  attr_accessor :tmp_dir
14
14
  attr_accessor :ignore
15
+ attr_accessor :track_dependencies
16
+
17
+ attr_accessor :images_dir
18
+ attr_accessor :stylesheets_dir
15
19
 
16
20
  def initialize(dir = Dir.pwd)
17
21
  @dir = Pathname.new( dir )
@@ -22,7 +26,13 @@ module Awestruct
22
26
  @extension_dir = Pathname.new( File.join(dir, '_ext') )
23
27
  @skin_dir = Pathname.new( File.join(dir, '_skin') )
24
28
  @tmp_dir = Pathname.new( File.join(dir, '_tmp') )
29
+
30
+ @images_dir = Pathname.new( File.join(dir, 'images') )
31
+ @stylesheets_dir = Pathname.new( File.join(dir, 'stylesheets') )
32
+
25
33
  @ignore = File.exists?(ignore_file = File.join(dir, ".awestruct_ignore")) ? Dir[*IO.read(ignore_file).each_line.map(&:strip)] : []
34
+
35
+ @track_dependencies = false
26
36
  end
27
37
 
28
38
  end
@@ -0,0 +1,102 @@
1
+
2
+ module Awestruct
3
+ class Dependencies
4
+
5
+ attr_reader :page
6
+ attr_reader :dependencies
7
+ attr_reader :dependents
8
+
9
+
10
+ def self.top_page
11
+ @pages ||= []
12
+ @pages.first
13
+ end
14
+
15
+ def self.push_page(page)
16
+ if ( top_page.nil? )
17
+ page.dependencies.clear
18
+ else
19
+ top_page.dependencies.add_dependency( page )
20
+ end
21
+ @pages.push( page )
22
+ end
23
+
24
+ def self.pop_page
25
+ page = @pages.pop
26
+ if ( @pages.empty? && ! page.nil? )
27
+ page.dependencies.persist!
28
+ end
29
+ end
30
+
31
+
32
+ def self.track_dependency(dep)
33
+ return if top_page.nil?
34
+ return if top_page == dep
35
+ top_page.dependencies.add_dependency(dep)
36
+ end
37
+
38
+ def initialize(page)
39
+ @page = page
40
+ @dependencies = Set.new
41
+ @dependents = Set.new
42
+ end
43
+
44
+ def <<(dep)
45
+ add_dependency( dep )
46
+ end
47
+
48
+ def add_dependency(dep)
49
+ return if @page.do_not_track_dependencies
50
+ return if @page.output_path.nil?
51
+ return if dep == @page
52
+ @dependencies << dep
53
+ dep.dependencies.add_dependent( page )
54
+ end
55
+
56
+ def add_dependent(dep)
57
+ @dependents << dep
58
+ end
59
+
60
+ def remove_dependent(dep)
61
+ @dependents.delete( dep )
62
+ end
63
+
64
+ def clear
65
+ @dependencies.clear
66
+ @dependents.each{|d| d.remove_dependent( page ) }
67
+ end
68
+
69
+ def persist!
70
+ return if page.output_path.nil? || page.output_path == ''
71
+ file = File.join( @page.site.config.dir, '.awestruct', 'dependency-cache', page.output_path )
72
+ FileUtils.mkdir_p( File.dirname( file ) )
73
+ File.open( file, 'w' ) do |file|
74
+ @dependencies.collect{|e| e.relative_source_path }.uniq.each do |d|
75
+ file.puts d unless d.nil?
76
+ end
77
+ end
78
+ end
79
+
80
+ def load!
81
+ return if page.output_path.nil? || page.output_path == ''
82
+ file = File.join( @page.site.config.dir, '.awestruct', 'dependency-cache', page.output_path )
83
+ #puts "load #{file}"
84
+ if ( File.exist?( file ) )
85
+ File.open( file, 'r' ) do |file|
86
+ file.lines.each do |line|
87
+ d = find_page_by_path( line.strip )
88
+ add_dependency( d ) unless d.nil?
89
+ end
90
+ end
91
+ return true
92
+ end
93
+ false
94
+ end
95
+
96
+ def find_page_by_path(path)
97
+ page.site.pages_by_relative_source_path[ path ]
98
+ end
99
+
100
+
101
+ end
102
+ end
@@ -0,0 +1,61 @@
1
+ require 'awestruct/deployers'
2
+
3
+ module Awestruct
4
+ module Deploy
5
+
6
+ class GitHubPagesDeploy
7
+ def initialize( site_config, deploy_config )
8
+ @site_path = site_config.output_dir
9
+ @branch = deploy_config[ 'branch' ] || 'gh-pages'
10
+ end
11
+
12
+ def run
13
+ git.status.changed.empty? ? publish_site : message_for(:existing_changes)
14
+ end
15
+
16
+ private
17
+ def git
18
+ @git ||= Git.open('.')
19
+ end
20
+
21
+ def publish_site
22
+ current_branch = git.branch
23
+ checkout_pages_branch
24
+ add_and_commit_site @site_path
25
+ push_and_restore current_branch
26
+ end
27
+
28
+ def checkout_pages_branch
29
+ git.branch( @branch ).checkout
30
+ end
31
+
32
+ def add_and_commit_site( path )
33
+ git.with_working( path ) do
34
+ git.add(".")
35
+ begin
36
+ git.commit("Published #{@branch} to GitHub pages.")
37
+ rescue Git::GitExecuteError => e
38
+ $stderr.puts "Can't commit. #{e}."
39
+ end
40
+ end
41
+ end
42
+
43
+ def push_and_restore( original_branch )
44
+ git.reset_hard
45
+ git.push( 'origin', @branch )
46
+ git.checkout( original_branch )
47
+ end
48
+
49
+ def message_for( key )
50
+ $stderr.puts case key
51
+ when :existing_changes
52
+ "You have uncommitted changes in the working branch. Please commit or stash them."
53
+ else
54
+ "An error occured."
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ Awestruct::Deployers.instance[ :github_pages ] = Awestruct::Deploy::GitHubPagesDeploy
@@ -0,0 +1,51 @@
1
+ require 'awestruct/deployers'
2
+
3
+ require 'open3'
4
+
5
+ module Awestruct
6
+ module Deploy
7
+ class RSyncDeploy
8
+
9
+ def initialize(site_config, deploy_config)
10
+ @site_path = File.join( site_config.output_dir, '/' )
11
+ @host = deploy_config['host']
12
+ @path = File.join( deploy_config['path'], '/' )
13
+ end
14
+
15
+ def run
16
+ cmd = "rsync -r -l -i --no-p --no-g --chmod=Dg+s,ug+w --delete #{@site_path} #{@host}:#{@path}"
17
+ Open3.popen3( cmd ) do |stdin, stdout, stderr|
18
+ stdin.close
19
+ threads = []
20
+ threads << Thread.new(stdout) do |i|
21
+ while ( ! i.eof? )
22
+ line = i.readline
23
+ case line[0,9]
24
+ when '<f.sT....'
25
+ puts " updating #{line[10..-1]}"
26
+ when 'cd+++++++'
27
+ puts " creating #{line[10..-1]}"
28
+ when '<f+++++++'
29
+ puts " adding #{line[10..-1]}"
30
+ when '<f..T....'
31
+ # ignoring unchanged files
32
+ # puts " no change to #{line[10..-1]}"
33
+ else
34
+ puts line
35
+ end
36
+ end
37
+ end
38
+ threads << Thread.new(stderr) do |i|
39
+ while ( ! i.eof? )
40
+ line = i.readline
41
+ puts line
42
+ end
43
+ end
44
+ threads.each{|t|t.join}
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ Awestruct::Deployers.instance[ :rsync ] = Awestruct::Deploy::RSyncDeploy
@@ -0,0 +1,15 @@
1
+
2
+ module Awestruct
3
+
4
+ class Deployers < Hash
5
+ def self.instance
6
+ @instance ||= Deployers.new
7
+ end
8
+
9
+ def self.register( key, cls )
10
+ Deployers.instance[ key.to_sym ] = cls
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -10,6 +10,7 @@ require 'awestruct/page_loader'
10
10
  require 'awestruct/extensions/pipeline'
11
11
 
12
12
  require 'fileutils'
13
+ require 'set'
13
14
 
14
15
  class OpenStruct
15
16
  def inspect
@@ -38,7 +39,6 @@ module Awestruct
38
39
  @pipeline = Pipeline.new
39
40
  @site_page_loader = PageLoader.new( @site )
40
41
  @layout_page_loader = PageLoader.new( @site, :layouts )
41
- adjust_load_path
42
42
  end
43
43
 
44
44
  def config
@@ -46,6 +46,7 @@ module Awestruct
46
46
  end
47
47
 
48
48
  def run(profile, base_url, default_base_url, force=false)
49
+ adjust_load_path
49
50
  load_site_yaml(profile)
50
51
  set_base_url( base_url, default_base_url )
51
52
  load_yamls
@@ -54,9 +55,24 @@ module Awestruct
54
55
  execute_pipeline
55
56
  configure_compass
56
57
  set_urls( site.pages )
58
+ build_page_index
57
59
  generate_output
58
60
  end
59
61
 
62
+ def build_page_index
63
+ site.pages_by_relative_source_path = {}
64
+ site.pages.each do |p|
65
+ if ( p.relative_source_path )
66
+ site.pages_by_relative_source_path[ p.relative_source_path ] = p
67
+ end
68
+ end
69
+ site.layouts.each do |p|
70
+ if ( p.relative_source_path )
71
+ site.pages_by_relative_source_path[ p.relative_source_path ] = p
72
+ end
73
+ end
74
+ end
75
+
60
76
  def set_base_url(base_url, default_base_url)
61
77
  if ( base_url )
62
78
  site.base_url = base_url
@@ -191,27 +207,47 @@ module Awestruct
191
207
  generated_path = File.join( site.config.output_dir, page.output_path )
192
208
  if ( page.stale_output?( generated_path ) )
193
209
  generate_page( page, generated_path )
210
+ else
211
+ generate_page( page, generated_path, false )
194
212
  end
195
213
  end
196
214
  end
197
215
 
198
- def generate_page(page, generated_path)
199
- puts "Generating: #{generated_path}"
200
- FileUtils.mkdir_p( File.dirname( generated_path ) )
201
- File.open( generated_path, 'w' ) do |file|
202
- file << page.rendered_content
216
+ def generate_page(page, generated_path, produce_output=true)
217
+ if ( produce_output )
218
+ puts "Generating: #{generated_path}"
219
+ FileUtils.mkdir_p( File.dirname( generated_path ) )
220
+ File.open( generated_path, 'w' ) do |file|
221
+ file << page.rendered_content
222
+ end
223
+ elsif ( site.config.track_dependencies )
224
+ if page.dependencies.load!
225
+ puts "Cached: #{generated_path}"
226
+ else
227
+ puts "Analyzing: #{generated_path}"
228
+ page.rendered_content
229
+ end
203
230
  end
204
231
  end
205
232
 
206
233
  def generate_page_by_output_path(path)
207
234
  full_path = File.join( '', path )
208
- #puts "regen path #{full_path}"
209
- page = site.pages.find{|p| p.relative_source_path.to_s==full_path}
210
- if ( page.nil? )
211
- #puts "Unable to locate page for #{path}"
212
- else
213
- generated_path = File.join( site.config.output_dir, page.output_path )
214
- generate_page(page, generated_path)
235
+ page = site.pages.find{|p| p.relative_source_path.to_s==full_path} || site.layouts.find{|p| p.relative_source_path.to_s==full_path}
236
+ return if page.nil?
237
+
238
+ #puts "regen page #{page.inspect}"
239
+ #puts "page.dependents #{page.dependencies.dependents.inspect}"
240
+
241
+ regen_pages = Set.new
242
+ regen_pages << page unless ( page.output_path.nil? )
243
+ regen_pages += page.dependencies.dependents
244
+
245
+ #puts regen_pages.collect{|e|e.output_path}.inspect
246
+ regen_pages.each do |p|
247
+ unless ( p.output_path.nil? || p.__is_layout )
248
+ generated_path = File.join( site.config.output_dir, p.output_path )
249
+ generate_page( p, generated_path )
250
+ end
215
251
  end
216
252
  end
217
253
 
@@ -2,8 +2,8 @@ module Awestruct
2
2
  module Extensions
3
3
  class Atomizer
4
4
 
5
- def initialize(entries_name, output_path, opts={})
6
- @entries_name = entries_name
5
+ def initialize(entries, output_path, opts={})
6
+ @entries = entries
7
7
  @output_path = output_path
8
8
  @num_entries = opts[:num_entries] || 50
9
9
  @content_url = opts[:content_url]
@@ -11,7 +11,7 @@ module Awestruct
11
11
  end
12
12
 
13
13
  def execute(site)
14
- entries = site.send( @entries_name ) || []
14
+ entries = @entries.is_a?(Array) ? @entries : site.send( @entries ) || []
15
15
  unless ( @num_entries == :all )
16
16
  entries = entries[0, @num_entries]
17
17
  end
@@ -12,10 +12,10 @@ require 'fileutils'
12
12
  #
13
13
  # These commands must be available on your PATH in order to use them.
14
14
  #
15
- # This class is loaded as a transformer in the Awestruct pipeline. The
15
+ # This class is loaded as a transformer into the Awestruct pipeline. The
16
16
  # constructor accepts an array of symbols representing the file types to minimize.
17
17
  #
18
- # extension Awestruct::Extensions::Minify.new
18
+ # transformer Awestruct::Extensions::Minify.new
19
19
  #
20
20
  # This transform recognizes the following symbols:
21
21
  #
@@ -57,30 +57,28 @@ module Awestruct
57
57
 
58
58
  def transform(site, page, input)
59
59
  if site.minify
60
- ext = File.extname(page.output_path)[1..-1].to_sym
61
- if @types.include?(ext)
62
- case ext
63
- when :html
64
- print "minifying html #{page.output_path}"
65
- htmlcompressor(page, input, site.minify_html_opts)
66
- when :css
67
- print "minifying css #{page.output_path}"
68
- yuicompressor(page, input, :css)
69
- when :js
70
- print "minifying js #{page.output_path}"
71
- yuicompressor(page, input, :js)
72
- when :png
73
- print "minifying png #{page.output_path}"
74
- pngcrush(page, input)
75
- else
76
- input
60
+ ext = File.extname(page.output_path)
61
+ if !ext.empty?
62
+ ext_sym = ext[1..-1].to_sym
63
+ if @types.include?(ext_sym)
64
+ case ext_sym
65
+ when :html
66
+ print "minifying html #{page.output_path}"
67
+ input = htmlcompressor(page, input, site.minify_html_opts)
68
+ when :css
69
+ print "minifying css #{page.output_path}"
70
+ input = yuicompressor(page, input, :css)
71
+ when :js
72
+ print "minifying js #{page.output_path}"
73
+ input = yuicompressor(page, input, :js)
74
+ when :png
75
+ print "minifying png #{page.output_path}"
76
+ input = pngcrush(page, input)
77
+ end
77
78
  end
78
- else
79
- input
80
79
  end
81
- else
82
- input
83
80
  end
81
+ input
84
82
  end
85
83
 
86
84
  private
@@ -27,22 +27,22 @@ module Awestruct
27
27
  date = Time.parse page.date
28
28
  end
29
29
  year = date.year
30
- month = date.month
31
- day = date.day
30
+ month = sprintf( "%02d", date.month )
31
+ day = sprintf( "%02d", date.day )
32
32
  page.date = Time.utc(year, month, day)
33
33
  slug = $1
34
34
  end
35
35
 
36
36
  # if a date was found create a post
37
37
  if( year and month and day)
38
- page.slug = slug
38
+ page.slug ||= slug
39
39
  #context = OpenStruct.new({
40
40
  #:site=>site,
41
41
  #:page=>page,
42
42
  #})
43
43
  context = page.create_context
44
44
  #page.body = page.render( context )
45
- page.output_path = "#{@path_prefix}/#{year}/#{month}/#{day}/#{slug}.html"
45
+ page.output_path = "#{@path_prefix}/#{year}/#{month}/#{day}/#{page.slug}.html"
46
46
  #page.layout = 'post'
47
47
  posts << page
48
48
  end
@@ -33,6 +33,7 @@ module Awestruct
33
33
  page = site.engine.load_page( sitemap )
34
34
  page.output_path = 'sitemap.xml'
35
35
  page.sitemap_entries = sitemap_pages
36
+ page.do_not_track_dependencies = true
36
37
 
37
38
  # Add the sitemap to our site
38
39
  site.pages << page