awestruct 0.0.1

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.
data/bin/awestruct ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__) + '/../lib'
4
+
5
+ require 'rubygems'
6
+ require 'optparse'
7
+ require 'awestruct/commands/init'
8
+ require 'awestruct/commands/generate'
9
+ require 'awestruct/commands/server'
10
+
11
+ def parse(args)
12
+ options = OpenStruct.new( {
13
+ :generate=>true,
14
+ :server=>false,
15
+ :port=>4242,
16
+ :bind_addr=>'0.0.0.0',
17
+ :auto=>false,
18
+ :force=>false,
19
+ :init=>false,
20
+ :framework=>'compass',
21
+ :scaffold=>true,
22
+ } )
23
+
24
+ opts = OptionParser.new do |opts|
25
+ opts.on( '-i', '--init', 'Initialize a new project in the current directory' ) do |init|
26
+ options.init = init
27
+ options.generate = false
28
+ end
29
+ opts.on( '-f', '--framework FRAMEWORK', 'Specify a framework during initialization' ) do |framework|
30
+ options.framework = framework
31
+ end
32
+ opts.on( '--[no-]scaffold', 'Create scaffolding during initialization (default: true)' ) do |s|
33
+ options.scaffold = s
34
+ end
35
+ opts.on( '--force', 'Force a regeneration' ) do |force|
36
+ options.force = force
37
+ end
38
+ opts.on( '-s', '--server', 'Serve generated site' ) do |s|
39
+ options.server = s
40
+ end
41
+ opts.on( '-a', '--auto', 'Auto-generate when changes are noticed' ) do |a|
42
+ options.auto = a
43
+ end
44
+ opts.on( '-p', '--port PORT', Integer, 'Server port (default: 4242)' ) do |port|
45
+ options.port = port
46
+ end
47
+ opts.on( '-b', '--bind ADDR', 'Server address (default: 0.0.0.0)' ) do |bind_addr|
48
+ options.bind_addr = bind_addr
49
+ end
50
+ opts.on( '-g', '--[no-]generate', 'Generated site' ) do |g|
51
+ options.generate = g
52
+ end
53
+
54
+ opts.separator ''
55
+ opts.separator "Common options:"
56
+
57
+ opts.on_tail("-h", "--help", "Show this message") do
58
+ puts opts
59
+ exit
60
+ end
61
+
62
+ end
63
+
64
+ opts.parse!(args)
65
+ options
66
+ end
67
+
68
+ options = parse(ARGV)
69
+
70
+ if ( options.init )
71
+ if ( options.generate || options.auto || options.server )
72
+ $stderr.puts "--init may not be used with --generate, --auto or --server"
73
+ end
74
+ cmd = Awestruct::Commands::Init.new( Dir.pwd, options.framework, options.scaffold )
75
+ cmd.run
76
+ exit
77
+ end
78
+
79
+ threads = []
80
+
81
+ if ( options.generate )
82
+ cmd = Awestruct::Commands::Generate.new( Dir.pwd, options.force )
83
+ cmd.run
84
+ end
85
+
86
+ if ( options.auto )
87
+ threads << Thread.new {
88
+ generate_cmd = Awestruct::Commands::Generate.new( Dir.pwd )
89
+ while ( true )
90
+ generate_cmd.run
91
+ sleep(1)
92
+ end
93
+ }
94
+ end
95
+
96
+ if ( options.server )
97
+ threads << Thread.new {
98
+ server_cmd = Awestruct::Commands::Server.new( File.join( Dir.pwd, '_site' ), options.bind_addr, options.port )
99
+ server_cmd.run
100
+ }
101
+ end
102
+
103
+ threads.each do |thr|
104
+ thr.join
105
+ end
106
+
107
+
108
+
data/lib/awestruct.rb ADDED
@@ -0,0 +1,2 @@
1
+
2
+ require 'awestruct/engine'
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: base
3
+ ---
4
+
5
+ %h1 You're awestruct.
@@ -0,0 +1,11 @@
1
+ %html
2
+ %head
3
+ %title
4
+ An awesome site
5
+ %link{ :rel=>'stylesheet', :type=>'text/css', :href=>'/stylesheets/screen.css', :media=>'screen, projection' }
6
+ %link{ :rel=>'stylesheet', :type=>'text/css', :href=>'/stylesheets/print.css', :media=>'print' }
7
+ /[if lt IE 8]
8
+ %link{ :rel=>'stylesheet', :type=>'text/css', :href=>'/stylesheets/ie.css', :media=>'screen, projection' }
9
+ %body.bp
10
+ #container
11
+ ~ content
@@ -0,0 +1,6 @@
1
+
2
+ Awestruct::Extensions::Pipeline.new do
3
+ # extension Awestruct::Extensions::Posts.new( '/news' )
4
+ # extension Awestruct::Extensions::Indexifier.new
5
+ end
6
+
@@ -0,0 +1,23 @@
1
+ require 'awestruct'
2
+
3
+ module Awestruct
4
+ module Commands
5
+ class Generate
6
+
7
+ def initialize(dir=Dir.pwd, force=false)
8
+ @dir = dir
9
+ @force = force
10
+ @engine = Awestruct::Engine.new( @dir )
11
+ end
12
+
13
+ def run()
14
+ begin
15
+ @engine.generate( @force )
16
+ rescue =>e
17
+ puts e
18
+ puts e.backtrace
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ require 'awestruct'
2
+ require 'awestruct/commands/manifest'
3
+
4
+
5
+ module Awestruct
6
+ module Commands
7
+ class Init
8
+
9
+ BASE_MANIFEST = Manifest.new {
10
+ mkdir( '_config' )
11
+ mkdir( '_layouts' )
12
+ mkdir( '_ext' )
13
+ copy_file( '_ext/pipeline.rb', File.join( File.dirname(__FILE__), 'base_pipeline.rb' ) )
14
+ mkdir( 'stylesheets' )
15
+ }
16
+
17
+ def initialize(dir=Dir.pwd,framework='compass',scaffold=true)
18
+ @dir = dir
19
+ @framework = framework
20
+ @scaffold = scaffold
21
+ end
22
+
23
+ def run()
24
+ manifest = Manifest.new( BASE_MANIFEST )
25
+ manifest.install_compass( @framework )
26
+ if ( @scaffold )
27
+ manifest.copy_file( '_layouts/base.html.haml', File.join( File.dirname(__FILE__), '/base_layout.html.haml' ) )
28
+ manifest.copy_file( 'index.html.haml', File.join( File.dirname(__FILE__), '/base_index.html.haml' ) )
29
+ end
30
+ manifest.perform( @dir )
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,172 @@
1
+ require 'compass/logger'
2
+ require 'compass/actions'
3
+ require 'compass/commands/base'
4
+ require 'compass/commands/create_project'
5
+ require 'compass/installers/stand_alone'
6
+
7
+ class Compass::Installers::StandAloneInstaller
8
+ def write_configuration_files(config_file=nil)
9
+ # skip it!
10
+ end
11
+
12
+ def compilation_required?
13
+ false
14
+ end
15
+ end
16
+
17
+ module Awestruct
18
+ module Commands
19
+ class Manifest
20
+
21
+ attr_reader :parent
22
+ attr_reader :steps
23
+
24
+ def initialize(parent=nil,&block)
25
+ @parent = parent
26
+ @steps = []
27
+ instance_eval &block if block
28
+ end
29
+
30
+ def mkdir(path)
31
+ steps << MkDir.new( path )
32
+ end
33
+
34
+ def copy_file(path, input_path)
35
+ steps << CopyFile.new( path, input_path )
36
+ end
37
+
38
+ def install_compass(framework)
39
+ steps << InstallCompass.new(framework)
40
+ end
41
+
42
+ def perform(dir)
43
+ parent.perform(dir) if parent
44
+ steps.each do |step|
45
+ begin
46
+ step.perform( dir )
47
+ rescue => e
48
+ puts e
49
+ puts e.backtrace
50
+ end
51
+ end
52
+ end
53
+
54
+ def unperform(dir)
55
+ steps.each do |step|
56
+ begin
57
+ step.unperform( dir )
58
+ rescue => e
59
+ puts e
60
+ puts e.backtrace
61
+ end
62
+ end
63
+ end
64
+
65
+ ##
66
+ ##
67
+ ##
68
+ ##
69
+
70
+ class MkDir
71
+ def initialize(path)
72
+ @path = path
73
+ end
74
+
75
+ def perform(dir)
76
+ p = File.join( dir, @path )
77
+ if ( File.exist?( p ) )
78
+ $stderr.puts "Exists: #{p}"
79
+ return
80
+ end
81
+ if ( ! File.directory?( File.dirname( p ) ) )
82
+ $stderr.puts "Does not exist: #{File.dirname(p)}"
83
+ return
84
+ end
85
+ $stderr.puts "Create directory: #{p}"
86
+ FileUtils.mkdir( p )
87
+ end
88
+
89
+ def unperform(dir)
90
+ p = File.join( dir, @path )
91
+ if ( ! File.exist?( p ) )
92
+ $stderr.puts "Does not exist: #{p}"
93
+ return
94
+ end
95
+ if ( ! File.directory?( p ) )
96
+ $stderr.puts "Not a directory: #{p}"
97
+ return
98
+ end
99
+ if ( Dir.entries( p ) != 2 )
100
+ $stderr.puts "Not empty: #{p}"
101
+ return
102
+ end
103
+ $stderr.puts "Remove: #{p}"
104
+ FileUtils.rmdir( p )
105
+ end
106
+ end
107
+
108
+ class CopyFile
109
+ def initialize(path, input_path)
110
+ @path = path
111
+ @input_path = input_path
112
+ end
113
+
114
+ def perform(dir )
115
+ p = File.join( dir, @path )
116
+ if ( File.exist?( p ) )
117
+ $stderr.puts "Exists: #{p}"
118
+ return
119
+ end
120
+ if ( ! File.directory?( File.dirname( p ) ) )
121
+ $stderr.puts "No directory: #{File.dirname( p )}"
122
+ return
123
+ end
124
+ $stderr.puts "Create file: #{p}"
125
+ File.open( p, 'w' ){|f| f.write( File.read( @input_path ) ) }
126
+ end
127
+
128
+ def unperform(dir)
129
+ # nothing
130
+ end
131
+
132
+ def notunperform(dir)
133
+ p = File.join( @dir, p )
134
+ if ( ! File.exist?( p ) )
135
+ $stderr.puts "Does not exist: #{p}"
136
+ return
137
+ end
138
+ $stderr.puts "Remove: #{p}"
139
+ FileUtils.rm( p )
140
+ end
141
+
142
+ end
143
+
144
+ class InstallCompass
145
+ def initialize(framework='compass')
146
+ @framework = framework
147
+ end
148
+
149
+ def perform(dir)
150
+ Compass.configuration.sass_dir = 'stylesheets'
151
+ Compass.configuration.css_dir = '_site/stylesheets'
152
+ Compass.configuration.images_dir = 'images'
153
+
154
+ cmd = Compass::Commands::CreateProject.new( dir, {
155
+ :framework=>@framework,
156
+ :project_type=>:stand_alone,
157
+ #:css_dir=>'_site/stylesheets',
158
+ #:sass_dir=>'stylesheets',
159
+ :images_dir=>'images',
160
+ :javascripts_dir=>'javascripts',
161
+ } )
162
+ cmd.perform
163
+ end
164
+
165
+ def unperform(dir)
166
+ # nothing
167
+ end
168
+ end
169
+
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,27 @@
1
+ require 'mongrel'
2
+
3
+ module Awestruct
4
+ module Commands
5
+
6
+ #Mongrel::DirHandler::MIME_TYPES['.atom'] = 'text/plain'
7
+ Mongrel::DirHandler::MIME_TYPES['.atom'] = 'application/atom+xml'
8
+
9
+ class Server
10
+ attr_reader :server
11
+
12
+ def initialize(path, bind_addr='0.0.0.0', port=4242)
13
+ @path = path
14
+ @bind_addr = bind_addr
15
+ @port = port
16
+ end
17
+
18
+ def run
19
+ @server = Mongrel::HttpServer.new( @bind_addr, @port )
20
+ handler = Mongrel::DirHandler.new( @path )
21
+ @server.register("/", handler )
22
+ $stderr.puts "Launching server on http://#{@bind_addr}:#{@port}/"
23
+ @server.run.join
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Awestruct
3
+
4
+ class Config
5
+
6
+ attr_accessor :layouts_dir
7
+ attr_accessor :config_dir
8
+ attr_accessor :extension_dir
9
+ attr_accessor :output_dir
10
+ attr_accessor :ignore
11
+
12
+ def initialize()
13
+ @layouts_dir = '_layouts'
14
+ @config_dir = '_config'
15
+ @output_dir = '_site'
16
+ @extension_dir = '_ext'
17
+ @ignore = [ ]
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,248 @@
1
+
2
+ require 'ostruct'
3
+ require 'find'
4
+ require 'compass'
5
+ require 'time'
6
+
7
+ require 'awestruct/config'
8
+ require 'awestruct/site'
9
+ require 'awestruct/haml_file'
10
+ require 'awestruct/maruku_file'
11
+ require 'awestruct/sass_file'
12
+ require 'awestruct/verbatim_file'
13
+
14
+ require 'awestruct/haml_helpers'
15
+
16
+ require 'awestruct/extensions/pipeline'
17
+ require 'awestruct/extensions/posts'
18
+ require 'awestruct/extensions/indexifier'
19
+
20
+ module Awestruct
21
+
22
+ IGNORE_NAMES = [
23
+ 'hekyll',
24
+ ]
25
+
26
+ class Engine
27
+
28
+ attr_reader :config
29
+ attr_reader :dir
30
+ attr_reader :site
31
+
32
+ def initialize(dir, config=::Awestruct::Config.new)
33
+ @dir = dir
34
+ @config = config
35
+ @site = Site.new( @dir )
36
+ @max_yaml_mtime = nil
37
+ end
38
+
39
+ def generate(force=false)
40
+ load_layouts
41
+ load_yamls
42
+ load_pages
43
+ load_extensions
44
+ set_urls
45
+ generate_files(force)
46
+ end
47
+
48
+ private
49
+
50
+ def set_urls
51
+ site.pages.each do |page|
52
+ page_path = page.output_path
53
+ if ( page_path =~ /^\// )
54
+ page.url = page_path
55
+ else
56
+ page.url = "/#{page_path}"
57
+ end
58
+ if ( page.url =~ /^(.*\/)index.html$/ )
59
+ page.url = $1
60
+ end
61
+ end
62
+ end
63
+
64
+ def generate_files(force)
65
+ site.pages.each do |page|
66
+ generate_page( page, force )
67
+ end
68
+ end
69
+
70
+ def generate_page(page, force)
71
+ return unless requires_generation?(page, force)
72
+
73
+ generated_path = File.join( dir, config.output_dir, page.output_path )
74
+ $stderr.puts "rendering #{page.source_path} -> #{page.output_path}"
75
+ rendered = render_page(page, true)
76
+ FileUtils.mkdir_p( File.dirname( generated_path ) )
77
+ File.open( generated_path, 'w' ) do |file|
78
+ file << rendered
79
+ end
80
+ end
81
+
82
+ def requires_generation?(page,force)
83
+ return true if force
84
+ generated_path = File.join( @dir, config.output_dir, page.output_path )
85
+ return true unless File.exist?( generated_path )
86
+ now = Time.now
87
+ generated_mtime = File.mtime( generated_path )
88
+ return true if ( ( @max_yaml_mtime || Time.at(0) ) > generated_mtime )
89
+ source_mtime = File.mtime( page.source_path )
90
+ return true if ( source_mtime > generated_mtime ) && ( source_mtime + 1 < now )
91
+ ext = page.output_extension
92
+ layout_name = page.layout
93
+ while ( ! layout_name.nil? )
94
+ layout = site.layouts[ layout_name + ext ]
95
+ if ( layout )
96
+ layout_mtime = File.mtime( layout.source_path )
97
+ return true if layout_mtime > generated_mtime
98
+ end
99
+ layout_name = layout.layout
100
+ end
101
+ false
102
+ end
103
+
104
+ def self.create_context(site, page, content='')
105
+ context = OpenStruct.new( :site=>site, :content=>content )
106
+ context.page = page
107
+ class << context
108
+ def interpolate_string(str)
109
+ result = instance_eval("%@#{(str||'').gsub('@', '\@')}@")
110
+ result
111
+ end
112
+ end
113
+ context
114
+ end
115
+
116
+ def render_page(page, with_layouts=true)
117
+ context = Engine.create_context( site, page )
118
+ rendered = page.render( context )
119
+ if ( with_layouts )
120
+ cur = page
121
+ while ( ! cur.nil? && ! cur.layout.nil? )
122
+ layout_name = cur.layout.to_s + page.output_extension
123
+ cur = site.layouts[ layout_name ]
124
+ context.content = rendered.to_s
125
+ rendered = cur.render( context )
126
+ end
127
+ end
128
+ rendered
129
+ end
130
+
131
+ def load_layouts
132
+ dir_pathname = Pathname.new( dir )
133
+ Dir[ File.join( dir, config.layouts_dir, '*.haml' ) ].each do |layout_path|
134
+ layout_pathname = Pathname.new( layout_path )
135
+ relative_path = layout_pathname.relative_path_from( dir_pathname ).to_s
136
+ name = File.basename( layout_path, '.haml' )
137
+ site.layouts[ name ] = HamlFile.new( site, layout_path, relative_path )
138
+ end
139
+ end
140
+
141
+ def load_yamls
142
+ @max_yaml_mtime = nil
143
+ Dir[ File.join( dir, config.config_dir, '*.yml' ) ].each do |yaml_path|
144
+ mtime = File.mtime( yaml_path )
145
+ if ( mtime > ( @max_yaml_mtime || Time.at(0) ) )
146
+ @max_yaml_mtime = mtime
147
+ end
148
+ data = YAML.load( File.read( yaml_path ) )
149
+ name = File.basename( yaml_path, '.yml' )
150
+ if ( name == 'site' )
151
+ data.each do |k,v|
152
+ site.send( "#{k}=", v )
153
+ end
154
+ else
155
+ site.send( "#{name}=", massage_yaml( data ) )
156
+ end
157
+ end
158
+ end
159
+
160
+ def load_pages()
161
+ dir_pathname = Pathname.new( dir )
162
+ site.pages.clear
163
+ Find.find( dir ) do |path|
164
+ basename = File.basename( path )
165
+ if ( basename == '.htaccess' )
166
+ #special case
167
+ elsif ( config.ignore.include?( basename ) || ( basename =~ /^[_.]/ ) )
168
+ Find.prune
169
+ next
170
+ end
171
+ unless ( site.has_page?( path ) )
172
+ file_pathname = Pathname.new( path )
173
+ relative_path = file_pathname.relative_path_from( dir_pathname ).to_s
174
+ page = nil
175
+ if ( path =~ /\.haml$/ )
176
+ page = HamlFile.new( site, path, File.join( '', relative_path ) )
177
+ elsif ( path =~ /\.md$/ )
178
+ page = MarukuFile.new( site, path, File.join( '', relative_path ) )
179
+ elsif ( path =~ /\.sass$/ )
180
+ page = SassFile.new( site, path, File.join( '', relative_path ) )
181
+ elsif ( File.file?( path ) )
182
+ page = VerbatimFile.new( site, path, File.join( '', relative_path ) )
183
+ end
184
+ if ( page )
185
+ site.pages << page
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ def massage_yaml(obj)
192
+ result = obj
193
+ case ( obj )
194
+ when Hash
195
+ result = {}
196
+ obj.each do |k,v|
197
+ result[k] = massage_yaml(v)
198
+ end
199
+ result = OpenStruct.new( result )
200
+ when Array
201
+ result = []
202
+ obj.each do |v|
203
+ result << massage_yaml(v)
204
+ end
205
+ end
206
+ result
207
+ end
208
+
209
+ def load_extensions
210
+ ext_dir = File.join( dir, config.extension_dir )
211
+ pipeline_file = File.join( ext_dir, 'pipeline.rb' )
212
+ if ( $LOAD_PATH.index( ext_dir ).nil? )
213
+ $LOAD_PATH << ext_dir
214
+ end
215
+ pipeline = eval File.read( pipeline_file )
216
+ pipeline.execute( site )
217
+ end
218
+
219
+ def old_load_extensions
220
+ ext_dir_pathname = Pathname.new( File.join( dir, config.extension_dir ) )
221
+ Dir[ File.join( dir, config.extension_dir, '*.rb' ) ].each do |path|
222
+ ext_pathname = Pathname.new( path )
223
+ relative_path = ext_pathname.relative_path_from( ext_dir_pathname ).to_s
224
+ dir_name = File.dirname( relative_path )
225
+ if ( dir_name == '.' )
226
+ simple_path = File.basename( relative_path, '.rb' )
227
+ else
228
+ simple_path = File.join( dir_name, File.basename( relative_path, '.rb' ) )
229
+ end
230
+ ext_classname = camelize(simple_path)
231
+ require File.join( dir, config.extension_dir, simple_path )
232
+ ext_class = eval( ext_classname )
233
+ ext = ext_class.new
234
+ ext.execute( site )
235
+ end
236
+ end
237
+
238
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
239
+ if first_letter_in_uppercase
240
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
241
+ else
242
+ lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
243
+ end
244
+ end
245
+
246
+ end
247
+
248
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Awestruct
3
+ module Extensions
4
+
5
+ class Indexifier
6
+ def execute(site)
7
+ site.pages.each do |page|
8
+ if ( page.inhibit_indexifier || ( page.output_path =~ /^(.*\/)?index.html$/ ) )
9
+ # skip it!
10
+ else
11
+ page.output_path = page.output_path.gsub( /.html$/, '/index.html' )
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ module Awestruct
2
+ module Extensions
3
+
4
+ class Pipeline
5
+
6
+ attr_reader :extensions
7
+
8
+ def initialize(&block)
9
+ @extensions = []
10
+ instance_eval &block if block
11
+ end
12
+
13
+ def extension(ext)
14
+ @extensions << ext
15
+ end
16
+
17
+ def execute(site)
18
+ extensions.each do |ext|
19
+ ext.execute( site )
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+
@@ -0,0 +1,46 @@
1
+
2
+ module Awestruct
3
+ module Extensions
4
+ class Posts
5
+
6
+ def initialize(path_prefix)
7
+ @path_prefix = path_prefix
8
+ end
9
+
10
+ def execute(site)
11
+ posts = []
12
+
13
+ site.pages.each do |page|
14
+ if ( page.relative_source_path =~ /^#{@path_prefix}\/(20[01][0-9])-([01][0-9])-([0123][0-9])-(.*)((\.html.haml)|(\.[^.]+))$/ )
15
+ year = $1
16
+ month = $2
17
+ day = $3
18
+ slug = $4
19
+ page.date = Time.utc( year.to_i, month.to_i, day.to_i )
20
+ page.slug = slug
21
+ context = OpenStruct.new({
22
+ :site=>site,
23
+ :page=>page,
24
+ })
25
+ #page.body = page.render( context )
26
+ page.output_path = "#{@path_prefix}/#{year}/#{month}/#{day}/#{slug}.html"
27
+ posts << page
28
+ end
29
+ end
30
+
31
+ posts = posts.sort_by{|each| [each.date, File.mtime( each.source_path ), each.slug ] }.reverse
32
+
33
+ last = nil
34
+ posts.each do |e|
35
+ if ( last != nil )
36
+ e.next = last
37
+ last.previous = e
38
+ end
39
+ last = e
40
+ end
41
+
42
+ site.posts = posts
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,48 @@
1
+ require 'awestruct/renderable_file'
2
+
3
+ module Awestruct
4
+ class FrontMatterFile < RenderableFile
5
+
6
+ attr_reader :raw_page_content
7
+
8
+ def initialize(site, source_path, relative_source_path)
9
+ super( site, source_path, relative_source_path )
10
+ @raw_page_content = ''
11
+ load_page
12
+ end
13
+
14
+ protected
15
+
16
+ def load_page
17
+ full_content = File.read( source_path )
18
+ yaml_content = ''
19
+
20
+ dash_lines = 0
21
+ mode = :yaml
22
+
23
+ full_content.each_line do |line|
24
+ if ( line.strip == '---' )
25
+ dash_lines = dash_lines +1
26
+ end
27
+ if ( mode == :yaml )
28
+ yaml_content << line
29
+ else
30
+ @raw_page_content << line
31
+ end
32
+ if ( dash_lines == 2 )
33
+ mode = :page
34
+ end
35
+ end
36
+
37
+ if ( dash_lines == 0 )
38
+ @raw_page_content = yaml_content
39
+ yaml_content = ''
40
+ end
41
+
42
+ front_matter = YAML.load( yaml_content ) || {}
43
+ front_matter.each do |k,v|
44
+ self.send( "#{k}=", v )
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+
2
+ require 'haml'
3
+ require 'awestruct/front_matter_file'
4
+ require 'awestruct/hamlable'
5
+
6
+ module Awestruct
7
+ class HamlFile < FrontMatterFile
8
+
9
+ include Hamlable
10
+
11
+ def initialize(site, source_path, relative_source_path)
12
+ super(site, source_path, relative_source_path)
13
+ end
14
+
15
+ def output_filename
16
+ File.basename( self.source_path, '.haml' )
17
+ end
18
+
19
+ def output_extension
20
+ File.extname( output_filename )
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ require 'hpricot'
2
+
3
+ module Haml::Helpers
4
+ def html_to_text(str)
5
+ str.gsub( /<[^>]+>/, '' )
6
+ end
7
+
8
+ def summarize(text, numwords=20)
9
+ text.split()[0, numwords].join(' ')
10
+ end
11
+
12
+ def fully_qualify_urls(base_url, text)
13
+ doc = Hpricot( text )
14
+
15
+ doc.search( "//a" ).each do |a|
16
+ a['href'] = fix_url( base_url, a['href'] )
17
+ end
18
+ doc.search( "//link" ).each do |link|
19
+ link['href'] = fix_url( base_url, link['href'] )
20
+ end
21
+ doc.search( "//img" ).each do |img|
22
+ img['src'] = fix_url( base_url, img['src'] )
23
+ end
24
+ return doc.to_s
25
+ end
26
+
27
+ def fix_url(base_url, url)
28
+ return url unless ( url =~ /^\// )
29
+ "#{base_url}#{url}"
30
+ end
31
+
32
+ end
@@ -0,0 +1,22 @@
1
+ module Awestruct
2
+
3
+ module Hamlable
4
+ def render(context)
5
+ rendered = ''
6
+ begin
7
+ haml_engine = Haml::Engine.new( raw_page_content )
8
+ rendered = haml_engine.render( context )
9
+ rescue => e
10
+ puts e
11
+ puts e.backtrace
12
+ end
13
+ rendered
14
+ end
15
+
16
+ def content
17
+ context = OpenStruct.new( :site=>site, :page=>self )
18
+ render( context )
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'awestruct/front_matter_file'
3
+ require 'awestruct/marukuable'
4
+
5
+ module Awestruct
6
+ class MarukuFile < FrontMatterFile
7
+
8
+ include Marukuable
9
+
10
+ def initialize(site, source_path, relative_source_path)
11
+ super(site, source_path, relative_source_path)
12
+ end
13
+
14
+ def output_filename
15
+ File.basename( self.source_path, '.md' ) + output_extension
16
+ end
17
+
18
+ def output_extension
19
+ '.html'
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ require 'maruku'
2
+
3
+ module Awestruct
4
+
5
+ module Marukuable
6
+ def render(context)
7
+ rendered = ''
8
+ begin
9
+ doc = Maruku.new( context.interpolate_string( raw_page_content ) )
10
+ rendered = doc.to_html
11
+ rescue => e
12
+ puts e
13
+ puts e.backtrace
14
+ end
15
+ rendered
16
+ end
17
+
18
+ def content
19
+ context = Awestruct::Engine.create_context( site, page )
20
+ render( context )
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,18 @@
1
+ require 'ostruct'
2
+
3
+ module Awestruct
4
+ class Renderable < OpenStruct
5
+
6
+ attr_reader :site
7
+
8
+ def initialize(site)
9
+ super( {} )
10
+ @site = site
11
+ end
12
+
13
+ def render(context)
14
+ puts ''
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+
2
+ require 'awestruct/renderable'
3
+
4
+ module Awestruct
5
+ class RenderableFile < Renderable
6
+
7
+ def initialize(site, source_path, relative_source_path)
8
+ super( site )
9
+ self.source_path = source_path
10
+ self.relative_source_path = relative_source_path
11
+ dir_name = File.dirname( relative_source_path )
12
+ if ( dir_name == '.' )
13
+ self.output_path = output_filename
14
+ else
15
+ self.output_path = File.join( dir_name, output_filename )
16
+ end
17
+ end
18
+
19
+ def raw_page_content
20
+ File.read( self.source_path )
21
+ end
22
+
23
+ def render(context)
24
+ raw_page_content
25
+ end
26
+
27
+ def output_extension
28
+ File.extname( self.source_path )
29
+ end
30
+
31
+ def output_filename
32
+ File.basename( self.source_path )
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+
2
+ require 'sass'
3
+ require 'awestruct/renderable_file'
4
+ require 'awestruct/sassable'
5
+
6
+ module Awestruct
7
+ class SassFile < RenderableFile
8
+
9
+ include Sassable
10
+
11
+ def initialize(site, source_path, relative_source_path)
12
+ super( site, source_path, relative_source_path )
13
+ end
14
+
15
+ def output_filename
16
+ File.basename( source_path, '.sass' ) + '.css'
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ require 'sass'
2
+
3
+ require 'compass'
4
+
5
+ module Awestruct
6
+ module Sassable
7
+
8
+ def render(context)
9
+ sass_opts = {
10
+ :load_paths => [
11
+ File.dirname( self.source_path ),
12
+ Compass::Frameworks['compass'].stylesheets_directory,
13
+ Compass::Frameworks['blueprint'].stylesheets_directory,
14
+ ],
15
+ }
16
+ sass_engine = Sass::Engine.new( raw_page_content, sass_opts )
17
+ sass_engine.render
18
+ end
19
+
20
+ def output_extension
21
+ 'css'
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,52 @@
1
+ require 'ostruct'
2
+
3
+ module Awestruct
4
+ class Site < OpenStruct
5
+
6
+ attr_reader :dir
7
+ attr_reader :output_dir
8
+
9
+ attr_reader :layouts
10
+ attr_accessor :pages
11
+
12
+ def initialize(dir)
13
+ super({ :base_url=>'http://localhost:4242' })
14
+
15
+ @dir = dir
16
+ @output_dir = File.join( dir, '_site' )
17
+
18
+ @pages = []
19
+ @layouts = {}
20
+ end
21
+
22
+ def has_page?(path)
23
+ ! pages.find{|e| e.path == path}.nil?
24
+ end
25
+
26
+ def output_path(path, ext=nil)
27
+ path = File.join( @output_dir, path[ @dir.size..-1] )
28
+ unless ( ext.nil? )
29
+ path = File.join( File.dirname( path ), File.basename( path, ext ) )
30
+ end
31
+ path
32
+ end
33
+
34
+ def url_path(path, ext=nil)
35
+ url_path = output_path( path, ext )[ @output_dir.size .. -1 ]
36
+ end
37
+
38
+ def apply_plugins
39
+ Dir[ File.join( @dir, '_plugins', '*.rb' ) ].each do |rb_path|
40
+ site_root = @dir
41
+ output_root = @output_dir
42
+ begin
43
+ eval File.read( rb_path )
44
+ rescue => e
45
+ puts e
46
+ puts e.backtrace
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,12 @@
1
+ require 'awestruct/renderable_file'
2
+
3
+ module Awestruct
4
+
5
+ class VerbatimFile < RenderableFile
6
+
7
+ def initialize(site, source_path, relative_source_path)
8
+ super( site, source_path, relative_source_path )
9
+ end
10
+
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awestruct
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Bob McWhirter
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-02-26 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: hpricot
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: haml
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :runtime
43
+ version_requirements: *id002
44
+ - !ruby/object:Gem::Dependency
45
+ name: maruku
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ type: :runtime
55
+ version_requirements: *id003
56
+ - !ruby/object:Gem::Dependency
57
+ name: compass
58
+ prerelease: false
59
+ requirement: &id004 !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ type: :runtime
67
+ version_requirements: *id004
68
+ - !ruby/object:Gem::Dependency
69
+ name: mongrel
70
+ prerelease: false
71
+ requirement: &id005 !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ type: :runtime
79
+ version_requirements: *id005
80
+ description:
81
+ email: bob@mcwhirter.org
82
+ executables:
83
+ - awestruct
84
+ extensions: []
85
+
86
+ extra_rdoc_files: []
87
+
88
+ files:
89
+ - lib/awestruct.rb
90
+ - lib/awestruct/config.rb
91
+ - lib/awestruct/engine.rb
92
+ - lib/awestruct/front_matter_file.rb
93
+ - lib/awestruct/haml_file.rb
94
+ - lib/awestruct/haml_helpers.rb
95
+ - lib/awestruct/hamlable.rb
96
+ - lib/awestruct/maruku_file.rb
97
+ - lib/awestruct/marukuable.rb
98
+ - lib/awestruct/renderable.rb
99
+ - lib/awestruct/renderable_file.rb
100
+ - lib/awestruct/sass_file.rb
101
+ - lib/awestruct/sassable.rb
102
+ - lib/awestruct/site.rb
103
+ - lib/awestruct/verbatim_file.rb
104
+ - lib/awestruct/commands/base_pipeline.rb
105
+ - lib/awestruct/commands/generate.rb
106
+ - lib/awestruct/commands/init.rb
107
+ - lib/awestruct/commands/manifest.rb
108
+ - lib/awestruct/commands/server.rb
109
+ - lib/awestruct/extensions/indexifier.rb
110
+ - lib/awestruct/extensions/pipeline.rb
111
+ - lib/awestruct/extensions/posts.rb
112
+ - lib/awestruct/commands/base_index.html.haml
113
+ - lib/awestruct/commands/base_layout.html.haml
114
+ has_rdoc: true
115
+ homepage:
116
+ licenses: []
117
+
118
+ post_install_message:
119
+ rdoc_options: []
120
+
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ requirements: []
138
+
139
+ rubyforge_project:
140
+ rubygems_version: 1.3.6
141
+ signing_key:
142
+ specification_version: 3
143
+ summary: Static site-baking utility
144
+ test_files: []
145
+