awestruct 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+