amiba 0.0.2
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/Gemfile +28 -0
- data/Thorfile +2 -0
- data/bin/amiba +15 -0
- data/bin/amiba-wp-import +113 -0
- data/lib/amiba/all.rb +13 -0
- data/lib/amiba/configuration.rb +40 -0
- data/lib/amiba/core_ext/file.rb +7 -0
- data/lib/amiba/core_ext/symbol.rb +11 -0
- data/lib/amiba/entry.rb +108 -0
- data/lib/amiba/page.rb +139 -0
- data/lib/amiba/repo.rb +28 -0
- data/lib/amiba/reverse_markdown.rb +199 -0
- data/lib/amiba/scope.rb +49 -0
- data/lib/amiba/site.rb +166 -0
- data/lib/amiba/source/entry.rb +42 -0
- data/lib/amiba/source/entry_finder.rb +136 -0
- data/lib/amiba/source/feed.rb +34 -0
- data/lib/amiba/source/partial.rb +22 -0
- data/lib/amiba/source.rb +148 -0
- data/lib/amiba.rb +90 -0
- data/templates/.amiba +4 -0
- data/templates/entries/.empty_directory +0 -0
- data/templates/layouts/default.haml.tt +6 -0
- data/templates/pages/.empty_directory +0 -0
- data/templates/skeletons/page.haml.tt +9 -0
- data/templates/skeletons/page.md.tt +8 -0
- metadata +282 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
include REXML
|
3
|
+
|
4
|
+
# reverse markdown for ruby
|
5
|
+
# author: JO
|
6
|
+
# e-mail: xijo@gmx.de
|
7
|
+
# date: 14.7.2009
|
8
|
+
# version: 0.1
|
9
|
+
# license: GPL
|
10
|
+
|
11
|
+
# TODO
|
12
|
+
# - ol numbering is buggy, in fact doesn't matter for markdown code
|
13
|
+
# -
|
14
|
+
|
15
|
+
module Amiba
|
16
|
+
class ReverseMarkdown
|
17
|
+
|
18
|
+
# set basic variables:
|
19
|
+
# - @li_counter: numbering list item (li) tags in an ordered list (ol)
|
20
|
+
# - @links: hold the links for adding them to the bottom of the @output
|
21
|
+
# this means 'reference style', please take a look at http://daringfireball.net/projects/markdown/syntax#link
|
22
|
+
# - @outout: fancy markdown code in here!
|
23
|
+
# - @indent: control indention level for nested lists
|
24
|
+
# - @errors: appearing errors, like unknown tags, go into this array
|
25
|
+
def initialize()
|
26
|
+
@li_counter = 0
|
27
|
+
@links = []
|
28
|
+
@output = ""
|
29
|
+
@indent = 0
|
30
|
+
@errors = []
|
31
|
+
end
|
32
|
+
|
33
|
+
# Invokes the HTML parsing by using a string. Returns the markdown code in @output.
|
34
|
+
# To garantuee well-formed xml for REXML a <root> element will be added, but has no effect.
|
35
|
+
# After parsing all elements, the 'reference style'-links will be inserted.
|
36
|
+
def parse_string(string)
|
37
|
+
doc = Document.new("<root>\n"+string+"\n</root>")
|
38
|
+
root = doc.root
|
39
|
+
root.elements.each do |element|
|
40
|
+
parse_element(element, :root)
|
41
|
+
end
|
42
|
+
insert_links()
|
43
|
+
@output
|
44
|
+
end
|
45
|
+
|
46
|
+
# Parsing an element and its children (recursive) and writing its markdown code to @output
|
47
|
+
# 1. do indent for nested list items
|
48
|
+
# 2. add the markdown opening tag for this element
|
49
|
+
# 3a. if element only contains text, handle it like a text node
|
50
|
+
# 3b. if element is a container handle its children, which may be text- or element nodes
|
51
|
+
# 4. finally add the markdown ending tag for this element
|
52
|
+
def parse_element(element, parent)
|
53
|
+
name = element.name.to_sym
|
54
|
+
# 1.
|
55
|
+
@output << indent() if name.eql?(:li)
|
56
|
+
# 2.
|
57
|
+
@output << opening(element, parent)
|
58
|
+
|
59
|
+
# 3a.
|
60
|
+
if (element.has_text? and element.children.size < 2)
|
61
|
+
@output << text_node(element, parent)
|
62
|
+
end
|
63
|
+
|
64
|
+
# 3b.
|
65
|
+
if element.has_elements?
|
66
|
+
element.children.each do |child|
|
67
|
+
# increase indent if nested list
|
68
|
+
@indent += 1 if element.name=~/(ul|ol)/ and parent.eql?(:li)
|
69
|
+
|
70
|
+
if child.node_type.eql?(:element)
|
71
|
+
parse_element(child, element.name.to_sym)
|
72
|
+
else
|
73
|
+
if parent.eql?(:blockquote)
|
74
|
+
@output << child.to_s.gsub("\n ", "\n>")
|
75
|
+
else
|
76
|
+
@output << child.to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# decrease indent if end of nested list
|
81
|
+
@indent -= 1 if element.name=~/(ul|ol)/ and parent.eql?(:li)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# 4.
|
86
|
+
@output << ending(element, parent)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns opening markdown tag for the element. Its parent matters sometimes!
|
90
|
+
def opening(type, parent)
|
91
|
+
case type.name.to_sym
|
92
|
+
when :h1
|
93
|
+
"# "
|
94
|
+
when :li
|
95
|
+
parent.eql?(:ul) ? " - " : " "+(@li_counter+=1).to_s+". "
|
96
|
+
when :ol
|
97
|
+
@li_counter = 0
|
98
|
+
""
|
99
|
+
when :ul
|
100
|
+
""
|
101
|
+
when :h2
|
102
|
+
"## "
|
103
|
+
when :em
|
104
|
+
"*"
|
105
|
+
when :strong
|
106
|
+
"**"
|
107
|
+
when :blockquote
|
108
|
+
# remove leading newline
|
109
|
+
type.children.first.value = ""
|
110
|
+
"> "
|
111
|
+
when :code
|
112
|
+
parent.eql?(:pre) ? " " : "`"
|
113
|
+
when :a
|
114
|
+
"["
|
115
|
+
when :img
|
116
|
+
"!["
|
117
|
+
when :hr
|
118
|
+
"----------\n\n"
|
119
|
+
else
|
120
|
+
@errors << "unknown start tag: "+type.name.to_s
|
121
|
+
""
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns the closing markdown tag, like opening()
|
126
|
+
def ending(type, parent)
|
127
|
+
case type.name.to_sym
|
128
|
+
when :h1
|
129
|
+
" #\n\n"
|
130
|
+
when :h2
|
131
|
+
" ##\n\n"
|
132
|
+
when :p
|
133
|
+
parent.eql?(:root) ? "\n\n" : "\n"
|
134
|
+
when :ol
|
135
|
+
parent.eql?(:li) ? "" : "\n"
|
136
|
+
when :ul
|
137
|
+
parent.eql?(:li) ? "" : "\n"
|
138
|
+
when :em
|
139
|
+
"*"
|
140
|
+
when :strong
|
141
|
+
"**"
|
142
|
+
when :li
|
143
|
+
""
|
144
|
+
when :blockquote
|
145
|
+
""
|
146
|
+
when :code
|
147
|
+
parent.eql?(:pre) ? "" : "`"
|
148
|
+
when :a
|
149
|
+
@links << type.attribute('href').to_s
|
150
|
+
"][" + @links.size.to_s + "] "
|
151
|
+
when :img
|
152
|
+
@links << type.attribute('src').to_s
|
153
|
+
"" + type.attribute('alt').to_s + "][" + @links.size.to_s + "] "
|
154
|
+
"#{type.attribute('alt')}][#{@links.size}] "
|
155
|
+
else
|
156
|
+
@errors << " unknown end tag: "+type.name.to_s
|
157
|
+
""
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Perform indent: two space, @indent times - quite simple! :)
|
162
|
+
def indent
|
163
|
+
str = ""
|
164
|
+
@indent.times do
|
165
|
+
str << " "
|
166
|
+
end
|
167
|
+
str
|
168
|
+
end
|
169
|
+
|
170
|
+
# Return the content of element, which should be just text.
|
171
|
+
# If its a code block to indent of 4 spaces.
|
172
|
+
# For block quotation add a leading '>'
|
173
|
+
def text_node(element, parent)
|
174
|
+
if element.name.to_sym.eql?(:code) and parent.eql?(:pre)
|
175
|
+
element.text.gsub("\n","\n ") << "\n"
|
176
|
+
elsif parent.eql?(:blockquote)
|
177
|
+
element.text.gsub!("\n ","\n>")
|
178
|
+
else
|
179
|
+
element.text
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Insert the mentioned reference style links.
|
184
|
+
def insert_links
|
185
|
+
@output << "\n"
|
186
|
+
@links.each_index do |index|
|
187
|
+
@output << " [#{index+1}]: #{@links[index]}\n"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Print out all errors, that occured and have been written to @errors.
|
192
|
+
def print_errors
|
193
|
+
@errors.each do |error|
|
194
|
+
puts error
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
data/lib/amiba/scope.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Amiba
|
2
|
+
class Scope
|
3
|
+
|
4
|
+
attr_reader :page
|
5
|
+
|
6
|
+
def initialize(page)
|
7
|
+
@page = page
|
8
|
+
end
|
9
|
+
|
10
|
+
def title
|
11
|
+
page.title
|
12
|
+
end
|
13
|
+
|
14
|
+
def description
|
15
|
+
page.description
|
16
|
+
end
|
17
|
+
|
18
|
+
def content
|
19
|
+
page_renderer.render(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def entries
|
23
|
+
Amiba::Source::Entry
|
24
|
+
end
|
25
|
+
|
26
|
+
def partial(path, locals={})
|
27
|
+
p = Amiba::Source::Partial.new path
|
28
|
+
Tilt.new(p.filename).render(Amiba::Scope.new(p), locals)
|
29
|
+
end
|
30
|
+
|
31
|
+
def site_name
|
32
|
+
Amiba::Configuration.site_name.nil? ? "" : "http://#{Amiba::Configuration.site_name}/"
|
33
|
+
end
|
34
|
+
|
35
|
+
def full_url(frag)
|
36
|
+
if site_name.empty?
|
37
|
+
frag
|
38
|
+
else
|
39
|
+
URI.join(site_name, frag).to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def page_renderer
|
46
|
+
Tilt.new page.staged_filename
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/amiba/site.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
module Amiba
|
2
|
+
module Site
|
3
|
+
|
4
|
+
class S3Upload < Thor::Group
|
5
|
+
include Amiba::Generator
|
6
|
+
|
7
|
+
namespace :"site:upload:s3"
|
8
|
+
|
9
|
+
class_option :credentials, :default => :default
|
10
|
+
|
11
|
+
def init_s3
|
12
|
+
Fog.credential = options[:credentials].to_sym
|
13
|
+
@s3 ||= Fog::Storage.new(:provider=>'AWS')
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
invoke Amiba::Site::Generate
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure_s3
|
21
|
+
if ! @s3.directories.get bucket
|
22
|
+
@bucket = @s3.directories.create(:key=>bucket, :public=>true, :location=>location)
|
23
|
+
say_status "Created", @bucket.key, :green
|
24
|
+
@s3.put_bucket_website(bucket,"index.html")
|
25
|
+
say_status "Configured", @bucket.key, :green
|
26
|
+
else
|
27
|
+
@bucket = @s3.directories.get bucket
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def upload_files
|
32
|
+
Dir[File.join(Amiba::Configuration.site_dir, "public", "**/*")].each do |ent|
|
33
|
+
next if File.directory? ent
|
34
|
+
path = File.expand_path ent
|
35
|
+
name = File.relpath(path, File.join(Amiba::Configuration.site_dir, "public"))
|
36
|
+
data = File.open path
|
37
|
+
file = @bucket.files.create(:key=>name, :body=>data, :public=>true)
|
38
|
+
say_status "Uploaded", name, :green
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def complete
|
43
|
+
host = "http://#{bucket}.s3-website-#{Fog.credentials[:region]}.amazonaws.com/"
|
44
|
+
say_status "Available at", host, :green
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def bucket
|
49
|
+
Amiba::Configuration.site_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def location
|
53
|
+
Amiba::Configuration.s3_location || "EU"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
class Generate < Thor::Group
|
59
|
+
include Amiba::Generator
|
60
|
+
|
61
|
+
namespace :"site:generate"
|
62
|
+
|
63
|
+
def self.source_root
|
64
|
+
Dir.pwd
|
65
|
+
end
|
66
|
+
|
67
|
+
def cleardown
|
68
|
+
remove_dir Amiba::Configuration.site_dir
|
69
|
+
remove_dir Amiba::Configuration.staged_dir
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_site_structure
|
73
|
+
empty_directory Amiba::Configuration.site_dir
|
74
|
+
end
|
75
|
+
|
76
|
+
def copy_favicon
|
77
|
+
if File.exists? "public/images/favicon.ico"
|
78
|
+
copy_file "public/images/favicon.ico", File.join(Amiba::Configuration.site_dir, "public/favicon.ico")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def copy_xdomain
|
83
|
+
if File.exists? "public/crossdomain.xml"
|
84
|
+
copy_file "public/crossdomain.xml", File.join(Amiba::Configuration.site_dir, "public/crossdomain.xml")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def copy_javascript
|
89
|
+
directory "public/js", File.join(Amiba::Configuration.site_dir, "public/js")
|
90
|
+
end
|
91
|
+
|
92
|
+
def copy_images
|
93
|
+
directory "public/images", File.join(Amiba::Configuration.site_dir, "public/images")
|
94
|
+
end
|
95
|
+
|
96
|
+
def copy_css
|
97
|
+
Dir.glob('public/css/*.css').each do |css_file|
|
98
|
+
copy_file css_file, File.join(Amiba::Configuration.site_dir, "public/css/", File.basename(css_file))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def process_and_copy_sass
|
103
|
+
Dir.glob('public/css/[^_]*.scss').each do |scss_file|
|
104
|
+
create_file File.join(Amiba::Configuration.site_dir,"public/css/", File.basename(scss_file).gsub('scss', 'css')) do
|
105
|
+
Tilt.new(scss_file).render
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def build_pages
|
111
|
+
Dir.glob('pages/**/[^_]*').each do |page_file|
|
112
|
+
next if File.directory? page_file
|
113
|
+
page = Amiba::Source::Page.new(File.relpath(page_file, "pages"))
|
114
|
+
next unless page.state == "published"
|
115
|
+
build_page page
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def build_entries
|
120
|
+
Amiba::Source::Entry.all.each do |entry|
|
121
|
+
build_page entry
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def build_json
|
126
|
+
Dir.glob('entries/*').each do |cat|
|
127
|
+
c = File.basename cat
|
128
|
+
create_file(File.join(Amiba::Configuration.site_dir, "public", c, "latest.json")) do
|
129
|
+
Amiba::Source::Entry.send(c.to_sym.pluralize).limit(20).each.inject([]) do |acc, ent|
|
130
|
+
a = ent.metadata
|
131
|
+
a["content"] = ent.render
|
132
|
+
acc << a
|
133
|
+
end.to_json
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def build_feeds
|
139
|
+
Dir.glob('feeds/*.builder').each do |feed_file|
|
140
|
+
feed = Amiba::Source::Feed.new(feed_file)
|
141
|
+
create_file(feed.output_filename) do
|
142
|
+
Tilt.new(feed.filename).render(Amiba::Scope.new(feed), :xml => Builder::XmlMarkup.new)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def build_layout(page)
|
150
|
+
layout = Amiba::Source::Layout.new(page.layout)
|
151
|
+
return layout if File.exists? layout.staged_filename
|
152
|
+
create_file(layout.staged_filename) do layout.content end
|
153
|
+
layout
|
154
|
+
end
|
155
|
+
|
156
|
+
def build_page(page)
|
157
|
+
layout = build_layout(page)
|
158
|
+
create_file(page.staged_filename) do page.content end
|
159
|
+
create_file(page.output_filename) do
|
160
|
+
Tilt.new(layout.staged_filename).render(Amiba::Scope.new(page))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Amiba
|
2
|
+
module Source
|
3
|
+
class Entry
|
4
|
+
extend Amiba::Source::EntryFinder
|
5
|
+
include Amiba::Source
|
6
|
+
|
7
|
+
attr_accessor :category
|
8
|
+
metadata_fields :title, :slug, :state, :layout
|
9
|
+
|
10
|
+
validates_presence_of :title, :state, :layout
|
11
|
+
|
12
|
+
def initialize(category, name, format, metadata = nil, content = nil)
|
13
|
+
self.category = category
|
14
|
+
self.name = name
|
15
|
+
self.format = format
|
16
|
+
self.metadata = metadata
|
17
|
+
self.content = content
|
18
|
+
end
|
19
|
+
|
20
|
+
def filename
|
21
|
+
File.join("entries", category.to_s.downcase.pluralize, name + ".#{format.to_s}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def staged_filename
|
25
|
+
File.join(Amiba::Configuration.staged_dir, filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
def output_filename
|
29
|
+
File.join(Amiba::Configuration.site_dir, 'public', category.to_s.downcase.pluralize, "#{name}.html")
|
30
|
+
end
|
31
|
+
|
32
|
+
def link
|
33
|
+
URI.escape( ["", category.to_s.downcase.pluralize, "#{name}.html"].join("/") )
|
34
|
+
end
|
35
|
+
|
36
|
+
def render
|
37
|
+
Tilt.new(self.staged_filename).render(Amiba::Scope.new(self))
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Amiba
|
2
|
+
module Source
|
3
|
+
module EntryFinder
|
4
|
+
|
5
|
+
def method_missing(method_name, *args, &block)
|
6
|
+
proxy = FinderProxy.new
|
7
|
+
proxy.send(method_name, *args, &block)
|
8
|
+
rescue
|
9
|
+
raise ArgumentError.new("#{method_name} does not exist")
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class FinderProxy
|
15
|
+
include Amiba::Repo
|
16
|
+
include Enumerable
|
17
|
+
|
18
|
+
def each(&blk)
|
19
|
+
entries.each(&blk)
|
20
|
+
end
|
21
|
+
|
22
|
+
def first
|
23
|
+
entries.first
|
24
|
+
end
|
25
|
+
|
26
|
+
def last
|
27
|
+
entries.last
|
28
|
+
end
|
29
|
+
|
30
|
+
def count
|
31
|
+
entries.count
|
32
|
+
end
|
33
|
+
|
34
|
+
def [](index)
|
35
|
+
entries[index]
|
36
|
+
end
|
37
|
+
|
38
|
+
def entries
|
39
|
+
result = (scopes[:category] || CategoryScope.new).apply
|
40
|
+
result = (scopes[:state] || StateScope.new).apply(result)
|
41
|
+
# reverse sorting is a more natural approach
|
42
|
+
result.sort! do |a, b|
|
43
|
+
last_commit_date(b.filename) <=> last_commit_date(a.filename)
|
44
|
+
end
|
45
|
+
result = scopes[:offset].apply(result) if scopes[:offset]
|
46
|
+
result = scopes[:limit].apply(result) if scopes[:limit]
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
[:draft, :published, :any].each do |state|
|
51
|
+
define_method state do
|
52
|
+
self[:state] = StateScope.new(state)
|
53
|
+
self
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(method_name, *args, &block)
|
58
|
+
entry_types = (Dir.glob('entries/*') << "all").map {|c| File.basename(c).to_sym}
|
59
|
+
if entry_types.include?(method_name)
|
60
|
+
self[:category] = CategoryScope.new(method_name)
|
61
|
+
else
|
62
|
+
raise ArgumentError
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def offset(index)
|
68
|
+
self[:offset] = OffsetScope.new(index)
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def limit(count)
|
73
|
+
self[:limit] = LimitScope.new(count)
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
def []=(key, val)
|
80
|
+
scopes[key] = val
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
def scopes
|
85
|
+
@scopes ||= {}
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
class CategoryScope
|
91
|
+
include Amiba::Repo
|
92
|
+
def initialize(category = :all)
|
93
|
+
@category = category
|
94
|
+
end
|
95
|
+
def apply
|
96
|
+
entry_files.map do |ef|
|
97
|
+
_, category, filename = ef.split('/')
|
98
|
+
name, format = filename.split('.')
|
99
|
+
Amiba::Source::Entry.new(category, name, format)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
def entry_files
|
103
|
+
globstring = "entries/#{@category == :all ? '*' : @category.to_s}/*"
|
104
|
+
Dir.glob(globstring).select {|e| !repo.log(e).empty?}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class StateScope
|
109
|
+
def initialize(state = :published)
|
110
|
+
@state = state
|
111
|
+
end
|
112
|
+
def apply(entries)
|
113
|
+
return entries if @state == :any
|
114
|
+
entries.select {|e| e.state.to_sym == @state}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class OffsetScope
|
119
|
+
def initialize(offset = 0)
|
120
|
+
@offset = offset
|
121
|
+
end
|
122
|
+
def apply(entries)
|
123
|
+
entries[@offset..-1]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class LimitScope
|
128
|
+
def initialize(limit = -1)
|
129
|
+
@limit = (limit == -1 ? -1 : limit - 1)
|
130
|
+
end
|
131
|
+
def apply(entries)
|
132
|
+
entries[0..@limit]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module Amiba
|
3
|
+
module Source
|
4
|
+
class Feed
|
5
|
+
include Amiba::Source
|
6
|
+
|
7
|
+
attr_accessor :type, :name
|
8
|
+
def initialize(fn)
|
9
|
+
self.name, self.type = File.basename(fn, ".builder").split(".")
|
10
|
+
end
|
11
|
+
|
12
|
+
def filename
|
13
|
+
@filename ||= File.join("feeds", "#{@name}.#{@type}.builder")
|
14
|
+
end
|
15
|
+
|
16
|
+
def content=(c)
|
17
|
+
@content ||= self.new? ? c : File.read(filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
def staged_filename
|
21
|
+
File.join(Amiba::Configuration.staged_dir, filename)
|
22
|
+
end
|
23
|
+
|
24
|
+
def output_filename
|
25
|
+
File.join(Amiba::Configuration.site_dir, "public/#{name}.#{type}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def link
|
29
|
+
URI.escape "/#{name}.#{type}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Amiba
|
2
|
+
module Source
|
3
|
+
class Partial
|
4
|
+
include Amiba::Source
|
5
|
+
|
6
|
+
attr_accessor :dir, :name
|
7
|
+
def initialize(path)
|
8
|
+
self.dir, self.name = File.split path
|
9
|
+
end
|
10
|
+
|
11
|
+
def filename
|
12
|
+
@filename ||= File.join("pages", @dir, "_#{@name}.haml")
|
13
|
+
end
|
14
|
+
|
15
|
+
def staged_filename
|
16
|
+
File.join(Amiba::Configuration.staged_dir, filename)
|
17
|
+
end
|
18
|
+
alias_method :output_filename, :staged_filename
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|