zwite 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ # Introducing Zwite
2
+ ### the static site generator
3
+
4
+ Zwite is a static site generator that is -very- pluggable built in ruby. It is very pluggable and works with apps/plugins instead of one monolithic site.
data/bin/zwite ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env rvm-auto-ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
5
+ help = <<HELP
6
+ HELP
7
+
8
+ require "optparse"
9
+ require "zwite"
10
+
11
+ options = {}
12
+ opts = OptionParser.new do |opts|
13
+ opts.banner = help
14
+
15
+ opts.on("--server [PORT]", "Start web server (default port 3030)") do |port|
16
+ options["server"] = true
17
+ unless port.nil?
18
+ options["server_port"] = port
19
+ else
20
+ options["server_port"] = "3030"
21
+ end
22
+ end
23
+
24
+ opts.on("--path [PATH]", "Path to project folder") do |path|
25
+ unless path.nil?
26
+ options["path"] = File.absolute_path(path)
27
+ else
28
+ options["path"] = Dir.pwd
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ opts.parse!
35
+
36
+ Zwite::Engine.sharedEngine.run(options)
@@ -0,0 +1,122 @@
1
+ module Zwite
2
+
3
+ class App
4
+
5
+ ##
6
+ # Properties
7
+ ##
8
+
9
+ attr_accessor :site
10
+ attr_accessor :path
11
+ attr_accessor :url
12
+ attr_accessor :static_url
13
+ attr_accessor :name
14
+ attr_accessor :output_path
15
+ attr_accessor :plugins
16
+ attr_accessor :liquid_file_system
17
+
18
+ def to_s
19
+ return "<Zwite::App> name: #{self.name}, mount: #{self.url}"
20
+ end
21
+
22
+ def to_liquid
23
+ hash = {
24
+ "url" => self.url,
25
+ "static_url" => self.static_url,
26
+ "name" => self.name
27
+ }
28
+ self.plugins.each do |p|
29
+ hash[p.name] = p
30
+ end
31
+ return hash
32
+ end
33
+
34
+ ##
35
+ # Initialization
36
+ ##
37
+
38
+ def initialize(site, path, url)
39
+ self.site = site
40
+ self.path = path
41
+ self.url = url
42
+ self.static_url = self.url + "static/"
43
+ self.name = self.path.basename.to_s
44
+ self.output_path = self.site.output_path + self.url[1..self.url.length]
45
+ self.plugins = []
46
+ self.site.plugins.each do |p|
47
+ plugin = p.new(self)
48
+ if plugin.enabled?
49
+ self.plugins << plugin
50
+ end
51
+ end
52
+ self.liquid_file_system = Zwite::Liquid::FileSystem.new((self.path + "templates").to_s)
53
+ end
54
+
55
+ ##
56
+ # Actions
57
+ ##
58
+
59
+ def hash
60
+ return self.path.hash
61
+ end
62
+
63
+ def eql?(other)
64
+ return self.path.eql?(other.path)
65
+ end
66
+
67
+ def preprocess
68
+ self.plugins.each do |p|
69
+ p.preprocess
70
+ end
71
+ end
72
+
73
+ def generate
74
+ self.plugins.each do |p|
75
+ p.generate
76
+ end
77
+ end
78
+
79
+ def render(contents, context = {}, path = nil, validate = true)
80
+ ::Liquid::Template.file_system = self.liquid_file_system
81
+ template = ::Liquid::Template.parse(contents)
82
+ ctx = self.site.liquid_context
83
+ ctx = ctx.merge_recursive(context)
84
+
85
+ output = template.render(ctx)
86
+
87
+ # # nokogiri validate
88
+ # if validate
89
+ # n = Nokogiri.parse(output)
90
+ # if n.errors.any?
91
+ # message = ["\n"]
92
+ # unless path.nil?
93
+ # message << "[VALIDATION ERROR]: #{path}"
94
+ #
95
+ # else
96
+ # message << "[VALIDATION ERROR]"
97
+ # end
98
+ # n.errors.each do |error|
99
+ # message << "\tline: #{error.line} error: #{error}"
100
+ # end
101
+ #
102
+ # message << "\n\n"
103
+ # raise message.join("\n")
104
+ #
105
+ # end
106
+ # end
107
+
108
+ return output
109
+ end
110
+
111
+ def render_file(path, context = {})
112
+ contents = path.read
113
+ return render(contents, context, path)
114
+ end
115
+
116
+ def render_template(template, context = {})
117
+ return render_file((self.path + "templates" + template), context)
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,339 @@
1
+ module Zwite
2
+
3
+ module DateFormat
4
+
5
+ class Formatter < Object
6
+
7
+ WEEKDAYS = {
8
+ 0 => "Sunday",
9
+ 1 => "Monday",
10
+ 2 => "Tuesday",
11
+ 3 => "Wednesday",
12
+ 4 => "Thursday",
13
+ 5 => "Friday",
14
+ 6 => "Saturday"
15
+ }
16
+ WEEKDAYS_ABBR = {
17
+ 0 => "Sun",
18
+ 1 => "Mon",
19
+ 2 => "Tue",
20
+ 3 => "Wed",
21
+ 4 => "Thu",
22
+ 5 => "Fri",
23
+ 6 => "Sat"
24
+ }
25
+ WEEKDAYS_REV = {
26
+ "sunday" => 0,
27
+ "monday" => 1,
28
+ "tuesday" => 2,
29
+ "wednesday" => 3,
30
+ "thursday" => 4,
31
+ "friday" => 5,
32
+ "saturday" => 6
33
+ }
34
+ MONTHS = {
35
+ 1 => "January",
36
+ 2 => "February",
37
+ 3 => "March",
38
+ 4 => "April",
39
+ 5 => "May",
40
+ 6 => "June",
41
+ 7 => "July",
42
+ 8 => "August",
43
+ 9 => "September",
44
+ 10 => "October",
45
+ 11 => "November",
46
+ 12 => "December"
47
+ }
48
+ MONTHS_3 = {
49
+ 1 => "Jan",
50
+ 2 => "Feb",
51
+ 3 => "Mar",
52
+ 4 => "Apr",
53
+ 5 => "May",
54
+ 6 => "Jun",
55
+ 7 => "Jul",
56
+ 8 => "Aug",
57
+ 9 => "Sep",
58
+ 10 => "Oct",
59
+ 11 => "Nov",
60
+ 12 => "Dec"
61
+ }
62
+ MONTHS_3_REV = {
63
+ "Jan" => 1,
64
+ "Feb" => 2,
65
+ "Mar" => 3,
66
+ "Apr" => 4,
67
+ "May" => 5,
68
+ "Jun" => 6,
69
+ "Jul" => 7,
70
+ "Aug" => 8,
71
+ "Sep" => 9,
72
+ "Oct" => 10,
73
+ "Nov" => 11,
74
+ "Dec" => 12
75
+ }
76
+ MONTHS_AP = {
77
+ 1 => "Jan.",
78
+ 2 => "Feb.",
79
+ 3 => "March",
80
+ 4 => "April",
81
+ 5 => "May",
82
+ 6 => "June",
83
+ 7 => "July",
84
+ 8 => "Aug.",
85
+ 9 => "Sept.",
86
+ 10 => "Oct.",
87
+ 11 => "Nov.",
88
+ 12 => "Dec."
89
+ }
90
+
91
+ attr_accessor :data
92
+
93
+ def initialize(datetime)
94
+ self.data = datetime
95
+ end
96
+
97
+ def format(str)
98
+ pieces = []
99
+ str.each_char do |c|
100
+ if Formatter.method_defined?(c)
101
+ pieces << self.send(c)
102
+ elsif c
103
+ pieces << c
104
+ end
105
+ end
106
+ return pieces.join("")
107
+ end
108
+
109
+ # a.m or p.m
110
+ def a
111
+ if self.data.hour > 11
112
+ return "p.m."
113
+ end
114
+ return "a.m"
115
+ end
116
+
117
+ # 'AM' or 'PM'.
118
+ def A
119
+ if self.data.hour > 11
120
+ return "PM"
121
+ end
122
+ return "AM"
123
+ end
124
+
125
+ # Month, textual, 3 letters, lowercase.
126
+ def b
127
+ return MONTHS_3[self.data.month].downcase
128
+ end
129
+
130
+ # Unimplemented
131
+ def B
132
+ return "[B]Unimplemented"
133
+ end
134
+
135
+ # ISO 8601 format. (Note: unlike others formatters, such as "Z", "O" or "r", the "c" formatter will not add timezone offset if value is a naive datetime (see datetime.tzinfo).
136
+ def c
137
+ return self.data.iso8601
138
+ end
139
+
140
+ # Day of the month, 2 digits with leading zeros.
141
+ def d
142
+ return "%02d" % self.data.day
143
+ end
144
+
145
+ # Day of the week, textual, 3 letters.
146
+ def D
147
+ return WEEKDAYS_ABBR[self.data.weekday]
148
+ end
149
+
150
+ # Unimplemented
151
+ def e
152
+ return "[E]Unimplemented"
153
+ end
154
+
155
+ # Month, locale specific alternative representation usually used for long date representation
156
+ def E
157
+ return MONTHS_ALT[self.data.month]
158
+ end
159
+
160
+ # Time, in 12-hour hours and minutes, with minutes left off if they're zero. Proprietary extension.
161
+ def f
162
+ if self.data.minute == 0
163
+ return self.g
164
+ end
165
+ return "%s:%s" % self.g, self.i
166
+ end
167
+
168
+ # Month, textual, long.
169
+ def F
170
+ return MONTHS[self.data.month]
171
+ end
172
+
173
+ # Hour 12 hour format - without leading zeros
174
+ def g
175
+ if self.data.hour == 0
176
+ return 12
177
+ end
178
+ if self.data.hour > 12
179
+ return self.data.hour - 12
180
+ end
181
+ return self.data.hour
182
+ end
183
+
184
+ # Hour 24 hour format - without leading zeros
185
+ def G
186
+ return self.data.hour
187
+ end
188
+
189
+ # Hour 12 hour format
190
+ def h
191
+ return "%02d" % self.g
192
+ end
193
+
194
+ # Hour 24 hour format
195
+ def H
196
+ return "%02d" % self.G
197
+ end
198
+
199
+ # Minutes
200
+ def i
201
+ return "%02d" % self.data.minute
202
+ end
203
+
204
+ # Unimplemented
205
+ def I
206
+ return "[I]Unimplemented"
207
+ end
208
+
209
+ # Day of the month without leading zeros.
210
+ def j
211
+ return self.data.day
212
+ end
213
+
214
+ # Day of the week, textual, long.
215
+ def l
216
+ return WEEKDAYS[self.data.wday]
217
+ end
218
+
219
+ # Boolean for whether it's a leap year.
220
+ def L
221
+ return self.data.leap?
222
+ end
223
+
224
+ # Month, 2 digits with leading zeros.
225
+ def m
226
+ return "%02d" % self.data.month
227
+ end
228
+
229
+ # Month, textual, 3 letters.
230
+ def M
231
+ return MONTHS_3[self.data.month]
232
+ end
233
+
234
+ # Month without leading zero
235
+ def n
236
+ return self.data.month
237
+ end
238
+
239
+ # Month abbreviation in Associated Press style. Proprietary extension.
240
+ def N
241
+ return MONTHS_AP[self.data.month]
242
+ end
243
+
244
+ # ISO-8601 week-numbering year, corresponding to the ISO-8601 week number (W)
245
+ def o
246
+ return self.data.strftime("%G")
247
+ end
248
+
249
+ # Difference to Greenwich time in hours.
250
+ def O
251
+ return self.data.strftime("%z")
252
+ end
253
+
254
+ # Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off if they're zero and the special-case strings 'midnight' and 'noon' if appropriate. Proprietary extension.
255
+ def P
256
+ if self.data.minute == 0 && self.data.hour == 0
257
+ return "midnight"
258
+ elsif self.data.minute == 0 and self.data.hour == 12
259
+ return "noon"
260
+ end
261
+ return "%s %s" % self.f, self.a
262
+ end
263
+
264
+ # RFC 2822 formatted date.
265
+ def r
266
+ return self.data.rfc2822
267
+ end
268
+
269
+ # Seconds, 2 digits with leading zeros.
270
+ def s
271
+ return "%02d" % self.data.second
272
+ end
273
+
274
+ # English ordinal suffix for day of the month, 2 characters.
275
+ def S
276
+ if (11..13).include?(self.data.day)
277
+ return "#{self}th"
278
+ end
279
+ last = self.data.day % 10
280
+ if last == 1
281
+ return "st"
282
+ elsif last == 2
283
+ return "nd"
284
+ elsif last == 3
285
+ return "rd"
286
+ end
287
+ return "th"
288
+ end
289
+
290
+ # Number of days in the given month
291
+ def t
292
+ return (Date.new(self.data.year, 12, 31) << (12 - self.data.month)).day
293
+ end
294
+
295
+ # Timezone of this machine
296
+ def T
297
+ return DateTime.now.strftime("%Z")
298
+ end
299
+
300
+ # Microseconds
301
+ def u
302
+ return self.data.strftime("%6N").to_i
303
+ end
304
+
305
+ # Seconds since the Unix Epoch (January 1 1970 00:00:00 UTC).
306
+ def U
307
+ return self.data.strftime("%s").to_i
308
+ end
309
+
310
+ # ISO-8601 week number of year, weeks starting on Monday
311
+ def W
312
+ return self.data.strftime("%-V").to_i
313
+ end
314
+
315
+ # Year 2 digits
316
+ def y
317
+ return self.data.year.to_s[2..3]
318
+ end
319
+
320
+ # Year 4 digits
321
+ def Y
322
+ return self.data.year
323
+ end
324
+
325
+ # Day of the year
326
+ def z
327
+ return self.data.yday - 1
328
+ end
329
+
330
+ # Time zone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.
331
+ def Z
332
+ return self.data.offset.numerator * 60 *60
333
+ end
334
+
335
+ end
336
+
337
+ end
338
+
339
+ end
@@ -0,0 +1,100 @@
1
+ module Zwite
2
+
3
+ module Pagination
4
+
5
+ class Page < Object
6
+
7
+ ##
8
+ # Properties
9
+ ##
10
+
11
+ attr_accessor :paginator
12
+ attr_accessor :objects
13
+ attr_accessor :number
14
+ attr_accessor :has_next
15
+ attr_accessor :has_prev
16
+ attr_accessor :has_other_pages
17
+ attr_accessor :next_page_number
18
+ attr_accessor :prev_page_number
19
+ attr_accessor :start_index
20
+ attr_accessor :end_index
21
+
22
+ def to_liquid
23
+ return {
24
+ "objects" => self.objects,
25
+ "number" => self.number,
26
+ "has_next" => self.has_next,
27
+ "has_prev" => self.has_prev,
28
+ "has_other_pages" => self.has_other_pages,
29
+ "next_page_number" => self.next_page_number,
30
+ "prev_page_number" => self.prev_page_number,
31
+ "start_index" => self.start_index,
32
+ "end_index" => self.end_index
33
+ }
34
+ end
35
+
36
+ ##
37
+ # Initialization
38
+ ##
39
+ def initialize(paginator, objects, number)
40
+ self.paginator = paginator
41
+ self.objects = objects
42
+ self.number = number
43
+
44
+ self.has_next = (self.number < self.paginator.pages_count)
45
+ self.has_prev = (self.number > 1)
46
+ self.has_other_pages = (self.has_next || self.has_prev)
47
+ self.next_page_number = self.number + 1
48
+ self.prev_page_number = self.number - 1
49
+ self.start_index = (self.paginator.pages_count == 0) ? 0 : (self.paginator.per_page * (self.number - 1)) + 1
50
+ self.end_index = (self.paginator.pages_count == self.number) ? self.paginator.pages_count : self.number * self.paginator.per_page
51
+
52
+ end
53
+
54
+ end
55
+
56
+ class Paginator < Object
57
+
58
+ ##
59
+ # Properties
60
+ ##
61
+
62
+ attr_accessor :objects
63
+ attr_accessor :per_page
64
+ attr_accessor :pages
65
+ attr_accessor :pages_count
66
+
67
+ def to_liquid
68
+ return {
69
+ "objects" => self.objects,
70
+ "per_page" => self.per_page,
71
+ "pages" => self.pages,
72
+ "pages_count" => self.pages_count
73
+ }
74
+ end
75
+
76
+ ##
77
+ # Initialization
78
+ ##
79
+ def initialize(objects, per_page)
80
+ self.objects = objects
81
+ self.per_page = per_page
82
+
83
+ self.pages = []
84
+ unless objects.count == 0
85
+ self.pages_count = (self.objects.count / self.per_page.to_f).ceil
86
+ self.pages_count.times do |i|
87
+ page_start = self.per_page * i
88
+ page_objects = self.objects[page_start..page_start + self.per_page - 1]
89
+ page = Page.new(self, page_objects, i + 1)
90
+ self.pages << page
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,50 @@
1
+ module Zwite
2
+
3
+ class Plugin
4
+
5
+ ##
6
+ # properties
7
+ ##
8
+
9
+ attr_accessor :app
10
+ attr_reader :name
11
+ attr_reader :enabled
12
+
13
+ def enabled?
14
+ return (self.app.path + self.name).exist?
15
+ end
16
+
17
+ ##
18
+ # class methods
19
+ ##
20
+
21
+ def self.inherited(base_class)
22
+ self.subclasses << base_class
23
+ end
24
+
25
+ def self.subclasses
26
+ @subclasses ||= []
27
+ return @subclasses
28
+ end
29
+
30
+ ##
31
+ # initialization
32
+ ##
33
+
34
+ def initialize(app)
35
+ self.app = app
36
+ end
37
+
38
+ ##
39
+ # actions
40
+ ##
41
+
42
+ def preprocess
43
+ end
44
+
45
+ def generate
46
+ end
47
+
48
+ end
49
+
50
+ end