olelo 0.9.0
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 +10 -0
- data/.gitmodules +3 -0
- data/Gemfile +3 -0
- data/README.markdown +104 -0
- data/Rakefile +92 -0
- data/bin/olelo +5 -0
- data/config.ru +86 -0
- data/config/aspects.rb +256 -0
- data/config/config.yml.default +154 -0
- data/config/initializers/00-mime_types.rb +29 -0
- data/config/initializers/01-slim.rb +2 -0
- data/config/interwiki.yml +11 -0
- data/doc/AUTHORS +7 -0
- data/doc/LICENSE +22 -0
- data/lib/olelo.rb +39 -0
- data/lib/olelo/application.rb +294 -0
- data/lib/olelo/attributes.rb +285 -0
- data/lib/olelo/config.rb +88 -0
- data/lib/olelo/extensions.rb +252 -0
- data/lib/olelo/helper.rb +290 -0
- data/lib/olelo/hooks.rb +142 -0
- data/lib/olelo/html_safe.rb +29 -0
- data/lib/olelo/initializer.rb +76 -0
- data/lib/olelo/locale.rb +63 -0
- data/lib/olelo/locale.yml +284 -0
- data/lib/olelo/menu.rb +101 -0
- data/lib/olelo/middleware/blacklist.rb +25 -0
- data/lib/olelo/middleware/degrade_mime_type.rb +19 -0
- data/lib/olelo/middleware/flash.rb +97 -0
- data/lib/olelo/middleware/force_encoding.rb +41 -0
- data/lib/olelo/page.rb +266 -0
- data/lib/olelo/patch.rb +311 -0
- data/lib/olelo/plugin.rb +188 -0
- data/lib/olelo/repository.rb +225 -0
- data/lib/olelo/routing.rb +223 -0
- data/lib/olelo/templates.rb +30 -0
- data/lib/olelo/user.rb +132 -0
- data/lib/olelo/util.rb +233 -0
- data/lib/olelo/version.rb +3 -0
- data/lib/olelo/virtualfs.rb +161 -0
- data/lib/rack/olelo_patches.rb +33 -0
- data/lib/rack/relative_redirect.rb +44 -0
- data/lib/rack/static_cache.rb +93 -0
- data/lib/yard/addons.rb +1 -0
- data/lib/yard/addons/hook_handler.rb +25 -0
- data/lib/yard/addons/override_tag.rb +14 -0
- data/lib/yard/addons/route_handler.rb +33 -0
- data/lib/yard/addons/sanitize_anchor.rb +16 -0
- data/olelo.gemspec +31 -0
- data/plugins/aspects/changelog.rb +45 -0
- data/plugins/aspects/documentbrowser.rb +57 -0
- data/plugins/aspects/download.rb +11 -0
- data/plugins/aspects/highlight.rb +8 -0
- data/plugins/aspects/image.rb +41 -0
- data/plugins/aspects/imageinfo.rb +64 -0
- data/plugins/aspects/locale.yml +60 -0
- data/plugins/aspects/main.rb +199 -0
- data/plugins/aspects/pageinfo.rb +37 -0
- data/plugins/aspects/source.rb +6 -0
- data/plugins/aspects/subpages.rb +44 -0
- data/plugins/aspects/text.rb +9 -0
- data/plugins/blog/blog.css +1 -0
- data/plugins/blog/blog.scss +37 -0
- data/plugins/blog/locale.yml +12 -0
- data/plugins/blog/main.rb +85 -0
- data/plugins/editor/locale.yml +18 -0
- data/plugins/editor/markup/main.rb +3 -0
- data/plugins/editor/markup/script.js +10 -0
- data/plugins/editor/markup/script/00-jquery.textselection.js +267 -0
- data/plugins/editor/markup/script/01-olelo.markupeditor.js +116 -0
- data/plugins/editor/markup/script/init.js +10 -0
- data/plugins/editor/preview.rb +52 -0
- data/plugins/editor/recaptcha.rb +56 -0
- data/plugins/filters/creole.rb +37 -0
- data/plugins/filters/disposition.rb +9 -0
- data/plugins/filters/editsection.rb +67 -0
- data/plugins/filters/fix_img_tag.rb +16 -0
- data/plugins/filters/html_wrapper.rb +12 -0
- data/plugins/filters/interwiki.rb +19 -0
- data/plugins/filters/link_classifier.rb +26 -0
- data/plugins/filters/locale.yml +15 -0
- data/plugins/filters/main.rb +202 -0
- data/plugins/filters/markdown_nowiki.rb +15 -0
- data/plugins/filters/numbering.xsl +93 -0
- data/plugins/filters/orgmode.rb +6 -0
- data/plugins/filters/rubypants.rb +6 -0
- data/plugins/filters/s5/main.rb +32 -0
- data/plugins/filters/s5/s5.xsl +118 -0
- data/plugins/filters/tilt.rb +17 -0
- data/plugins/filters/toc.rb +50 -0
- data/plugins/filters/xhtml2latex.xsl +232 -0
- data/plugins/filters/xslt.rb +22 -0
- data/plugins/gallery/gallery.css +1 -0
- data/plugins/gallery/gallery.scss +28 -0
- data/plugins/gallery/main.rb +34 -0
- data/plugins/misc/fancybox/images/blank.gif +0 -0
- data/plugins/misc/fancybox/images/fancy_close.png +0 -0
- data/plugins/misc/fancybox/images/fancy_loading.png +0 -0
- data/plugins/misc/fancybox/images/fancy_nav_left.png +0 -0
- data/plugins/misc/fancybox/images/fancy_nav_right.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_e.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_n.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_ne.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_nw.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_s.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_se.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_sw.png +0 -0
- data/plugins/misc/fancybox/images/fancy_shadow_w.png +0 -0
- data/plugins/misc/fancybox/images/fancy_title_left.png +0 -0
- data/plugins/misc/fancybox/images/fancy_title_main.png +0 -0
- data/plugins/misc/fancybox/images/fancy_title_over.png +0 -0
- data/plugins/misc/fancybox/images/fancy_title_right.png +0 -0
- data/plugins/misc/fancybox/images/fancybox-x.png +0 -0
- data/plugins/misc/fancybox/images/fancybox-y.png +0 -0
- data/plugins/misc/fancybox/images/fancybox.png +0 -0
- data/plugins/misc/fancybox/jquery.fancybox.css +1 -0
- data/plugins/misc/fancybox/jquery.fancybox.scss +323 -0
- data/plugins/misc/fancybox/main.rb +4 -0
- data/plugins/misc/fancybox/script.js +37 -0
- data/plugins/misc/fancybox/script/00-jquery.mousewheel.js +84 -0
- data/plugins/misc/fancybox/script/01-jquery.easing.js +205 -0
- data/plugins/misc/fancybox/script/02-jquery.fancybox.js +1156 -0
- data/plugins/misc/fancybox/script/init.js +18 -0
- data/plugins/misc/system.rb +192 -0
- data/plugins/misc/variables.rb +29 -0
- data/plugins/misc/webdav.rb +45 -0
- data/plugins/repositories/git_grep.rb +69 -0
- data/plugins/repositories/gitrb_repository.rb +204 -0
- data/plugins/repositories/locale.yml +12 -0
- data/plugins/repositories/rugged_repository.rb +454 -0
- data/plugins/security/acl.rb +57 -0
- data/plugins/security/basic_auth.rb +21 -0
- data/plugins/security/locale.yml +21 -0
- data/plugins/security/persistent_login.rb +32 -0
- data/plugins/security/portal.rb +28 -0
- data/plugins/security/private_wiki.rb +24 -0
- data/plugins/security/readonly_wiki.rb +25 -0
- data/plugins/security/stack.rb +20 -0
- data/plugins/security/yamlfile.rb +66 -0
- data/plugins/tags/code.rb +6 -0
- data/plugins/tags/footnotes.rb +35 -0
- data/plugins/tags/gist-embed.css +123 -0
- data/plugins/tags/gist.rb +13 -0
- data/plugins/tags/html.rb +57 -0
- data/plugins/tags/include.rb +20 -0
- data/plugins/tags/main.rb +353 -0
- data/plugins/tags/math.rb +117 -0
- data/plugins/tags/scripting.rb +64 -0
- data/plugins/tags/sort.rb +7 -0
- data/plugins/tags/tabs.rb +20 -0
- data/plugins/treeview/images/collapsed.png +0 -0
- data/plugins/treeview/images/expanded.png +0 -0
- data/plugins/treeview/images/menu.png +0 -0
- data/plugins/treeview/images/tree.png +0 -0
- data/plugins/treeview/images/wait.gif +0 -0
- data/plugins/treeview/main.rb +16 -0
- data/plugins/treeview/script.js +5 -0
- data/plugins/treeview/script/00-jquery.treeview.js +164 -0
- data/plugins/treeview/script/init.js +25 -0
- data/plugins/treeview/treeview.css +1 -0
- data/plugins/treeview/treeview.scss +113 -0
- data/plugins/utils/assets.rb +74 -0
- data/plugins/utils/cache.rb +53 -0
- data/plugins/utils/image_magick.rb +34 -0
- data/plugins/utils/pygments.css +1 -0
- data/plugins/utils/pygments.rb +50 -0
- data/plugins/utils/pygments.scss +83 -0
- data/plugins/utils/semaphore.rb +50 -0
- data/plugins/utils/shell.rb +45 -0
- data/plugins/utils/store.rb +315 -0
- data/plugins/utils/worker.rb +36 -0
- data/plugins/utils/xml.rb +29 -0
- data/static/images/favicon.png +0 -0
- data/static/script.js +267 -0
- data/static/script/00-json2.js +486 -0
- data/static/script/01-jstorage.js +217 -0
- data/static/script/02-jquery.js +9440 -0
- data/static/script/03-jquery.ui.core.js +337 -0
- data/static/script/04-jquery.ui.widget.js +502 -0
- data/static/script/05-jquery.ui.position.js +517 -0
- data/static/script/06-jquery.ui.menu.js +609 -0
- data/static/script/07-jquery.ui.autocomplete.js +601 -0
- data/static/script/08-olelo.i18n.js +37 -0
- data/static/script/09-olelo.unsaved.js +68 -0
- data/static/script/10-olelo.historytable.js +40 -0
- data/static/script/11-olelo.pagination.js +18 -0
- data/static/script/13-olelo.tabwidget.js +57 -0
- data/static/script/14-olelo.timeago.js +70 -0
- data/static/script/15-olelo.underliner.js +31 -0
- data/static/script/16-olelo.ui.combobox.js +32 -0
- data/static/script/init.js +48 -0
- data/static/themes/atlantis/constants.scss +15 -0
- data/static/themes/atlantis/iehacks.scss +38 -0
- data/static/themes/atlantis/images/actions/delete.png +0 -0
- data/static/themes/atlantis/images/actions/edit.png +0 -0
- data/static/themes/atlantis/images/actions/history.png +0 -0
- data/static/themes/atlantis/images/actions/home.png +0 -0
- data/static/themes/atlantis/images/actions/move.png +0 -0
- data/static/themes/atlantis/images/actions/new.png +0 -0
- data/static/themes/atlantis/images/actions/page.png +0 -0
- data/static/themes/atlantis/images/bg/button.png +0 -0
- data/static/themes/atlantis/images/bg/container.png +0 -0
- data/static/themes/atlantis/images/bg/content.png +0 -0
- data/static/themes/atlantis/images/bg/footer.png +0 -0
- data/static/themes/atlantis/images/bg/header.jpg +0 -0
- data/static/themes/atlantis/images/bg/header.orig.jpg +0 -0
- data/static/themes/atlantis/images/bg/header_gray.jpg +0 -0
- data/static/themes/atlantis/images/bug.png +0 -0
- data/static/themes/atlantis/images/filetypes/7z.png +0 -0
- data/static/themes/atlantis/images/filetypes/_archive.png +0 -0
- data/static/themes/atlantis/images/filetypes/_audio.png +0 -0
- data/static/themes/atlantis/images/filetypes/_code.png +0 -0
- data/static/themes/atlantis/images/filetypes/_linux.png +0 -0
- data/static/themes/atlantis/images/filetypes/_picture.png +0 -0
- data/static/themes/atlantis/images/filetypes/_video.png +0 -0
- data/static/themes/atlantis/images/filetypes/bz2.png +0 -0
- data/static/themes/atlantis/images/filetypes/doc.png +0 -0
- data/static/themes/atlantis/images/filetypes/flac.png +0 -0
- data/static/themes/atlantis/images/filetypes/gz.png +0 -0
- data/static/themes/atlantis/images/filetypes/html.png +0 -0
- data/static/themes/atlantis/images/filetypes/java.png +0 -0
- data/static/themes/atlantis/images/filetypes/jpg.png +0 -0
- data/static/themes/atlantis/images/filetypes/midi.png +0 -0
- data/static/themes/atlantis/images/filetypes/mp3.png +0 -0
- data/static/themes/atlantis/images/filetypes/ogg.png +0 -0
- data/static/themes/atlantis/images/filetypes/pdf.png +0 -0
- data/static/themes/atlantis/images/filetypes/php.png +0 -0
- data/static/themes/atlantis/images/filetypes/png.png +0 -0
- data/static/themes/atlantis/images/filetypes/ppt.png +0 -0
- data/static/themes/atlantis/images/filetypes/psd.png +0 -0
- data/static/themes/atlantis/images/filetypes/rar.png +0 -0
- data/static/themes/atlantis/images/filetypes/rb.png +0 -0
- data/static/themes/atlantis/images/filetypes/sh.png +0 -0
- data/static/themes/atlantis/images/filetypes/tar.png +0 -0
- data/static/themes/atlantis/images/filetypes/txt.png +0 -0
- data/static/themes/atlantis/images/filetypes/wma.png +0 -0
- data/static/themes/atlantis/images/filetypes/xls.png +0 -0
- data/static/themes/atlantis/images/filetypes/zip.png +0 -0
- data/static/themes/atlantis/images/folder.png +0 -0
- data/static/themes/atlantis/images/folder_open.png +0 -0
- data/static/themes/atlantis/images/loading.gif +0 -0
- data/static/themes/atlantis/images/loading.xcf +0 -0
- data/static/themes/atlantis/images/not_found.png +0 -0
- data/static/themes/atlantis/images/page.png +0 -0
- data/static/themes/atlantis/images/search.png +0 -0
- data/static/themes/atlantis/layout.scss +115 -0
- data/static/themes/atlantis/menu.scss +99 -0
- data/static/themes/atlantis/print.scss +129 -0
- data/static/themes/atlantis/screen.scss +495 -0
- data/static/themes/atlantis/style.css +3 -0
- data/static/themes/lib/autocomplete.scss +39 -0
- data/static/themes/lib/headlines.scss +10 -0
- data/static/themes/lib/horizontal-list.scss +31 -0
- data/static/themes/lib/patch.scss +88 -0
- data/static/themes/lib/reset.scss +114 -0
- data/static/themes/lib/rounded.scss +46 -0
- data/static/themes/lib/shadow.scss +14 -0
- data/test/config_test.rb +28 -0
- data/test/factory_test.rb +29 -0
- data/test/hash_extensions_test.rb +16 -0
- data/test/helper.rb +38 -0
- data/test/hooks_test.rb +85 -0
- data/test/object_extensions_test.rb +20 -0
- data/test/page_test.rb +168 -0
- data/test/request_test.rb +166 -0
- data/test/string_extensions_test.rb +32 -0
- data/test/templates_test.rb +39 -0
- data/test/util_test.rb +71 -0
- data/views/changes.slim +22 -0
- data/views/compare.slim +8 -0
- data/views/delete.slim +9 -0
- data/views/deleted.slim +2 -0
- data/views/edit.slim +65 -0
- data/views/error.slim +6 -0
- data/views/history.slim +20 -0
- data/views/layout.slim +38 -0
- data/views/login.slim +37 -0
- data/views/move.slim +10 -0
- data/views/not_found.slim +6 -0
- data/views/profile.slim +26 -0
- data/views/show.slim +9 -0
- metadata +488 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
module Olelo
|
|
2
|
+
# Version object
|
|
3
|
+
class Version
|
|
4
|
+
attr_reader :id, :author, :date, :comment, :parents
|
|
5
|
+
attr_reader? :head
|
|
6
|
+
|
|
7
|
+
def initialize(id, author, date, comment, parents, head)
|
|
8
|
+
@id, @author, @date, @comment, @parents, @head = id, author, date, comment, parents, head
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Returns shortened unique version id
|
|
12
|
+
#
|
|
13
|
+
# @return [String] shortened version id
|
|
14
|
+
# @api public
|
|
15
|
+
def short
|
|
16
|
+
Version.short(id)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Shortens given version id
|
|
20
|
+
#
|
|
21
|
+
# @param [String] long version id
|
|
22
|
+
# @return [String] shortened version id
|
|
23
|
+
# @api public
|
|
24
|
+
def self.short(id)
|
|
25
|
+
Repository.instance.short_version(id)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Return version id
|
|
29
|
+
#
|
|
30
|
+
# @return [String]
|
|
31
|
+
# @api public
|
|
32
|
+
def to_s
|
|
33
|
+
id
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Check equality of versions
|
|
37
|
+
#
|
|
38
|
+
# @param [Version, String] other version
|
|
39
|
+
# @return [Boolean]
|
|
40
|
+
# @api public
|
|
41
|
+
def ==(other)
|
|
42
|
+
other.to_s == id
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def cache_id
|
|
46
|
+
"#{@id}-#{@head}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Difference between versions
|
|
51
|
+
Diff = Struct.new(:from, :to, :patch)
|
|
52
|
+
|
|
53
|
+
# Abstract repository base
|
|
54
|
+
#
|
|
55
|
+
# This class should not be used directly. Use the {Page} class
|
|
56
|
+
# which is implemented on top of it.
|
|
57
|
+
#
|
|
58
|
+
# @abstract
|
|
59
|
+
class Repository
|
|
60
|
+
include Util
|
|
61
|
+
extend Factory
|
|
62
|
+
|
|
63
|
+
def self.instance
|
|
64
|
+
Thread.current[:olelo_repository] ||= self[Config['repository.type']].new(Config['repository'][Config['repository.type']])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Wrap block in transaction
|
|
68
|
+
#
|
|
69
|
+
# Every write operation has to be wrapped in a transaction.
|
|
70
|
+
#
|
|
71
|
+
# @yield Transaction block
|
|
72
|
+
# @return [void]
|
|
73
|
+
# @api public
|
|
74
|
+
def transaction
|
|
75
|
+
raise NotImplementedError
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Set content of path
|
|
79
|
+
#
|
|
80
|
+
# This method can only be used within a {#transaction} block.
|
|
81
|
+
#
|
|
82
|
+
# @param [String] path
|
|
83
|
+
# @param [String, #read] content
|
|
84
|
+
# @return [void]
|
|
85
|
+
# @api public
|
|
86
|
+
def set_content(path, content)
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Set attributes of path
|
|
91
|
+
#
|
|
92
|
+
# This method can only be used within a {#transaction} block.
|
|
93
|
+
#
|
|
94
|
+
# @param [String] path
|
|
95
|
+
# @param [Hash] attributes
|
|
96
|
+
# @return [void]
|
|
97
|
+
# @api public
|
|
98
|
+
def set_attributes(path, attributes)
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Move path
|
|
103
|
+
#
|
|
104
|
+
# This method can only be used within a {#transaction} block.
|
|
105
|
+
#
|
|
106
|
+
# @param [String] path
|
|
107
|
+
# @param [String] destination
|
|
108
|
+
# @return [void]
|
|
109
|
+
def move(path, destination)
|
|
110
|
+
raise NotImplementedError
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Delete path
|
|
114
|
+
#
|
|
115
|
+
# This method can only be used within a {#transaction} block.
|
|
116
|
+
#
|
|
117
|
+
# @param [String] path
|
|
118
|
+
# @return [void]
|
|
119
|
+
def delete(path)
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Commit changes with a comment
|
|
124
|
+
#
|
|
125
|
+
# This method can only be used within a {#transaction} block.
|
|
126
|
+
#
|
|
127
|
+
# @param [String] comment
|
|
128
|
+
# @return [Version] New head version
|
|
129
|
+
# @api public
|
|
130
|
+
def commit(comment)
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Check if path exists
|
|
135
|
+
#
|
|
136
|
+
# @param [String] path
|
|
137
|
+
# @param [String, Version] version
|
|
138
|
+
# @return [Boolean]
|
|
139
|
+
# @api public
|
|
140
|
+
def path_exists?(path, version)
|
|
141
|
+
raise NotImplementedError
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Find version by version id
|
|
145
|
+
#
|
|
146
|
+
# Returns head version if no version is given
|
|
147
|
+
#
|
|
148
|
+
# @param [String] version
|
|
149
|
+
# @return [Version]
|
|
150
|
+
# @api public
|
|
151
|
+
def get_version(version = nil)
|
|
152
|
+
raise NotImplementedError
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Get history of path beginning with newest version
|
|
156
|
+
#
|
|
157
|
+
# @param [String] path
|
|
158
|
+
# @param [Integer] Number of versions to skip
|
|
159
|
+
# @param [Integer] Maximum number of versions to load
|
|
160
|
+
# @return [Array<Version>]
|
|
161
|
+
# @api public
|
|
162
|
+
def get_history(path, skip = nil, limit = nil)
|
|
163
|
+
raise NotImplementedError
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Get versions of path
|
|
167
|
+
#
|
|
168
|
+
# @param [String] path
|
|
169
|
+
# @param [String, Version] version
|
|
170
|
+
# @return [Array<Version>] Tuple: previous version, current version, next version
|
|
171
|
+
# @api public
|
|
172
|
+
def get_path_version(path, version)
|
|
173
|
+
raise NotImplementedError
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Get children of path
|
|
177
|
+
#
|
|
178
|
+
# @param [String] path
|
|
179
|
+
# @param [String, Version] version
|
|
180
|
+
# @return [Array<String>] Names of children
|
|
181
|
+
# @api public
|
|
182
|
+
def get_children(path, version)
|
|
183
|
+
raise NotImplementedError
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Get content
|
|
187
|
+
#
|
|
188
|
+
# @param [String] path
|
|
189
|
+
# @param [String, Version] version
|
|
190
|
+
# @return [String] content
|
|
191
|
+
# @api public
|
|
192
|
+
def get_content(path, version)
|
|
193
|
+
raise NotImplementedError
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Get attributes
|
|
197
|
+
#
|
|
198
|
+
# @param [String] path
|
|
199
|
+
# @param [String, Version] version
|
|
200
|
+
# @return [Hash] attribute hash
|
|
201
|
+
# @api public
|
|
202
|
+
def get_attributes(path, version)
|
|
203
|
+
raise NotImplementedError
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Difference between versions for path
|
|
207
|
+
#
|
|
208
|
+
# @param [String] path
|
|
209
|
+
# @param [Version, String] from
|
|
210
|
+
# @param [Version, String] to
|
|
211
|
+
# @api public
|
|
212
|
+
def diff(path, from, to)
|
|
213
|
+
raise NotImplementedError
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Shortens given version id
|
|
217
|
+
#
|
|
218
|
+
# @param [String] long version id
|
|
219
|
+
# @return [String] shortened version id
|
|
220
|
+
# @api public
|
|
221
|
+
def short_version(version)
|
|
222
|
+
version
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
module Olelo
|
|
2
|
+
module Routing
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.extend(ClassMethods)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
attr_reader :params, :original_params, :response, :request, :env
|
|
8
|
+
|
|
9
|
+
# Process rack request
|
|
10
|
+
#
|
|
11
|
+
# This method duplicates the object and calls {#call!} on it.
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
# @param [Hash] env Rack environment
|
|
15
|
+
# @return [Array] Rack return value
|
|
16
|
+
# @see http://rack.rubyforge.org/doc/SPEC.html
|
|
17
|
+
def call(env)
|
|
18
|
+
dup.call!(env)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Process rack request
|
|
22
|
+
#
|
|
23
|
+
# @api public
|
|
24
|
+
# @param [Hash] env Rack environment
|
|
25
|
+
# @return [Array] Rack return value
|
|
26
|
+
def call!(env)
|
|
27
|
+
@env = env
|
|
28
|
+
@request = Rack::Request.new(env)
|
|
29
|
+
@response = Rack::Response.new
|
|
30
|
+
@params = @original_params = @request.params.with_indifferent_access
|
|
31
|
+
@original_params.freeze
|
|
32
|
+
|
|
33
|
+
catch(:forward) do
|
|
34
|
+
with_hooks(:request) { perform! }
|
|
35
|
+
status, header, body = response.finish
|
|
36
|
+
return [status, header, request.head? ? [] : body]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
@app ? @app.call(env) : error!(NotFound.new(@request.path_info))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Halt routing with response
|
|
43
|
+
#
|
|
44
|
+
# Possible responses:
|
|
45
|
+
# * String or Object with #each
|
|
46
|
+
# * Symbol
|
|
47
|
+
# * [Symbol, String or Object with #each]
|
|
48
|
+
#
|
|
49
|
+
# @param [Symbol, String, #each] *response
|
|
50
|
+
# @return [void]
|
|
51
|
+
# @api public
|
|
52
|
+
def halt(*response)
|
|
53
|
+
throw :halt, response.length == 1 ? response.first : response
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Redirect to uri
|
|
57
|
+
#
|
|
58
|
+
# @param uri Target uri
|
|
59
|
+
# @return [void]
|
|
60
|
+
# @api public
|
|
61
|
+
def redirect(uri)
|
|
62
|
+
throw :redirect, uri
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Pass to next matching route
|
|
66
|
+
#
|
|
67
|
+
# @return [void]
|
|
68
|
+
# @api public
|
|
69
|
+
def pass
|
|
70
|
+
throw :pass
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Forward to next application on the rack stack
|
|
74
|
+
#
|
|
75
|
+
# @return [void]
|
|
76
|
+
# @api public
|
|
77
|
+
def forward
|
|
78
|
+
throw :forward
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def error!(error)
|
|
84
|
+
response.status = Rack::Utils.status_code(error.try(:status) || :internal_server_error)
|
|
85
|
+
handle_error(error)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def perform!
|
|
89
|
+
result = catch(:halt) do
|
|
90
|
+
uri = catch(:redirect) do
|
|
91
|
+
with_hooks(:routing) { route! }
|
|
92
|
+
end
|
|
93
|
+
response.redirect uri
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
return if !result
|
|
98
|
+
if result.respond_to?(:to_str)
|
|
99
|
+
response.body = [result]
|
|
100
|
+
elsif result.respond_to?(:to_ary)
|
|
101
|
+
result = result.to_ary
|
|
102
|
+
if result.length == 2 && Symbol === result.first
|
|
103
|
+
response.status = Rack::Utils.status_code(result.first)
|
|
104
|
+
response.body = result.last
|
|
105
|
+
else
|
|
106
|
+
response.body = result
|
|
107
|
+
end
|
|
108
|
+
elsif result.respond_to?(:each)
|
|
109
|
+
response.body = result
|
|
110
|
+
elsif Symbol === result
|
|
111
|
+
response.status = Rack::Utils.status_code(result)
|
|
112
|
+
else
|
|
113
|
+
raise TypeError, "#{result.inspect} not supported"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def route!
|
|
118
|
+
path = unescape(request.path_info)
|
|
119
|
+
method = request.request_method
|
|
120
|
+
self.class.router[method].find(path) do |name, params, function|
|
|
121
|
+
@params = @original_params.merge(params)
|
|
122
|
+
catch(:pass) do
|
|
123
|
+
with_hooks(:action, method.downcase.to_sym, name) do
|
|
124
|
+
halt function.bind(self).call
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end if self.class.router[method]
|
|
128
|
+
raise NotFound, path
|
|
129
|
+
rescue ::Exception => error
|
|
130
|
+
halt error!(error)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
class Router
|
|
134
|
+
SYNTAX = {
|
|
135
|
+
'\(' => '(?:', '\)' => ')?',
|
|
136
|
+
'\{' => '(?:', '\}' => ')',
|
|
137
|
+
'\|' => '|'
|
|
138
|
+
}.freeze
|
|
139
|
+
|
|
140
|
+
include Enumerable
|
|
141
|
+
attr_reader :head, :tail
|
|
142
|
+
|
|
143
|
+
def initialize
|
|
144
|
+
@head, @tail = [], []
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def find(path)
|
|
148
|
+
each do |name, pattern, keys, function|
|
|
149
|
+
if match = pattern.match(path)
|
|
150
|
+
params = {}
|
|
151
|
+
keys.zip(match.captures.to_a).each {|k, v| params[k] = v if !v.blank? }
|
|
152
|
+
yield(name, params, function)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def each(&block)
|
|
158
|
+
@head.each(&block)
|
|
159
|
+
@tail.each(&block)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def add(function, path, patterns = {})
|
|
163
|
+
tail = patterns.delete(:tail)
|
|
164
|
+
pattern = Regexp.escape(path)
|
|
165
|
+
SYNTAX.each_pair {|k,v| pattern.gsub!(k, v) }
|
|
166
|
+
keys = []
|
|
167
|
+
pattern.gsub!(/:(\w+)/) do
|
|
168
|
+
keys << $1
|
|
169
|
+
patterns.key?($1) ? "(#{patterns[$1]})" : "([^/?&#\.]+)"
|
|
170
|
+
end
|
|
171
|
+
pattern = /^#{pattern}$/
|
|
172
|
+
|
|
173
|
+
if i = @head.index {|x| x.first == path }
|
|
174
|
+
@head[i] = [path, pattern, keys, function]
|
|
175
|
+
elsif i = @tail.index {|x| x.first == path }
|
|
176
|
+
@tail[i] = [path, pattern, keys, function]
|
|
177
|
+
else
|
|
178
|
+
(tail ? @tail : @head) << [path, pattern, keys, function]
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
module ClassMethods
|
|
184
|
+
def router
|
|
185
|
+
@router ||= {}
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def patterns(patterns = nil)
|
|
189
|
+
@patterns ||= Hash.with_indifferent_access
|
|
190
|
+
patterns ? @patterns.merge!(patterns) : @patterns
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def get(path, patterns = {}, &block)
|
|
194
|
+
add_route('GET', path, patterns, &block)
|
|
195
|
+
add_route('HEAD', path, patterns, &block)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def put(path, patterns = {}, &block)
|
|
199
|
+
add_route('PUT', path, patterns, &block)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def post(path, patterns = {}, &block)
|
|
203
|
+
add_route('POST', path, patterns, &block)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def delete(path, patterns = {}, &block)
|
|
207
|
+
add_route('DELETE', path, patterns, &block)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
private
|
|
211
|
+
|
|
212
|
+
def add_route(method, path, patterns = {}, &block)
|
|
213
|
+
name = "#{method} #{path}"
|
|
214
|
+
if method_defined?(name)
|
|
215
|
+
redefine_method(name, &block)
|
|
216
|
+
else
|
|
217
|
+
define_method(name, &block)
|
|
218
|
+
end
|
|
219
|
+
(router[method] ||= Router.new).add(instance_method(name), path, self.patterns.merge(patterns))
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Olelo
|
|
2
|
+
module Templates
|
|
3
|
+
class << self
|
|
4
|
+
attr_reader :cache
|
|
5
|
+
attr_accessor :loader
|
|
6
|
+
|
|
7
|
+
def enable_caching
|
|
8
|
+
@cache = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def with_caching(id)
|
|
12
|
+
return cache[id] if cache && cache[id]
|
|
13
|
+
template = yield
|
|
14
|
+
cache[id] = template if cache
|
|
15
|
+
template
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def render(name, options = {}, &block)
|
|
20
|
+
locals = options.delete(:locals) || {}
|
|
21
|
+
name = "#{name}.slim"
|
|
22
|
+
path = Templates.loader.context.to_s/name
|
|
23
|
+
id = [path, options.to_a].flatten.join('-')
|
|
24
|
+
template = Templates.with_caching(id) do
|
|
25
|
+
Slim::Template.new(path, options) { Templates.loader.load(name) }
|
|
26
|
+
end
|
|
27
|
+
template.render(self, locals, &block).html_safe
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|