alula 0.2.3 → 0.4.0b
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +7 -0
- data/Guardfile +9 -0
- data/Rakefile +12 -1
- data/VERSION +1 -1
- data/alula.gemspec +20 -4
- data/lib/alula/attachment_processor.rb +77 -0
- data/lib/alula/cdn.rb +30 -0
- data/lib/alula/cdns/edgecast.rb +16 -0
- data/lib/alula/cdns/hosts.rb +14 -0
- data/lib/alula/cli.rb +90 -39
- data/lib/alula/compressors.rb +22 -10
- data/lib/alula/config.rb +141 -0
- data/lib/alula/content.rb +113 -0
- data/lib/alula/contents/attachment.rb +8 -0
- data/lib/alula/contents/item.rb +409 -0
- data/lib/alula/contents/metadata.rb +73 -0
- data/lib/alula/contents/page.rb +9 -0
- data/lib/alula/contents/post.rb +32 -0
- data/lib/alula/context.rb +72 -0
- data/lib/alula/core_ext.rb +5 -0
- data/lib/alula/core_ext/environment.rb +20 -0
- data/lib/alula/core_ext/filter.rb +20 -0
- data/lib/alula/core_ext/filters/smilies.rb +36 -0
- data/lib/alula/core_ext/manifest.rb +30 -0
- data/lib/alula/core_ext/tag.rb +100 -0
- data/lib/alula/core_ext/tags/attachment.rb +28 -0
- data/lib/alula/core_ext/tags/blockquote.rb +21 -0
- data/lib/alula/core_ext/tags/image.rb +48 -0
- data/lib/alula/core_ext/tags/locale.rb +17 -0
- data/lib/alula/core_ext/tags/video.rb +103 -0
- data/lib/alula/generator.rb +31 -0
- data/lib/alula/generators/feedbuilder.rb +44 -0
- data/lib/alula/generators/paginate.rb +88 -0
- data/lib/alula/generators/sitemap.rb +26 -0
- data/lib/alula/helpers.rb +2 -0
- data/lib/alula/helpers/addons.rb +12 -0
- data/lib/alula/helpers/assets.rb +56 -0
- data/lib/alula/helpers/url_helpers.rb +16 -0
- data/lib/alula/plugin.rb +32 -0
- data/lib/alula/processor.rb +86 -0
- data/lib/alula/processors/dummy.rb +24 -0
- data/lib/alula/processors/image.rb +52 -0
- data/lib/alula/processors/magick.rb +83 -0
- data/lib/alula/processors/video.rb +97 -0
- data/lib/alula/processors/zencoder.rb +199 -0
- data/lib/alula/progress.rb +95 -0
- data/lib/alula/progressbar.rb +66 -0
- data/lib/alula/site.rb +331 -262
- data/lib/alula/storage.rb +46 -0
- data/lib/alula/storages/file_item.rb +43 -0
- data/lib/alula/storages/filestorage.rb +96 -0
- data/lib/alula/storages/item.rb +12 -0
- data/lib/alula/support/commonlogger.rb +30 -0
- data/lib/alula/theme.rb +70 -13
- data/lib/alula/theme/layout.rb +56 -0
- data/lib/alula/theme/view.rb +43 -0
- data/lib/alula/version.rb +1 -1
- data/locales/en.yml +9 -0
- data/locales/fi.yml +10 -0
- data/locales/l10n/ar.yml +199 -0
- data/locales/l10n/az.yml +199 -0
- data/locales/l10n/bg.yml +199 -0
- data/locales/l10n/bn-IN.yml +182 -0
- data/locales/l10n/bs.yml +242 -0
- data/locales/l10n/ca.yml +199 -0
- data/locales/l10n/cs.yml +198 -0
- data/locales/l10n/csb.yml +210 -0
- data/locales/l10n/cy.yml +199 -0
- data/locales/l10n/da.yml +199 -0
- data/locales/l10n/de-AT.yml +203 -0
- data/locales/l10n/de-CH.yml +203 -0
- data/locales/l10n/de.yml +203 -0
- data/locales/l10n/dsb.yml +215 -0
- data/locales/l10n/el.yml +199 -0
- data/locales/l10n/en-AU.yml +205 -0
- data/locales/l10n/en-CA.yml +214 -0
- data/locales/l10n/en-GB.yml +205 -0
- data/locales/l10n/en-IN.yml +205 -0
- data/locales/l10n/en-US.yml +205 -0
- data/locales/l10n/en.yml +205 -0
- data/locales/l10n/eo.yml +201 -0
- data/locales/l10n/es-AR.yml +205 -0
- data/locales/l10n/es-CL.yml +199 -0
- data/locales/l10n/es-CO.yml +205 -0
- data/locales/l10n/es-MX.yml +205 -0
- data/locales/l10n/es-PE.yml +181 -0
- data/locales/l10n/es-VE.yml +205 -0
- data/locales/l10n/es.yml +199 -0
- data/locales/l10n/et.yml +199 -0
- data/locales/l10n/eu.yml +199 -0
- data/locales/l10n/fa.yml +199 -0
- data/locales/l10n/fi.yml +199 -0
- data/locales/l10n/fr-CA.yml +207 -0
- data/locales/l10n/fr-CH.yml +207 -0
- data/locales/l10n/fr.yml +222 -0
- data/locales/l10n/fur.yml +199 -0
- data/locales/l10n/gl-ES.yml +178 -0
- data/locales/l10n/gsw-CH.yml +199 -0
- data/locales/l10n/he.yml +201 -0
- data/locales/l10n/hi-IN.yml +199 -0
- data/locales/l10n/hi.yml +199 -0
- data/locales/l10n/hr.yml +237 -0
- data/locales/l10n/hsb.yml +214 -0
- data/locales/l10n/hu.yml +199 -0
- data/locales/l10n/id.yml +200 -0
- data/locales/l10n/is.yml +213 -0
- data/locales/l10n/it.yml +205 -0
- data/locales/l10n/ja.yml +197 -0
- data/locales/l10n/kn.yml +199 -0
- data/locales/l10n/ko.yml +197 -0
- data/locales/l10n/lo.yml +186 -0
- data/locales/l10n/lt.yml +182 -0
- data/locales/l10n/lv.yml +215 -0
- data/locales/l10n/mk.yml +170 -0
- data/locales/l10n/mn.yml +205 -0
- data/locales/l10n/nb.yml +207 -0
- data/locales/l10n/nl.yml +199 -0
- data/locales/l10n/nn.yml +160 -0
- data/locales/l10n/pl.yml +221 -0
- data/locales/l10n/pt-BR.yml +207 -0
- data/locales/l10n/pt-PT.yml +207 -0
- data/locales/l10n/quotes.yml +24 -0
- data/locales/l10n/rm.yml +182 -0
- data/locales/l10n/ro.yml +199 -0
- data/locales/l10n/ru.yml +257 -0
- data/locales/l10n/sk.yml +213 -0
- data/locales/l10n/sl.yml +210 -0
- data/locales/l10n/sr-Latn.yml +170 -0
- data/locales/l10n/sr.yml +170 -0
- data/locales/l10n/sv-SE.yml +199 -0
- data/locales/l10n/sw.yml +197 -0
- data/locales/l10n/th.yml +173 -0
- data/locales/l10n/tl.yml +229 -0
- data/locales/l10n/tr.yml +199 -0
- data/locales/l10n/uk.yml +257 -0
- data/locales/l10n/vi.yml +201 -0
- data/locales/l10n/wo.yml +205 -0
- data/locales/l10n/zh-CN.yml +199 -0
- data/locales/l10n/zh-TW.yml +199 -0
- data/template/Gemfile.erb +14 -4
- data/template/README +16 -0
- data/template/config.yml.erb +42 -38
- data/test/fixtures/config_001_simple.yml +2 -0
- data/test/fixtures/config_002_l10n.yml +5 -0
- data/test/fixtures/pages/invalid-page.markdown +1 -0
- data/test/fixtures/pages/multilingual-page.markdown +20 -0
- data/test/fixtures/pages/section/subpage.markdown +5 -0
- data/test/fixtures/pages/simple-page.markdown +7 -0
- data/test/fixtures/posts/2012-07-02-invalid-post.markdown +1 -0
- data/test/fixtures/posts/2012-07-02-simple.markdown +7 -0
- data/test/fixtures/posts/2012-07-03-full-metadata.markdown +8 -0
- data/test/fixtures/posts/2012-07-03-multilingual-full-metadata.markdown +20 -0
- data/test/fixtures/theme/test/layouts/default.html.erb +1 -0
- data/test/fixtures/theme/test/views/page.html.erb +1 -0
- data/test/fixtures/theme/test/views/post.html.erb +1 -0
- data/test/minitest_helper.rb +14 -0
- data/test/test_config.rb +33 -0
- data/test/test_content.rb +30 -0
- data/test/test_metadata.rb +83 -0
- data/test/test_page.rb +81 -0
- data/test/test_post.rb +123 -0
- data/test/test_storage.rb +23 -0
- data/test/test_storage_file.rb +32 -0
- data/test/test_theme.rb +45 -0
- data/vendor/assets/images/favicon.png +0 -0
- data/vendor/assets/images/grey.gif +0 -0
- data/vendor/assets/javascripts/jquery.alula.js.coffee +16 -0
- data/vendor/{javascripts → assets/javascripts}/jquery.js +0 -0
- data/vendor/assets/javascripts/jquery.lazyload.js +210 -0
- data/vendor/assets/javascripts/lazyload.js.coffee +15 -0
- data/vendor/layouts/feed.xml.builder +19 -0
- data/vendor/layouts/sitemap.xml.builder +10 -0
- data/vendor/views/feed_post.html.haml +1 -0
- metadata +529 -50
- data/lib/alula.rb +0 -5
- data/lib/alula/assethelper.rb +0 -75
- data/lib/alula/plugins.rb +0 -23
- data/lib/alula/plugins/assets.rb +0 -82
- data/lib/alula/plugins/pagination.rb +0 -121
- data/lib/alula/rake_tasks.rb +0 -42
- data/lib/alula/tasks.rb +0 -2
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'alula/progressbar'
|
2
|
+
|
3
|
+
module Alula
|
4
|
+
class Progress
|
5
|
+
def initialize(options)
|
6
|
+
@pbars = {}
|
7
|
+
@interval = 1.0
|
8
|
+
@options = options
|
9
|
+
@display = false
|
10
|
+
|
11
|
+
@@lock = Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def create(identifier, opts)
|
15
|
+
if @pbars[identifier]
|
16
|
+
@pbars[identifier].finish
|
17
|
+
end
|
18
|
+
|
19
|
+
@@lock.synchronize do
|
20
|
+
@pbars[identifier] = ProgressBar.new(opts[:title], opts[:total] == 0 ? 0.1 : opts[:total])
|
21
|
+
if @options[:debug]
|
22
|
+
@pbars[identifier].settings.force_mode = :notty
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def step(identifier)
|
28
|
+
if @pbars[identifier]
|
29
|
+
@pbars[identifier].step
|
30
|
+
_display
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def set(identifier, value)
|
35
|
+
if @pbars[identifier]
|
36
|
+
@pbars[identifier].set(value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def title(identifier, title)
|
41
|
+
if @pbars[identifier]
|
42
|
+
@pbars[identifier].message = title
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_file_transfer(identifier)
|
47
|
+
if @pbars[identifier]
|
48
|
+
@pbars[identifier].file_transfer_mode
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def finish(identifier)
|
53
|
+
if @pbars[identifier]
|
54
|
+
@pbars[identifier].finish
|
55
|
+
_display
|
56
|
+
@@lock.synchronize do
|
57
|
+
@pbars.delete(identifier)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def display
|
63
|
+
@display = true
|
64
|
+
_display(true)
|
65
|
+
unless @options[:debug]
|
66
|
+
@update_thread = Thread.new {
|
67
|
+
loop {
|
68
|
+
sleep(@interval)
|
69
|
+
_display
|
70
|
+
}
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def hide
|
76
|
+
@display = false
|
77
|
+
if @update_thread
|
78
|
+
Thread.kill(@update_thread)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def _display(first = false)
|
84
|
+
return unless @display
|
85
|
+
|
86
|
+
@@lock.synchronize do
|
87
|
+
output = @pbars.collect {|identifier, pbar| pbar.render }
|
88
|
+
unless @options[:debug] or first
|
89
|
+
print "\e[#{output.count}F"
|
90
|
+
end
|
91
|
+
puts output.join("\n")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'powerbar'
|
2
|
+
|
3
|
+
module Alula
|
4
|
+
class ProgressBar < PowerBar
|
5
|
+
attr_accessor :showing
|
6
|
+
attr_accessor :message
|
7
|
+
|
8
|
+
def initialize(message, total, opts = {})
|
9
|
+
super(opts)
|
10
|
+
|
11
|
+
@message = "%20s" % message
|
12
|
+
@done = 0
|
13
|
+
@total = total
|
14
|
+
|
15
|
+
@showing = true
|
16
|
+
|
17
|
+
self.settings.tty.finite.template.main = '${<msg>}: ${<percent>% } ${[<bar>] }${ ETA: <eta>}'
|
18
|
+
self.settings.tty.finite.template.barchar = 'o'
|
19
|
+
self.settings.tty.finite.template.padchar = ' '
|
20
|
+
end
|
21
|
+
|
22
|
+
def file_transfer_mode
|
23
|
+
self.settings.tty.finite.template.main = '${<msg>}: ${<percent>% } ${[<bar>] }${<rate>/s }${<done>}${ ETA: <eta>}'
|
24
|
+
end
|
25
|
+
|
26
|
+
def render(opts = {})
|
27
|
+
super({msg: @message, done: @done, total: @total}.merge(opts))
|
28
|
+
end
|
29
|
+
|
30
|
+
def step
|
31
|
+
@done += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def set(value)
|
35
|
+
@done = value
|
36
|
+
end
|
37
|
+
|
38
|
+
def vanish
|
39
|
+
self.wipe
|
40
|
+
end
|
41
|
+
|
42
|
+
def finish(fill = true)
|
43
|
+
# self.close(true)
|
44
|
+
render(
|
45
|
+
{
|
46
|
+
:done => fill && !state.total.is_a?(Symbol) ? state.total : state.done,
|
47
|
+
:tty => {
|
48
|
+
:finite => { :show_eta => false },
|
49
|
+
:infinite => { :show_eta => false },
|
50
|
+
},
|
51
|
+
:notty => {
|
52
|
+
:finite => { :show_eta => false },
|
53
|
+
:infinite => { :show_eta => false },
|
54
|
+
},
|
55
|
+
})
|
56
|
+
# scope.output.call(scope.template.close) unless scope.template.close.nil?
|
57
|
+
state.closed = true
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
# Monkey-patch to force percentage always being three characters long
|
62
|
+
def h_percent
|
63
|
+
sprintf "%3d", percent
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/alula/site.rb
CHANGED
@@ -1,336 +1,405 @@
|
|
1
|
-
require '
|
2
|
-
require 'jekyll'
|
3
|
-
require 'sprockets'
|
4
|
-
require 'active_support/inflector/methods'
|
5
|
-
require 'progressbar'
|
6
|
-
require 'stringex'
|
7
|
-
|
8
|
-
require 'alula/theme'
|
9
|
-
require 'alula/plugins'
|
10
|
-
require 'alula/assethelper'
|
1
|
+
require 'alula/core_ext'
|
11
2
|
|
12
|
-
|
3
|
+
require 'alula/config'
|
4
|
+
require 'alula/plugin'
|
5
|
+
require 'alula/storage'
|
6
|
+
require 'alula/content'
|
7
|
+
require 'alula/context'
|
8
|
+
require 'alula/generator'
|
9
|
+
require 'alula/attachment_processor'
|
13
10
|
require 'alula/compressors'
|
11
|
+
require 'alula/cdn'
|
12
|
+
require 'alula/helpers'
|
13
|
+
require 'alula/progress'
|
14
|
+
|
15
|
+
require 'thor'
|
16
|
+
require 'sprockets'
|
17
|
+
require 'i18n'
|
18
|
+
require 'parallel'
|
19
|
+
require 'hashie/mash'
|
14
20
|
|
15
|
-
#
|
16
|
-
|
17
|
-
require '
|
18
|
-
require 'alula/plugins/pagination'
|
21
|
+
# Silence Tilt
|
22
|
+
require 'sass'
|
23
|
+
require 'coffee-script'
|
19
24
|
|
20
25
|
module Alula
|
21
26
|
class Site
|
27
|
+
def self.instance; @@instance; end
|
28
|
+
|
29
|
+
# Global configuration
|
30
|
+
attr_reader :config
|
31
|
+
|
32
|
+
# Storage
|
33
|
+
attr_reader :storage
|
34
|
+
|
35
|
+
# Context for rendering
|
36
|
+
attr_reader :context
|
37
|
+
|
38
|
+
# Progress displayer
|
39
|
+
attr_reader :progress
|
40
|
+
|
41
|
+
# CDN Resolver for Site
|
42
|
+
attr_reader :cdn
|
43
|
+
|
44
|
+
# Site Plugins
|
45
|
+
attr_reader :plugins
|
46
|
+
|
47
|
+
# Site filters
|
48
|
+
attr_reader :filters
|
49
|
+
|
50
|
+
# Compressors
|
51
|
+
attr_reader :compressors
|
52
|
+
|
53
|
+
# Site metadata information
|
54
|
+
attr_reader :metadata
|
22
55
|
|
23
|
-
|
56
|
+
# Site attachment mapping
|
57
|
+
attr_reader :attachments
|
24
58
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
59
|
+
# Theme
|
60
|
+
attr_reader :theme
|
61
|
+
|
62
|
+
# User generated content
|
63
|
+
attr_reader :content
|
64
|
+
|
65
|
+
# System generated content, pages, pagination, etc.
|
66
|
+
attr_reader :generated
|
67
|
+
|
68
|
+
def initialize(options)
|
69
|
+
@@instance = self
|
70
|
+
|
71
|
+
# Read local config
|
72
|
+
@config = Config.new(options)
|
73
|
+
|
74
|
+
@storage = Storage.load(site: self)
|
75
|
+
|
76
|
+
@metadata = Content::Metadata.new({
|
77
|
+
base_locale: @config.locale,
|
78
|
+
environment: @config.environment,
|
79
|
+
|
80
|
+
title: @config.title,
|
81
|
+
author: @config.author,
|
82
|
+
tagline: @config.tagline,
|
83
|
+
url: @config.url,
|
84
|
+
|
85
|
+
theme: @config.theme,
|
86
|
+
|
87
|
+
# Use this to store information of GIT site or note
|
88
|
+
git: ::File.directory?(".git"),
|
44
89
|
})
|
45
90
|
|
46
|
-
|
91
|
+
# Progress displayer
|
92
|
+
@progress = Progress.new(debug: options["debug"])
|
47
93
|
|
48
|
-
|
49
|
-
|
50
|
-
|
94
|
+
# Compressors
|
95
|
+
compressors = if @config.assets.compress
|
96
|
+
{
|
97
|
+
html: Alula::Compressors::HTMLCompressor.new,
|
98
|
+
css: Alula::Compressors::CSSCompressor.new,
|
99
|
+
js: Alula::Compressors::JSCompressor.new,
|
100
|
+
}
|
101
|
+
else
|
102
|
+
{
|
103
|
+
html: Alula::Compressors::DummyCompressor.new,
|
104
|
+
css: Alula::Compressors::DummyCompressor.new,
|
105
|
+
js: Alula::Compressors::DummyCompressor.new,
|
106
|
+
}
|
51
107
|
end
|
108
|
+
@compressors = Hashie::Mash.new(compressors)
|
52
109
|
|
53
|
-
|
54
|
-
@sprockets = Sprockets::Environment.new
|
55
|
-
# Set our compressor
|
56
|
-
if @config['asset_compress']
|
57
|
-
@sprockets.css_compressor = Alula::Compressors::CSSCompressor.new
|
58
|
-
@sprockets.js_compressor = Alula::Compressors::JSCompressor.new
|
59
|
-
|
60
|
-
[Jekyll::Post, Jekyll::Page].each do |klass|
|
61
|
-
klass.send(:include, Alula::Compressors::HTMLCompressor)
|
62
|
-
klass.send(:alias_method, :output_without_compression, :output)
|
63
|
-
klass.send(:alias_method, :output, :output_with_compression)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Add theme to asset paths
|
68
|
-
@sprockets.append_path File.join(@themepath, @config['theme'], "stylesheets")
|
69
|
-
@sprockets.append_path File.join(@themepath, @config['theme'], "javascripts")
|
70
|
-
|
71
|
-
# Generated assets
|
72
|
-
@sprockets.append_path File.join("_tmp", "assets")
|
110
|
+
@attachments = AttachmentProcessor.new(site: self)
|
73
111
|
|
74
|
-
#
|
75
|
-
@
|
112
|
+
# Set up CDN resolver
|
113
|
+
@cdn = CDN.load(site: self)
|
76
114
|
|
77
|
-
|
78
|
-
|
79
|
-
@
|
80
|
-
|
115
|
+
@plugins = {}
|
116
|
+
|
117
|
+
@filters = {}
|
118
|
+
|
119
|
+
# Set up I18n
|
120
|
+
l10n_path = File.join(File.dirname(__FILE__), "..", "..", "locales", "l10n", "*.yml")
|
121
|
+
locale_path = File.join(File.dirname(__FILE__), "..", "..", "locales", "*.yml")
|
122
|
+
custom_locale_path = File.join(@storage.path(:custom, "locales"), "*.yml")
|
123
|
+
I18n.load_path += Dir[l10n_path]
|
124
|
+
I18n.load_path += Dir[locale_path]
|
125
|
+
I18n.load_path += Dir[custom_locale_path]
|
126
|
+
I18n.default_locale = @config.locale
|
127
|
+
|
128
|
+
# Set up default head addons
|
129
|
+
Alula::Plugin.addon(:head, "<meta name=\"generator\" content=\"Alula #{Alula::VERSION}\">")
|
130
|
+
Alula::Plugin.addon(:head, ->(context){"<link rel=\"icon\" type=\"image/png\" href=\"#{context.asset_url('favicon.png')}\">"})
|
81
131
|
|
82
|
-
# Initialize blog plugins
|
83
|
-
if @config["plugins"] != nil
|
84
|
-
@config["plugins"].each do |plugin, opts|
|
85
|
-
require "alula/plugins/#{plugin}"
|
86
|
-
|
87
|
-
plugin_class = Alula::Plugins.const_get(ActiveSupport::Inflector.camelize(plugin, true))
|
88
|
-
path = plugin_class.install(opts)
|
89
|
-
@sprockets.append_path File.join(path, "stylesheets")
|
90
|
-
@sprockets.append_path File.join(path, "javascripts")
|
91
|
-
end
|
92
|
-
end
|
93
132
|
end
|
94
133
|
|
134
|
+
# Compiles a site to static website
|
95
135
|
def generate
|
96
|
-
|
136
|
+
# Load our plugins and filters
|
137
|
+
load_plugins
|
138
|
+
load_filters
|
139
|
+
|
140
|
+
# Prepare public folder
|
141
|
+
prepare(true)
|
97
142
|
|
98
|
-
|
99
|
-
prepare
|
143
|
+
load_content
|
100
144
|
|
101
|
-
|
102
|
-
assetgen
|
145
|
+
process_attachments
|
103
146
|
|
104
|
-
|
105
|
-
compile
|
147
|
+
compile_assets
|
106
148
|
|
107
|
-
|
108
|
-
process
|
149
|
+
render
|
109
150
|
|
110
|
-
# Cleanup
|
111
151
|
cleanup
|
152
|
+
# Store cached version of configuration
|
153
|
+
cached_config = File.join(storage.path(:cache), "config.yml")
|
154
|
+
@config.write_cache(cached_config)
|
112
155
|
end
|
113
156
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
mime_types.store 'js', 'application/javascript'
|
124
|
-
|
125
|
-
s = WEBrick::HTTPServer.new(
|
126
|
-
:Port => 3000,
|
127
|
-
:MimeTypes => mime_types
|
128
|
-
)
|
129
|
-
s.mount('/', WEBrick::HTTPServlet::FileHandler, "public")
|
130
|
-
t = Thread.new {
|
131
|
-
s.start
|
132
|
-
}
|
133
|
-
|
134
|
-
trap("INT") { s.shutdown }
|
135
|
-
t.join()
|
157
|
+
# Proxy to metadata
|
158
|
+
def method_missing(meth, *args, &blk)
|
159
|
+
# Proxy to metadata
|
160
|
+
if !meth[/=$/] and self.metadata.respond_to?(meth)
|
161
|
+
args.unshift(self.context.locale || self.config.locale) if args.empty?
|
162
|
+
self.metadata.send(meth, *args)
|
163
|
+
else
|
164
|
+
super
|
165
|
+
end
|
136
166
|
end
|
137
167
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
date = Time.parse(date)
|
144
|
-
asset_path = File.join(%w{%Y %m %d}.collect{|f| date.strftime(f) })
|
145
|
-
|
146
|
-
helper = Alula::AssetHelper.new(asset_path, @config)
|
147
|
-
|
148
|
-
post_io = File.open(post, "a")
|
149
|
-
assets.each do |asset|
|
150
|
-
type, generated = helper.process(asset, :type => :attachment)
|
151
|
-
tn_type, tn_generated = helper.process(asset, :type => :thumbnail)
|
152
|
-
if generated and tn_generated
|
153
|
-
# Asset processed
|
154
|
-
puts "(#{asset}) done."
|
155
|
-
if handler = Alula::Plugins.attachment_handler(type)
|
156
|
-
post_io.puts handler.call(generated[0])
|
157
|
-
else
|
158
|
-
post_io.puts "{% image _images/#{generated[0]} %}"
|
159
|
-
end
|
160
|
-
else
|
161
|
-
puts "(#{asset}) cannot process."
|
168
|
+
private
|
169
|
+
def load_plugins
|
170
|
+
config.plugins.each do |name, options|
|
171
|
+
if plugin = Alula::Plugin.load(name, options)
|
172
|
+
@plugins[name] = plugin
|
162
173
|
end
|
163
174
|
end
|
164
175
|
end
|
165
176
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
|
177
|
+
def load_filters
|
178
|
+
config.content.filters.each do |name, options|
|
179
|
+
if filter = Alula::Filter.load(name, options)
|
180
|
+
@filters[name] = filter
|
181
|
+
end
|
182
|
+
end
|
170
183
|
end
|
171
184
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
185
|
+
def prepare(preserve = false)
|
186
|
+
say "==> Preparing environment" + (preserve ? " (preserving existing files)" : "")
|
187
|
+
|
188
|
+
# Delegate preparations to storage module
|
189
|
+
self.storage.prepare(preserve)
|
190
|
+
|
191
|
+
# Load theme
|
192
|
+
@context = Alula::Context.new(site: self, storage: self.storage)
|
193
|
+
@context.send(:extend, Helpers)
|
194
|
+
|
195
|
+
@theme = Alula::Theme.load(site: self)
|
196
|
+
|
197
|
+
# Create our asset environment
|
198
|
+
@environment = Environment.new
|
199
|
+
# Add compressor support
|
200
|
+
# if config.environment == "production"
|
201
|
+
@environment.css_compressor = @compressors.css
|
202
|
+
@environment.js_compressor = @compressors.js
|
203
|
+
# end
|
204
|
+
@environment.context_class.class_eval do
|
205
|
+
# include Helpers
|
206
|
+
def context; Alula::Site.instance.context; end
|
207
|
+
def method_missing(meth, *args, &blk)
|
208
|
+
return context.send(meth, *args, &blk) if context.respond_to?(meth)
|
209
|
+
super
|
184
210
|
end
|
185
211
|
end
|
212
|
+
@context.environment = @environment
|
213
|
+
@context.attachments = self.attachments
|
214
|
+
|
215
|
+
# Add generated attachements
|
216
|
+
@environment.append_path @storage.path(:cache, "attachments")
|
217
|
+
|
218
|
+
# Add generated assets
|
219
|
+
@environment.append_path @storage.path(:cache, "assets")
|
220
|
+
|
221
|
+
# Theme, plugins, vendor and customisation
|
222
|
+
[
|
223
|
+
self.theme.path,
|
224
|
+
*plugins.collect{|name, plugin| plugin.asset_path},
|
225
|
+
::File.join(File.dirname(__FILE__), "..", "..", "vendor"),
|
226
|
+
].each do |path|
|
227
|
+
%w{javascripts stylesheets images}.each {|p|
|
228
|
+
@environment.append_path ::File.join(path, "assets", p)
|
229
|
+
}
|
230
|
+
end
|
231
|
+
|
232
|
+
# Customisation
|
233
|
+
%w{javascripts stylesheets images}.each do |path|
|
234
|
+
@environment.prepend_path @storage.path(:custom, path)
|
235
|
+
end
|
186
236
|
end
|
187
237
|
|
188
|
-
def
|
189
|
-
|
190
|
-
# Clean our temporary folder
|
191
|
-
FileUtils.rm_rf "_tmp"
|
192
|
-
FileUtils.mkdir "_tmp"
|
193
|
-
FileUtils.rm_rf "public"
|
194
|
-
FileUtils.mkdir "public"
|
195
|
-
|
196
|
-
# Copy Jekyll files
|
197
|
-
# Install our theme
|
198
|
-
FileUtils.mkdir_p File.join("_tmp", "_layouts")
|
199
|
-
FileUtils.mkdir_p File.join("_tmp", "_includes")
|
200
|
-
|
201
|
-
FileUtils.cp_r Dir[File.join(@themepath, @config['theme'], "layouts", "*")], File.join("_tmp", "_layouts")
|
202
|
-
FileUtils.cp_r Dir[File.join(@themepath, @config['theme'], "includes", "*")], File.join("_tmp", "_includes")
|
203
|
-
|
204
|
-
FileUtils.cp_r Dir[File.join(@themepath, @config['theme'], "site", "*")], "_tmp"
|
205
|
-
|
206
|
-
# Copy posts
|
207
|
-
FileUtils.mkdir_p File.join("_tmp", "_posts")
|
208
|
-
FileUtils.cp_r Dir[File.join("posts", "*")], File.join("_tmp", "_posts")
|
238
|
+
def load_content
|
239
|
+
say "==> Loading site content"
|
209
240
|
|
210
|
-
#
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
241
|
+
# Read site content
|
242
|
+
@content = Content.new(site: self)
|
243
|
+
@content.load
|
244
|
+
|
245
|
+
# Do we have index page defined
|
246
|
+
if self.config.index
|
247
|
+
index_page = @content.by_slug(self.config.index)
|
248
|
+
if index_page
|
249
|
+
index_page.metadata.slug = "index"
|
250
|
+
index_page.metadata.template = "/:locale/:slug"
|
251
|
+
index_page.metadata.title = Hash[index_page.metadata.languages.collect{|lang| [lang, metadata.title(lang)]}]
|
252
|
+
end
|
217
253
|
end
|
218
|
-
|
219
|
-
FileUtils.mkdir_p File.join("_tmp", "assets")
|
220
254
|
end
|
221
255
|
|
222
|
-
def
|
223
|
-
puts "==>
|
224
|
-
|
225
|
-
# width, height = @config["images"]["thumbnails"].split("x").collect {|i| i.to_i }
|
256
|
+
def process_attachments
|
257
|
+
puts "==> Processing attachments"
|
226
258
|
|
227
|
-
|
228
|
-
|
229
|
-
images_path = File.join("attachments", "_generated", "images")
|
230
|
-
thumbnails_path = File.join("attachments", "_generated", "thumbnails")
|
259
|
+
progress.create :attachments, title: "Attachments", total: self.content.attachments.count
|
260
|
+
progress.display
|
231
261
|
|
232
|
-
|
233
|
-
.select {|f| File.file?(f) }
|
234
|
-
.collect {|f| File.join(f.split("/")[2..-1])}
|
235
|
-
pb = ProgressBar.new "Assets", attachments.count
|
262
|
+
@@lock = Mutex.new
|
236
263
|
|
237
|
-
attachments.
|
238
|
-
|
239
|
-
|
240
|
-
type, generated = helper.process(File.join("attachments", "originals", attachment), :type => :attachment)
|
264
|
+
Parallel.map(self.content.attachments, :in_threads => Parallel.processor_count) do |attachment|
|
265
|
+
if processor = attachments.get(attachment)
|
266
|
+
processor.process
|
241
267
|
end
|
242
|
-
|
243
|
-
|
244
|
-
helper = Alula::AssetHelper.new(File.dirname(attachment), @config)
|
245
|
-
tn_type, tn_generated = helper.process(File.join("attachments", "originals", attachment), :type => :thumbnail)
|
268
|
+
@@lock.synchronize do
|
269
|
+
progress.step(:attachments)
|
246
270
|
end
|
247
|
-
|
248
|
-
pb.inc
|
249
271
|
end
|
250
|
-
|
251
|
-
|
272
|
+
|
273
|
+
progress.finish(:attachments)
|
274
|
+
progress.hide
|
275
|
+
|
276
|
+
# DEBUG
|
277
|
+
require 'json'
|
278
|
+
File.open(self.storage.path(:cache) + "/mapping.json", 'w') {|io| io.puts self.attachments.mapping.to_json}
|
252
279
|
end
|
253
280
|
|
254
|
-
def
|
281
|
+
def compile_assets
|
255
282
|
puts "==> Compiling assets"
|
256
283
|
|
257
|
-
#
|
258
|
-
|
259
|
-
|
260
|
-
|
284
|
+
# Generate stylesheet
|
285
|
+
@storage.output(:cache, "assets/style.css") do |io|
|
286
|
+
io.puts "/*"
|
287
|
+
|
288
|
+
# Theme style
|
289
|
+
io.puts " *= require #{self.config.theme}"
|
290
|
+
|
261
291
|
# Plugins
|
262
|
-
|
263
|
-
|
292
|
+
@plugins.each do |name, plugin|
|
293
|
+
io.puts " *= require #{name}"
|
294
|
+
end
|
295
|
+
|
296
|
+
# Vendored
|
297
|
+
|
298
|
+
# Blog customization
|
299
|
+
@storage.custom(/stylesheets\/.*.css.*$/).each do |name, item|
|
300
|
+
name = File.basename(name).gsub(/(\.\S+)$/, '')
|
301
|
+
io.puts " *= require #{name}"
|
264
302
|
end
|
265
|
-
|
303
|
+
|
304
|
+
io.puts "*/"
|
266
305
|
end
|
306
|
+
# Add stlesheet to template
|
307
|
+
Alula::Plugin.addon(:head, ->(context){ context.stylesheet_link("style") })
|
267
308
|
|
268
|
-
#
|
269
|
-
|
270
|
-
|
309
|
+
# Generate javascript
|
310
|
+
@storage.output(:cache, "assets/script.js") do |io|
|
311
|
+
io.puts "/*"
|
312
|
+
|
313
|
+
# Theme scripts
|
314
|
+
io.puts " *= require #{self.config.theme}"
|
315
|
+
|
271
316
|
# Plugins
|
272
|
-
|
273
|
-
|
317
|
+
@plugins.each do |name, plugin|
|
318
|
+
io.puts " *= require #{name}"
|
274
319
|
end
|
275
|
-
end
|
276
320
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
321
|
+
# Vendored
|
322
|
+
io.puts " *= require lazyload" if self.config.attachments.image.lazyload
|
323
|
+
|
324
|
+
# Customisation
|
325
|
+
@storage.custom(/javascripts\/.*.js.*$/).each do |name, item|
|
326
|
+
name = File.basename(name).gsub(/(\.\S+)$/, '')
|
327
|
+
io.puts " *= require #{name}"
|
282
328
|
end
|
329
|
+
io.puts " */"
|
283
330
|
end
|
331
|
+
# Add javascript to end of body
|
332
|
+
Alula::Plugin.addon(:body, ->(context){ context.javascript_link("script") })
|
284
333
|
|
334
|
+
# Compile all assets
|
335
|
+
progress.create :assets, title: "Compiling assets", total: @environment.each_logical_path.count
|
336
|
+
progress.display
|
337
|
+
|
338
|
+
@manifest = Manifest.new(@environment, @storage.path(:assets))
|
339
|
+
@manifest.progress = -> { progress.step(:assets) }
|
285
340
|
|
286
|
-
@manifest = Sprockets::Manifest.new(@sprockets, File.join("public", "assets"))
|
287
|
-
|
288
|
-
# Compile assets
|
289
341
|
@manifest.compile
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
#
|
294
|
-
# # Javascript
|
295
|
-
# "javascripts.js",
|
296
|
-
#
|
297
|
-
# # Attachments
|
298
|
-
# Dir[File.join("attachments", "**", "*")]
|
299
|
-
# .select {|f| File.file?(f) }
|
300
|
-
# .collect {|f| File.join(f.split("/")[1..-1])},
|
301
|
-
# ])
|
302
|
-
|
303
|
-
# Inject our manifest to jekyll
|
304
|
-
@jekyll.config["manifest"] = @manifest
|
305
|
-
|
306
|
-
# Cleanup
|
307
|
-
%w{styles.css scripts.js scripts_body.js}.each do |f|
|
308
|
-
FileUtils.rm(File.join("_tmp", "assets", f))
|
309
|
-
end
|
342
|
+
|
343
|
+
progress.finish(:assets)
|
344
|
+
progress.hide
|
310
345
|
end
|
311
346
|
|
312
|
-
def
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
347
|
+
def render
|
348
|
+
say "==> Render site"
|
349
|
+
|
350
|
+
progress.create :render, title: "Rendering content", total: (self.content.posts.count + self.content.pages.count)
|
351
|
+
progress.display
|
352
|
+
|
353
|
+
# Render all user content, parallel...
|
354
|
+
(self.content.posts + self.content.pages).each do |content|
|
355
|
+
# Write content to file
|
356
|
+
content.write
|
357
|
+
|
358
|
+
progress.title(:render, "%20s" % content.name[0..19]) if self.config.debug
|
359
|
+
progress.step(:render)
|
360
|
+
end
|
361
|
+
|
362
|
+
progress.finish(:render)
|
363
|
+
|
364
|
+
# Copy static content
|
365
|
+
progress.create :static, title: "Copy statics", total: self.content.statics.count
|
366
|
+
self.content.statics.each do |static|
|
367
|
+
@storage.output_public(static.name) { |io| io.write(static.read) }
|
368
|
+
|
369
|
+
progress.step :static
|
370
|
+
end
|
371
|
+
progress.finish :static
|
372
|
+
|
373
|
+
progress.hide
|
320
374
|
end
|
321
375
|
|
322
376
|
def cleanup
|
323
|
-
|
377
|
+
say "==> Cleaning up"
|
378
|
+
|
379
|
+
asset_path = @storage.path(:assets)
|
380
|
+
assets = @environment.used
|
381
|
+
.collect{|u| @environment[u]}
|
382
|
+
.reject{|u| u.nil?}
|
383
|
+
.collect{|u| File.join(asset_path, u.digest_path)}
|
384
|
+
outputted = @storage.outputted.reject{|o|o[/^#{asset_path}/]}
|
385
|
+
|
386
|
+
keep = assets + outputted
|
387
|
+
Dir[File.join(@storage.path(:public), "**", "*")].each do |entry|
|
388
|
+
next unless File.file?(entry)
|
389
|
+
FileUtils.rm entry if File.file?(entry) and !keep.include?(entry)
|
390
|
+
end
|
324
391
|
|
325
|
-
|
392
|
+
# Clean up empty directories
|
393
|
+
Dir[File.join(@storage.path(:public), "**", "*")].each do |entry|
|
394
|
+
next unless File.directory?(entry)
|
395
|
+
FileUtils.rmdir entry if Dir[File.join(entry, "**", "*")].count == 0
|
396
|
+
end
|
326
397
|
end
|
327
|
-
end
|
328
|
-
|
329
|
-
DEFAULTS = Jekyll::DEFAULTS.deep_merge({
|
330
|
-
'source' => '_tmp',
|
331
|
-
'destination' => 'public',
|
332
|
-
'markdown' => 'kramdown',
|
333
398
|
|
334
|
-
|
335
|
-
|
399
|
+
# Output helpers
|
400
|
+
def say(msg)
|
401
|
+
@shell ||= Thor::Shell::Basic.new
|
402
|
+
@shell.say msg
|
403
|
+
end
|
404
|
+
end
|
336
405
|
end
|