awestructx 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/bin/awestruct +8 -0
  2. data/lib/awestruct/astruct.rb +22 -0
  3. data/lib/awestruct/astruct_mixin.rb +71 -0
  4. data/lib/awestruct/cli/auto.rb +20 -0
  5. data/lib/awestruct/cli/generate.rb +26 -0
  6. data/lib/awestruct/cli/invoker.rb +109 -0
  7. data/lib/awestruct/cli/options.rb +116 -0
  8. data/lib/awestruct/cli/server.rb +24 -0
  9. data/lib/awestruct/config.rb +30 -0
  10. data/lib/awestruct/context.rb +22 -0
  11. data/lib/awestruct/context_helper.rb +68 -0
  12. data/lib/awestruct/engine.rb +254 -0
  13. data/lib/awestruct/extensions/assets.rb +39 -0
  14. data/lib/awestruct/extensions/atomizer.rb +44 -0
  15. data/lib/awestruct/extensions/cachebuster.rb +12 -0
  16. data/lib/awestruct/extensions/coffeescripttransform.rb +42 -0
  17. data/lib/awestruct/extensions/data_dir.rb +31 -0
  18. data/lib/awestruct/extensions/disqus.rb +62 -0
  19. data/lib/awestruct/extensions/extend_string.rb +97 -0
  20. data/lib/awestruct/extensions/flattr.rb +42 -0
  21. data/lib/awestruct/extensions/google_analytics.rb +38 -0
  22. data/lib/awestruct/extensions/gsub.rb +20 -0
  23. data/lib/awestruct/extensions/indexifier.rb +17 -0
  24. data/lib/awestruct/extensions/intense_debate.rb +38 -0
  25. data/lib/awestruct/extensions/minify.rb +178 -0
  26. data/lib/awestruct/extensions/obfuscate.rb +32 -0
  27. data/lib/awestruct/extensions/paginator.rb +105 -0
  28. data/lib/awestruct/extensions/partial.rb +25 -0
  29. data/lib/awestruct/extensions/pipeline.rb +50 -0
  30. data/lib/awestruct/extensions/posts.rb +70 -0
  31. data/lib/awestruct/extensions/relative.rb +11 -0
  32. data/lib/awestruct/extensions/remotePartial.rb +17 -0
  33. data/lib/awestruct/extensions/sitemap.rb +85 -0
  34. data/lib/awestruct/extensions/sitemap.xml.haml +16 -0
  35. data/lib/awestruct/extensions/tag_cloud.html.haml +7 -0
  36. data/lib/awestruct/extensions/tag_cloud.rb +34 -0
  37. data/lib/awestruct/extensions/tagger.rb +107 -0
  38. data/lib/awestruct/extensions/template.atom.haml +39 -0
  39. data/lib/awestruct/handler_chain.rb +28 -0
  40. data/lib/awestruct/handler_chains.rb +65 -0
  41. data/lib/awestruct/handlers/base_handler.rb +92 -0
  42. data/lib/awestruct/handlers/base_sass_handler.rb +42 -0
  43. data/lib/awestruct/handlers/file_handler.rb +61 -0
  44. data/lib/awestruct/handlers/front_matter_handler.rb +80 -0
  45. data/lib/awestruct/handlers/haml_handler.rb +42 -0
  46. data/lib/awestruct/handlers/interpolation_handler.rb +28 -0
  47. data/lib/awestruct/handlers/layout_handler.rb +61 -0
  48. data/lib/awestruct/handlers/markdown_handler.rb +36 -0
  49. data/lib/awestruct/handlers/no_op_handler.rb +34 -0
  50. data/lib/awestruct/handlers/sass_handler.rb +14 -0
  51. data/lib/awestruct/handlers/scss_handler.rb +14 -0
  52. data/lib/awestruct/handlers/string_handler.rb +29 -0
  53. data/lib/awestruct/handlers/textile_handler.rb +43 -0
  54. data/lib/awestruct/handlers/yaml_handler.rb +25 -0
  55. data/lib/awestruct/layouts.rb +15 -0
  56. data/lib/awestruct/page.rb +128 -0
  57. data/lib/awestruct/page_loader.rb +72 -0
  58. data/lib/awestruct/pipeline.rb +49 -0
  59. data/lib/awestruct/site.rb +51 -0
  60. data/lib/awestruct/util/default_inflections.rb +45 -0
  61. data/lib/awestruct/util/inflector.rb +242 -0
  62. data/lib/awestruct/version.rb +4 -0
  63. data/lib/guard/awestruct.rb +38 -0
  64. metadata +427 -0
@@ -0,0 +1,68 @@
1
+ require 'hpricot'
2
+
3
+ module Awestruct
4
+ module ContextHelper
5
+
6
+ def html_to_text(str)
7
+ str.gsub( /<[^>]+>/, '' ).gsub( /&nbsp;/, ' ' )
8
+ end
9
+
10
+ def clean_html(str)
11
+ str.gsub( /&nbsp;/, ' ' )
12
+ end
13
+
14
+ def without_images(str)
15
+ str.gsub(/<img[^>]+>/,'').gsub(/<a[^>]+>([^<]*)<\/a>/, '\1')
16
+ end
17
+
18
+ def close_tags(s)
19
+ stack = []
20
+ s.scan(/<\/?[^>]+>/).each do |tag|
21
+ if tag[1] != '/'
22
+ tag = tag[1..-1].scan(/\w+/).first
23
+ stack = [ tag ] + stack
24
+ else
25
+ tag = tag[2..-1].scan(/\w+/).first
26
+ if stack[0] == tag
27
+ stack = stack.drop(1)
28
+ else
29
+ raise "Malformed HTML expected #{tag[0]} but got #{tag} '#{s}'"
30
+ end
31
+ end
32
+ end
33
+ stack.inject(s) { |memo,tag| memo += "</#{tag}>" }
34
+ end
35
+
36
+ def summarize(text, numwords=20, ellipsis='...')
37
+ close_tags(text.split(/ /)[0, numwords].join(' ') + ellipsis)
38
+ end
39
+
40
+ def fully_qualify_urls(base_url, text)
41
+ doc = Hpricot( text )
42
+
43
+ doc.search( "//a" ).each do |a|
44
+ a['href'] = fix_url( base_url, a['href'] )
45
+ end
46
+ doc.search( "//link" ).each do |link|
47
+ link['href'] = fix_url( base_url, link['href'] )
48
+ end
49
+ doc.search( "//img" ).each do |img|
50
+ img['src'] = fix_url( base_url, img['src'] )
51
+ end
52
+ # Hpricot::Doc#to_s output encoding is not necessarily the same as the encoding of text
53
+ if RUBY_VERSION.start_with? '1.8'
54
+ doc.to_s
55
+ else
56
+ doc.to_s.tap do |d|
57
+ d.force_encoding(text.encoding) if d.encoding != text.encoding
58
+ end
59
+ end
60
+ end
61
+
62
+ def fix_url(base_url, url)
63
+ return url unless ( url =~ /^\// )
64
+ "#{base_url}#{url}"
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,254 @@
1
+ require 'awestruct/util/inflector'
2
+ require 'awestruct/util/default_inflections'
3
+
4
+ require 'awestruct/config'
5
+ require 'awestruct/site'
6
+ require 'awestruct/pipeline'
7
+ require 'awestruct/page'
8
+ require 'awestruct/page_loader'
9
+
10
+ require 'awestruct/extensions/pipeline'
11
+
12
+ require 'fileutils'
13
+
14
+ class OpenStruct
15
+ def inspect
16
+ "OpenStruct{...}"
17
+ end
18
+ end
19
+
20
+ module Awestruct
21
+
22
+ class Engine
23
+
24
+ attr_reader :site
25
+ attr_reader :pipeline
26
+
27
+ def self.instance
28
+ @instance
29
+ end
30
+
31
+ def self.instance=(engine)
32
+ @instance = engine
33
+ end
34
+
35
+ def initialize(config=Awestruct::Config.new)
36
+ Engine.instance = self
37
+ @site = Site.new( self, config)
38
+ @pipeline = Pipeline.new
39
+ @site_page_loader = PageLoader.new( @site )
40
+ @layout_page_loader = PageLoader.new( @site, :layouts )
41
+ adjust_load_path
42
+ end
43
+
44
+ def config
45
+ site.config
46
+ end
47
+
48
+ def run(profile, base_url, default_base_url, force=false)
49
+ load_site_yaml(profile)
50
+ set_base_url( base_url, default_base_url )
51
+ load_yamls
52
+ load_pipeline
53
+ load_pages
54
+ execute_pipeline
55
+ configure_compass
56
+ set_urls( site.pages )
57
+ generate_output
58
+ end
59
+
60
+ def set_base_url(base_url, default_base_url)
61
+ if ( base_url )
62
+ site.base_url = base_url
63
+ end
64
+
65
+ if ( site.base_url.nil? )
66
+ site.base_url = default_base_url
67
+ end
68
+
69
+ if ( site.base_url )
70
+ if ( site.base_url =~ /^(.*)\/$/ )
71
+ site.base_url = $1
72
+ end
73
+ end
74
+ end
75
+
76
+ def load_site_yaml(profile)
77
+ site_yaml = File.join( site.config.config_dir, 'site.yml' )
78
+ if ( File.exist?( site_yaml ) )
79
+ data = YAML.load( File.read( site_yaml ) )
80
+ site.interpolate = true
81
+ profile_data = {}
82
+ data.each do |k,v|
83
+ if ( ( k == 'profiles' ) && ( ! profile.nil? ) )
84
+ profile_data = ( v[profile] || {} )
85
+ else
86
+ site.send( "#{k}=", v )
87
+ end
88
+ end if data
89
+ site.profile = profile
90
+
91
+ profile_data.each do |k,v|
92
+ site.send( "#{k}=", v )
93
+ end
94
+ end
95
+ end
96
+
97
+ def load_yamls
98
+ Dir[ File.join( site.config.config_dir, '*.yml' ) ].each do |yaml_path|
99
+ load_yaml( yaml_path ) unless ( File.basename( yaml_path ) == 'site.yml' )
100
+ end
101
+ end
102
+
103
+ def load_yaml(yaml_path)
104
+ data = YAML.load( File.read( yaml_path ) )
105
+ name = File.basename( yaml_path, '.yml' )
106
+ site.send( "#{name}=", massage_yaml( data ) )
107
+ end
108
+
109
+ def massage_yaml(obj)
110
+ result = obj
111
+ case ( obj )
112
+ when Hash
113
+ result = {}
114
+ obj.each do |k,v|
115
+ result[k] = massage_yaml(v)
116
+ end
117
+ result = AStruct.new( result ).cascade_for_nils!
118
+ when Array
119
+ result = []
120
+ obj.each do |v|
121
+ result << massage_yaml(v)
122
+ end
123
+ end
124
+ result
125
+ end
126
+
127
+ def adjust_load_path
128
+ ext_dir = File.join( site.config.extension_dir )
129
+ if ( $LOAD_PATH.index( ext_dir ).nil? )
130
+ $LOAD_PATH << ext_dir
131
+ end
132
+ end
133
+
134
+ def set_urls(pages)
135
+ pages.each do |page|
136
+ #puts "relative_source_path #{page.relative_source_path}"
137
+ page_path = page.output_path
138
+ if ( page_path =~ /^\// )
139
+ page.url = page_path
140
+ else
141
+ page.url = "/#{page_path}"
142
+ end
143
+ if ( page.url =~ /^(.*\/)index.html$/ )
144
+ page.url = $1
145
+ end
146
+ end
147
+ end
148
+
149
+ def load_pipeline
150
+ ext_dir = File.join( site.config.extension_dir )
151
+ pipeline_file = File.join( ext_dir, 'pipeline.rb' )
152
+ if ( File.exists?( pipeline_file ) )
153
+ p = eval(File.read( pipeline_file ), nil, pipeline_file, 1)
154
+ p.extensions.each do |e|
155
+ pipeline.extension( e )
156
+ end
157
+ p.helpers.each do |h|
158
+ pipeline.helper( h )
159
+ end
160
+ p.transformers.each do |e|
161
+ pipeline.transformer( e )
162
+ end
163
+ end
164
+ end
165
+
166
+ def execute_pipeline
167
+ pipeline.execute( site )
168
+ end
169
+
170
+ def configure_compass
171
+ Compass.configuration.project_type = :standalone
172
+ Compass.configuration.project_path = site.config.dir
173
+ Compass.configuration.sass_dir = 'stylesheets'
174
+
175
+ site.images_dir = File.join( site.config.output_dir, 'images' )
176
+ site.stylesheets_dir = File.join( site.config.output_dir, 'stylesheets' )
177
+ site.javascripts_dir = File.join( site.config.output_dir, 'javascripts' )
178
+
179
+ Compass.configuration.css_dir = site.css_dir
180
+ Compass.configuration.javascripts_dir = 'javascripts'
181
+ Compass.configuration.images_dir = 'images'
182
+ end
183
+
184
+ def load_pages
185
+ @layout_page_loader.load_all( :post )
186
+ @site_page_loader.load_all( :inline )
187
+ end
188
+
189
+ def generate_output
190
+ @site.pages.each do |page|
191
+ generated_path = File.join( site.config.output_dir, page.output_path )
192
+ if ( page.stale_output?( generated_path ) )
193
+ generate_page( page, generated_path )
194
+ end
195
+ end
196
+ end
197
+
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
203
+ end
204
+ end
205
+
206
+ def generate_page_by_output_path(path)
207
+ 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)
215
+ end
216
+ end
217
+
218
+ ####
219
+ ##
220
+ ## compat with awestruct 0.2.x
221
+ ##
222
+ ####
223
+
224
+ def load_page(path, options={})
225
+ page = @site_page_loader.load_page( path )
226
+ if ( options[:relative_path] )
227
+ fixed_relative_path = ( options[:relative_path].nil? ? nil : File.join( '', options[:relative_path] ) )
228
+ page.relative_path = fixed_relative_path
229
+ end
230
+ page
231
+ end
232
+
233
+ def load_site_page(relative_path)
234
+ load_page( File.join( site.config.dir, relative_path ) )
235
+ end
236
+
237
+ def find_and_load_site_page(simple_path)
238
+ path_glob = File.join( site.config.input_dir, simple_path + '.*' )
239
+ candidates = Dir[ path_glob ]
240
+ return nil if candidates.empty?
241
+ throw Exception.new( "too many choices for #{simple_path}" ) if candidates.size != 1
242
+ dir_pathname = Pathname.new( site.config.dir )
243
+ path_name = Pathname.new( candidates[0] )
244
+ relative_path = path_name.relative_path_from( dir_pathname ).to_s
245
+ load_page( candidates[0] )
246
+ end
247
+
248
+ def create_context(page, content='')
249
+ page.create_context( content )
250
+ end
251
+
252
+ end
253
+
254
+ end
@@ -0,0 +1,39 @@
1
+ require 'awestruct/extensions/relative'
2
+ require 'pathname'
3
+
4
+ module Awestruct
5
+ module Extensions
6
+ module Assets
7
+
8
+ def asset(href)
9
+ if site.assets_url
10
+ File.join(site.assets_url, href)
11
+ else
12
+ relative(File.join("/#{site.assets_path||'assets'}", href))
13
+ end
14
+ end
15
+
16
+ class Transformer
17
+ # FIXME this is not DRY at all
18
+ def relative(page, href)
19
+ Pathname.new(href).relative_path_from(Pathname.new(File.dirname(page.output_path))).to_s
20
+ end
21
+ def asset(site, page, href)
22
+ if site.assets_url
23
+ File.join(site.assets_url, href)
24
+ else
25
+ relative(page, File.join("/#{site.assets_path||'assets'}", href))
26
+ end
27
+ end
28
+ def transform(site, page, input)
29
+ if page.output_path =~ /\.html/
30
+ input.gsub('asset://', asset(site, page, "#{File.basename(File.basename(page.source_path, ".md"))}") + "/")
31
+ else
32
+ input
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,44 @@
1
+ module Awestruct
2
+ module Extensions
3
+ class Atomizer
4
+
5
+ def initialize(entries_name, output_path, opts={})
6
+ @entries_name = entries_name
7
+ @output_path = output_path
8
+ @num_entries = opts[:num_entries] || 50
9
+ @content_url = opts[:content_url]
10
+ @feed_title = opts[:feed_title]
11
+ end
12
+
13
+ def execute(site)
14
+ entries = site.send( @entries_name ) || []
15
+ unless ( @num_entries == :all )
16
+ entries = entries[0, @num_entries]
17
+ end
18
+
19
+ atom_pages = []
20
+
21
+ entries.each do |entry|
22
+ feed_entry = site.engine.load_page(entry.source_path, :relative_path => entry.relative_source_path, :html_entities => false)
23
+
24
+ feed_entry.output_path = entry.output_path
25
+ feed_entry.date = feed_entry.timestamp.nil? ? entry.date : feed_entry.timestamp
26
+
27
+ atom_pages << feed_entry
28
+ end
29
+
30
+ site.engine.set_urls(atom_pages)
31
+
32
+ input_page = File.join( File.dirname(__FILE__), 'template.atom.haml' )
33
+ page = site.engine.load_page( input_page )
34
+ page.date = page.timestamp unless page.timestamp.nil?
35
+ page.output_path = @output_path
36
+ page.entries = atom_pages
37
+ page.title = @feed_title || site.title || site.base_url
38
+ page.content_url = @content_url || site.base_url
39
+ site.pages << page
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ module Awestruct
2
+ module Extensions
3
+ module Cachebuster
4
+ def timestamp
5
+ (Time.now.to_i / 1000).to_i
6
+ end
7
+ def cache(href)
8
+ "#{href}?#{site.cachebuster||timestamp}"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ require 'coffee-script'
2
+ require 'nokogiri'
3
+
4
+ ##
5
+ # Awestruct:Extensions:CoffeeScript is a transformer that compiles inline CoffeeScript in HTML files as JavaScript.
6
+
7
+ module Awestruct
8
+ module Extensions
9
+ class CoffeeScriptTransform
10
+
11
+ def transform(site, page, input)
12
+ ext = File.extname(page.output_path)[1..-1].to_sym
13
+ case ext
14
+ when :html
15
+ encoding = 'UTF-8'
16
+ encoding = site.encoding unless site.encoding.nil?
17
+
18
+ return compile(input, encoding)
19
+ end
20
+ return input
21
+ end
22
+
23
+ private
24
+
25
+ def compile(input, encoding)
26
+ html = Nokogiri::HTML(input, nil, encoding);
27
+ html.search('script').each do |script|
28
+ next unless 'text/coffeescript'.eql? script.attr('type')
29
+
30
+ if script.attr('src') =~ /\.coffee$/
31
+ script.set_attribute('src', File.basename( script.attr('src'), '.coffee' ) + '.js')
32
+ else
33
+ script.inner_html = CoffeeScript.compile script.inner_html
34
+ end
35
+ script.set_attribute('type', 'text/javascript')
36
+
37
+ end
38
+ return html.to_html
39
+ end
40
+ end
41
+ end
42
+ end