alula 0.2.3 → 0.4.0b
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/.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
|