awestructx 0.4.0
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 +8 -0
- data/lib/awestruct/astruct.rb +22 -0
- data/lib/awestruct/astruct_mixin.rb +71 -0
- data/lib/awestruct/cli/auto.rb +20 -0
- data/lib/awestruct/cli/generate.rb +26 -0
- data/lib/awestruct/cli/invoker.rb +109 -0
- data/lib/awestruct/cli/options.rb +116 -0
- data/lib/awestruct/cli/server.rb +24 -0
- data/lib/awestruct/config.rb +30 -0
- data/lib/awestruct/context.rb +22 -0
- data/lib/awestruct/context_helper.rb +68 -0
- data/lib/awestruct/engine.rb +254 -0
- data/lib/awestruct/extensions/assets.rb +39 -0
- data/lib/awestruct/extensions/atomizer.rb +44 -0
- data/lib/awestruct/extensions/cachebuster.rb +12 -0
- data/lib/awestruct/extensions/coffeescripttransform.rb +42 -0
- data/lib/awestruct/extensions/data_dir.rb +31 -0
- data/lib/awestruct/extensions/disqus.rb +62 -0
- data/lib/awestruct/extensions/extend_string.rb +97 -0
- data/lib/awestruct/extensions/flattr.rb +42 -0
- data/lib/awestruct/extensions/google_analytics.rb +38 -0
- data/lib/awestruct/extensions/gsub.rb +20 -0
- data/lib/awestruct/extensions/indexifier.rb +17 -0
- data/lib/awestruct/extensions/intense_debate.rb +38 -0
- data/lib/awestruct/extensions/minify.rb +178 -0
- data/lib/awestruct/extensions/obfuscate.rb +32 -0
- data/lib/awestruct/extensions/paginator.rb +105 -0
- data/lib/awestruct/extensions/partial.rb +25 -0
- data/lib/awestruct/extensions/pipeline.rb +50 -0
- data/lib/awestruct/extensions/posts.rb +70 -0
- data/lib/awestruct/extensions/relative.rb +11 -0
- data/lib/awestruct/extensions/remotePartial.rb +17 -0
- data/lib/awestruct/extensions/sitemap.rb +85 -0
- data/lib/awestruct/extensions/sitemap.xml.haml +16 -0
- data/lib/awestruct/extensions/tag_cloud.html.haml +7 -0
- data/lib/awestruct/extensions/tag_cloud.rb +34 -0
- data/lib/awestruct/extensions/tagger.rb +107 -0
- data/lib/awestruct/extensions/template.atom.haml +39 -0
- data/lib/awestruct/handler_chain.rb +28 -0
- data/lib/awestruct/handler_chains.rb +65 -0
- data/lib/awestruct/handlers/base_handler.rb +92 -0
- data/lib/awestruct/handlers/base_sass_handler.rb +42 -0
- data/lib/awestruct/handlers/file_handler.rb +61 -0
- data/lib/awestruct/handlers/front_matter_handler.rb +80 -0
- data/lib/awestruct/handlers/haml_handler.rb +42 -0
- data/lib/awestruct/handlers/interpolation_handler.rb +28 -0
- data/lib/awestruct/handlers/layout_handler.rb +61 -0
- data/lib/awestruct/handlers/markdown_handler.rb +36 -0
- data/lib/awestruct/handlers/no_op_handler.rb +34 -0
- data/lib/awestruct/handlers/sass_handler.rb +14 -0
- data/lib/awestruct/handlers/scss_handler.rb +14 -0
- data/lib/awestruct/handlers/string_handler.rb +29 -0
- data/lib/awestruct/handlers/textile_handler.rb +43 -0
- data/lib/awestruct/handlers/yaml_handler.rb +25 -0
- data/lib/awestruct/layouts.rb +15 -0
- data/lib/awestruct/page.rb +128 -0
- data/lib/awestruct/page_loader.rb +72 -0
- data/lib/awestruct/pipeline.rb +49 -0
- data/lib/awestruct/site.rb +51 -0
- data/lib/awestruct/util/default_inflections.rb +45 -0
- data/lib/awestruct/util/inflector.rb +242 -0
- data/lib/awestruct/version.rb +4 -0
- data/lib/guard/awestruct.rb +38 -0
- 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( / /, ' ' )
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean_html(str)
|
11
|
+
str.gsub( / /, ' ' )
|
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,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
|