amiba 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|