rethoth 0.4.1
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.
- checksums.yaml +7 -0
- data/LICENSE +26 -0
- data/bin/thoth +233 -0
- data/lib/proto/config.ru +45 -0
- data/lib/proto/thoth.conf.sample +206 -0
- data/lib/thoth/cache.rb +53 -0
- data/lib/thoth/config.rb +158 -0
- data/lib/thoth/controller/admin.rb +75 -0
- data/lib/thoth/controller/api/comment.rb +73 -0
- data/lib/thoth/controller/api/page.rb +134 -0
- data/lib/thoth/controller/api/post.rb +122 -0
- data/lib/thoth/controller/api/tag.rb +59 -0
- data/lib/thoth/controller/archive.rb +50 -0
- data/lib/thoth/controller/comment.rb +173 -0
- data/lib/thoth/controller/main.rb +193 -0
- data/lib/thoth/controller/media.rb +172 -0
- data/lib/thoth/controller/page.rb +167 -0
- data/lib/thoth/controller/post.rb +310 -0
- data/lib/thoth/controller/search.rb +86 -0
- data/lib/thoth/controller/tag.rb +107 -0
- data/lib/thoth/controller.rb +48 -0
- data/lib/thoth/errors.rb +35 -0
- data/lib/thoth/helper/admin.rb +86 -0
- data/lib/thoth/helper/cookie.rb +45 -0
- data/lib/thoth/helper/error.rb +122 -0
- data/lib/thoth/helper/pagination.rb +131 -0
- data/lib/thoth/helper/wiki.rb +77 -0
- data/lib/thoth/helper/ysearch.rb +89 -0
- data/lib/thoth/importer/pants.rb +81 -0
- data/lib/thoth/importer/poseidon.rb +54 -0
- data/lib/thoth/importer/thoth.rb +103 -0
- data/lib/thoth/importer.rb +131 -0
- data/lib/thoth/layout/default.rhtml +47 -0
- data/lib/thoth/middleware/minify.rb +82 -0
- data/lib/thoth/migrate/001_create_schema.rb +108 -0
- data/lib/thoth/migrate/002_add_media_size.rb +37 -0
- data/lib/thoth/migrate/003_add_post_draft.rb +38 -0
- data/lib/thoth/migrate/004_add_comment_email.rb +37 -0
- data/lib/thoth/migrate/005_add_page_position.rb +37 -0
- data/lib/thoth/migrate/006_add_comment_close_delete.rb +43 -0
- data/lib/thoth/migrate/007_add_comment_summary.rb +37 -0
- data/lib/thoth/model/comment.rb +216 -0
- data/lib/thoth/model/media.rb +87 -0
- data/lib/thoth/model/page.rb +204 -0
- data/lib/thoth/model/post.rb +262 -0
- data/lib/thoth/model/tag.rb +80 -0
- data/lib/thoth/model/tags_posts_map.rb +34 -0
- data/lib/thoth/monkeypatch/sequel/model/errors.rb +37 -0
- data/lib/thoth/plugin/thoth_delicious.rb +105 -0
- data/lib/thoth/plugin/thoth_flickr.rb +86 -0
- data/lib/thoth/plugin/thoth_pinboard.rb +98 -0
- data/lib/thoth/plugin/thoth_tags.rb +68 -0
- data/lib/thoth/plugin/thoth_twitter.rb +175 -0
- data/lib/thoth/plugin.rb +59 -0
- data/lib/thoth/public/css/admin.css +223 -0
- data/lib/thoth/public/css/thoth.css +592 -0
- data/lib/thoth/public/images/admin-sprite.png +0 -0
- data/lib/thoth/public/images/thoth-sprite.png +0 -0
- data/lib/thoth/public/js/admin/comments.js +116 -0
- data/lib/thoth/public/js/admin/name.js +244 -0
- data/lib/thoth/public/js/admin/tagcomplete.js +332 -0
- data/lib/thoth/public/js/lazyload-min.js +4 -0
- data/lib/thoth/public/js/thoth.js +203 -0
- data/lib/thoth/public/robots.txt +5 -0
- data/lib/thoth/version.rb +37 -0
- data/lib/thoth/view/admin/index.rhtml +1 -0
- data/lib/thoth/view/admin/login.rhtml +23 -0
- data/lib/thoth/view/admin/toolbar.rhtml +117 -0
- data/lib/thoth/view/admin/welcome.rhtml +58 -0
- data/lib/thoth/view/archive/index.rhtml +24 -0
- data/lib/thoth/view/comment/comment.rhtml +47 -0
- data/lib/thoth/view/comment/delete.rhtml +15 -0
- data/lib/thoth/view/comment/form.rhtml +81 -0
- data/lib/thoth/view/comment/index.rhtml +68 -0
- data/lib/thoth/view/comment/list.rhtml +48 -0
- data/lib/thoth/view/media/delete.rhtml +15 -0
- data/lib/thoth/view/media/edit.rhtml +12 -0
- data/lib/thoth/view/media/form.rhtml +7 -0
- data/lib/thoth/view/media/list.rhtml +35 -0
- data/lib/thoth/view/media/media.rhtml +44 -0
- data/lib/thoth/view/media/new.rhtml +7 -0
- data/lib/thoth/view/page/delete.rhtml +15 -0
- data/lib/thoth/view/page/edit.rhtml +15 -0
- data/lib/thoth/view/page/form.rhtml +57 -0
- data/lib/thoth/view/page/index.rhtml +9 -0
- data/lib/thoth/view/page/list.rhtml +49 -0
- data/lib/thoth/view/page/new.rhtml +15 -0
- data/lib/thoth/view/post/comments.rhtml +12 -0
- data/lib/thoth/view/post/compact.rhtml +48 -0
- data/lib/thoth/view/post/delete.rhtml +15 -0
- data/lib/thoth/view/post/edit.rhtml +15 -0
- data/lib/thoth/view/post/form.rhtml +83 -0
- data/lib/thoth/view/post/index.rhtml +48 -0
- data/lib/thoth/view/post/list.rhtml +61 -0
- data/lib/thoth/view/post/new.rhtml +15 -0
- data/lib/thoth/view/post/tiny.rhtml +4 -0
- data/lib/thoth/view/search/index.rhtml +45 -0
- data/lib/thoth/view/tag/index.rhtml +34 -0
- data/lib/thoth/view/thoth/css.rhtml +9 -0
- data/lib/thoth/view/thoth/footer.rhtml +15 -0
- data/lib/thoth/view/thoth/header.rhtml +23 -0
- data/lib/thoth/view/thoth/index.rhtml +11 -0
- data/lib/thoth/view/thoth/js.rhtml +6 -0
- data/lib/thoth/view/thoth/sidebar.rhtml +38 -0
- data/lib/thoth/view/thoth/util/pager.rhtml +23 -0
- data/lib/thoth/view/thoth/util/simple_pager.rhtml +15 -0
- data/lib/thoth/view/thoth/util/table_sortheader.rhtml +20 -0
- data/lib/thoth.rb +394 -0
- metadata +409 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth; module Helper
|
30
|
+
|
31
|
+
# The Cookie helper wraps access to Ramaze's request.cookies hash and returns
|
32
|
+
# only the first cookie matching a specified name (rather than an array).
|
33
|
+
module Cookie
|
34
|
+
private
|
35
|
+
|
36
|
+
# Gets the first cookie matching the specified _name_. If not found, the
|
37
|
+
# provided _default_ value will be returned.
|
38
|
+
def cookie(name, default = nil)
|
39
|
+
return default unless cookie = request.cookies[name.to_s]
|
40
|
+
return cookie.first if cookie.is_a?(Array)
|
41
|
+
cookie
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end; end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth; module Helper
|
30
|
+
|
31
|
+
# The Error helper module provides methods for interrupting the current
|
32
|
+
# request and responding with an error message and corresponding HTTP error
|
33
|
+
# code.
|
34
|
+
module Error
|
35
|
+
Ramaze::Helper::LOOKUP << self
|
36
|
+
|
37
|
+
# Displays a "400 Bad Request" error message and returns a 400 response
|
38
|
+
# code.
|
39
|
+
def error_400(message = nil)
|
40
|
+
if message
|
41
|
+
error_layout 400, '400 Bad Request', %[
|
42
|
+
<p>
|
43
|
+
Your browser sent a request that this server could not understand.
|
44
|
+
</p>
|
45
|
+
|
46
|
+
<p>
|
47
|
+
#{message}
|
48
|
+
</p>
|
49
|
+
]
|
50
|
+
else
|
51
|
+
error_layout 400, '400 Bad Request', %[
|
52
|
+
<p>
|
53
|
+
Your browser sent a request that this server could not understand.
|
54
|
+
</p>
|
55
|
+
]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Displays a "403 Forbidden" error message and returns a 403 response code.
|
60
|
+
def error_403
|
61
|
+
error_layout 403, '403 Forbidden', %[
|
62
|
+
<p>
|
63
|
+
You don't have permission to access
|
64
|
+
<code>#{h(request.REQUEST_URI)}</code> on this server.
|
65
|
+
</p>
|
66
|
+
]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Displays a "404 Not Found" error message and returns a 404 response code.
|
70
|
+
def error_404
|
71
|
+
error_layout 404, '404 Not Found', %[
|
72
|
+
<p>
|
73
|
+
The requested URL <code>#{h(request.REQUEST_URI)}</code> was not
|
74
|
+
found on this server.
|
75
|
+
</p>
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Displays a "405 Method Not Allowed" error message and returns a 405
|
80
|
+
# response code.
|
81
|
+
def error_405
|
82
|
+
error_layout 405, '405 Method Not Allowed', %[
|
83
|
+
<p>
|
84
|
+
The #{request.env['REQUEST_METHOD']} method is not allowed for the
|
85
|
+
requested URL.
|
86
|
+
</p>
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
# Displays a "500 Internal Server Error" error message and returns a 500
|
91
|
+
# response code.
|
92
|
+
def error_500
|
93
|
+
if e = request.env[Rack::RouteExceptions::EXCEPTION]
|
94
|
+
Ramaze::Log.error e
|
95
|
+
end
|
96
|
+
|
97
|
+
error_layout 500, '500 Internal Server Error', %[
|
98
|
+
<p>
|
99
|
+
The server encountered an internal error and was unable to complete
|
100
|
+
your request.
|
101
|
+
</p>
|
102
|
+
]
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def error_layout(status, title, content = '')
|
108
|
+
respond! %[
|
109
|
+
<html>
|
110
|
+
<head>
|
111
|
+
<title>#{h(title)}</title>
|
112
|
+
</head>
|
113
|
+
<body>
|
114
|
+
<h1>#{h(title)}</h1>
|
115
|
+
#{content}
|
116
|
+
</body>
|
117
|
+
</html>
|
118
|
+
].unindent, status
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end; end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
|
31
|
+
# The Pager class provides a simple wrapper around a paginated Sequel dataset.
|
32
|
+
class Pager
|
33
|
+
|
34
|
+
# Initializes a new Pager instance wrapping the given Sequel _dataset_ and
|
35
|
+
# using _url_ as the template for all generated URLs. _url_ should be a
|
36
|
+
# string containing an sprintf flag (such as <tt>%s</tt>) in place of the
|
37
|
+
# page number.
|
38
|
+
def initialize(dataset, url)
|
39
|
+
@dataset = dataset
|
40
|
+
@url = url
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the number of the current page.
|
44
|
+
def current_page
|
45
|
+
@dataset.current_page
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the number of records in the current page.
|
49
|
+
def current_page_record_count
|
50
|
+
@dataset.current_page_record_count
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the record range for the current page.
|
54
|
+
def current_page_record_range
|
55
|
+
@dataset.current_page_record_range
|
56
|
+
end
|
57
|
+
|
58
|
+
# Iterates over all pages within 5 steps from the current page, yielding the
|
59
|
+
# page number and URL for each.
|
60
|
+
def navigate # :yields: page, url
|
61
|
+
nav_start = [current_page - 5, 1].max
|
62
|
+
nav_end = [nav_start + 9, page_count].min
|
63
|
+
(nav_start..nav_end).each {|page| yield page, url(page) }
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns +true+ if the total number of pages is greater than 1.
|
67
|
+
def navigation?
|
68
|
+
page_count > 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the number of the next page or +nil+ if the current page is the
|
72
|
+
# last.
|
73
|
+
def next_page
|
74
|
+
@dataset.next_page
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the URL for the next page or +nil+ if the current page is the
|
78
|
+
# last.
|
79
|
+
def next_url
|
80
|
+
next_page ? url(next_page) : nil
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the total number of pages.
|
84
|
+
def page_count
|
85
|
+
@dataset.page_count
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the page range.
|
89
|
+
def page_range
|
90
|
+
@dataset.page_range
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the number of records per page.
|
94
|
+
def page_size
|
95
|
+
@dataset.page_size
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the number of the previous page or +nil+ if the current page is
|
99
|
+
# the first.
|
100
|
+
def prev_page
|
101
|
+
@dataset.prev_page
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the URL for the previous page or +nil+ if the current page is the
|
105
|
+
# first.
|
106
|
+
def prev_url
|
107
|
+
prev_page ? url(prev_page) : nil
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the total number of records in the dataset.
|
111
|
+
def record_count
|
112
|
+
@dataset.pagination_record_count
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the URL for the specified page number.
|
116
|
+
def url(page)
|
117
|
+
@url.to_s.gsub('__page__', page.to_i.to_s)
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
module Thoth; module Helper
|
124
|
+
module Pagination
|
125
|
+
|
126
|
+
def pager(dataset, url = rs(:/, '__page__'))
|
127
|
+
Pager.new(dataset, url)
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end; end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth; module Helper
|
30
|
+
|
31
|
+
module Wiki
|
32
|
+
private
|
33
|
+
|
34
|
+
# Parse wiki-style markup into HTML markup.
|
35
|
+
def wiki_to_html(string)
|
36
|
+
# [[page_name|link text]]
|
37
|
+
string.gsub!(/\[\[([0-9a-z_-]+)\|(.+?)\]\]/i) do
|
38
|
+
PageController.a($2, :/, $1.downcase)
|
39
|
+
end
|
40
|
+
|
41
|
+
# [[page_name]]
|
42
|
+
string.gsub!(/\[\[([0-9a-z_-]+)\]\]/i) do
|
43
|
+
PageController.a($1, :/, $1.downcase)
|
44
|
+
end
|
45
|
+
|
46
|
+
# [[@post_name|link text]]
|
47
|
+
# [[@123|link text]]
|
48
|
+
string.gsub!(/\[\[@(\d+|[0-9a-z_-]+)\|(.+?)\]\]/i) do
|
49
|
+
PostController.a($2, :/, $1.downcase)
|
50
|
+
end
|
51
|
+
|
52
|
+
# [[@post_name]]
|
53
|
+
# [[@123]]
|
54
|
+
string.gsub!(/\[\[@(\d+|[0-9a-z_-]+)\]\]/i) do
|
55
|
+
PostController.a($1, :/, $1.downcase)
|
56
|
+
end
|
57
|
+
|
58
|
+
# [[media:filename|link text]]
|
59
|
+
string.gsub!(/\[\[media:([^\]]+)\|(.+?)\]\]/i) do
|
60
|
+
MediaController.a($2, :/, $1)
|
61
|
+
end
|
62
|
+
|
63
|
+
# [[media:filename]]
|
64
|
+
string.gsub!(/\[\[media:([^\]]+)\]\]/i) do
|
65
|
+
MediaController.a($1, :/, $1)
|
66
|
+
end
|
67
|
+
|
68
|
+
# [[media_url:filename]]
|
69
|
+
string.gsub!(/\[\[media_url:([^\]]+)\]\]/i) do
|
70
|
+
MediaController.r(:/, $1).to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
string
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end; end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
require 'cgi'
|
30
|
+
require 'json'
|
31
|
+
require 'open-uri'
|
32
|
+
|
33
|
+
module Thoth; module Helper
|
34
|
+
|
35
|
+
# The YSearch helper provides search results using the Yahoo! Search API.
|
36
|
+
# Requires the json or json_pure gem.
|
37
|
+
module Ysearch
|
38
|
+
class SearchError < Thoth::Error; end
|
39
|
+
|
40
|
+
# Yahoo! Developer API key. Feel free to replace this with your own key.
|
41
|
+
API_ID = 'pNi6xQDV34FbvnO3QRfWKSByhmPFG.3fVS_R2KzOhMek3szHWKNBrTsdi1mob2vZgKjLoLuZ4A--'
|
42
|
+
|
43
|
+
# Yahoo! Search API URL.
|
44
|
+
API_URL = 'http://search.yahooapis.com/WebSearchService/V1/webSearch'
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Performs a web search using the Yahoo! Search API and returns the results
|
49
|
+
# as a Hash. For details on the available options, see
|
50
|
+
# http://developer.yahoo.com/search/web/V1/webSearch.html
|
51
|
+
def yahoo_search(query, options = {})
|
52
|
+
options = {:format => 'html'}.merge(options).collect{|key, val|
|
53
|
+
"#{key.to_s}=#{::CGI.escape(val.to_s)}"}.join('&')
|
54
|
+
|
55
|
+
request = "#{API_URL}?appid=#{API_ID}&query=#{::CGI.escape(query)}&" +
|
56
|
+
options + '&output=json'
|
57
|
+
|
58
|
+
r = JSON.parse(open(request).read)['ResultSet']
|
59
|
+
|
60
|
+
# Parse the response into a more Rubyish format.
|
61
|
+
data = {
|
62
|
+
:available => r['totalResultsAvailable'],
|
63
|
+
:end => r['totalResultsReturned'] + r['firstResultPosition'] - 1,
|
64
|
+
:results => [],
|
65
|
+
:start => r['firstResultPosition'],
|
66
|
+
:returned => r['totalResultsReturned']
|
67
|
+
}
|
68
|
+
|
69
|
+
r['Result'].each do |result|
|
70
|
+
data[:results] << {
|
71
|
+
:cache_size => result['Cache'] ? result['Cache']['Size'].to_i : 0,
|
72
|
+
:cache_url => result['Cache'] ? result['Cache']['Url'] : '',
|
73
|
+
:click_url => result['ClickUrl'],
|
74
|
+
:mime => result['MimeType'],
|
75
|
+
:modified => Time.at(result['ModificationDate']),
|
76
|
+
:summary => result['Summary'],
|
77
|
+
:title => result['Title'],
|
78
|
+
:url => result['Url']
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
return data
|
83
|
+
|
84
|
+
rescue => e
|
85
|
+
raise SearchError, "Unable to retrieve search results: #{e}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end; end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#
|
2
|
+
# Pants -> Thoth importer.
|
3
|
+
#
|
4
|
+
|
5
|
+
class PantsImporter < Thoth::Importer
|
6
|
+
|
7
|
+
before_import do
|
8
|
+
unless uri = ARGV.shift
|
9
|
+
puts "Please enter a connection string for the Pants database you want to import."
|
10
|
+
puts "Example: mysql://user:pass@localhost/dbname"
|
11
|
+
print "> "
|
12
|
+
|
13
|
+
uri = STDIN.gets.strip
|
14
|
+
puts
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
@pants = Sequel.connect(uri)
|
19
|
+
rescue => e
|
20
|
+
abort("Error: unable to connect to database: #{e}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
import_comments do
|
25
|
+
@pants[:comments].each do |row|
|
26
|
+
Thoth::Comment.create do |comment|
|
27
|
+
comment.id = row[:id]
|
28
|
+
comment.author = row[:author]
|
29
|
+
comment.author_url = row[:url]
|
30
|
+
comment.title = row[:title]
|
31
|
+
comment.body = row[:content]
|
32
|
+
comment.created_at = row[:posted]
|
33
|
+
comment.updated_at = row[:posted]
|
34
|
+
comment.post_id = row[:article_id]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
import_pages do
|
40
|
+
@pants[:pages].each do |row|
|
41
|
+
Thoth::Page.create do |page|
|
42
|
+
page.id = row[:id]
|
43
|
+
page.title = row[:title]
|
44
|
+
page.name = row[:name]
|
45
|
+
page.body = row[:content]
|
46
|
+
page.created_at = row[:posted]
|
47
|
+
page.updated_at = row[:modified]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
import_posts do
|
53
|
+
@pants[:articles].each do |row|
|
54
|
+
Thoth::Post.create do |post|
|
55
|
+
post.id = row[:id]
|
56
|
+
post.title = row[:title]
|
57
|
+
post.body = row[:content]
|
58
|
+
post.created_at = row[:posted]
|
59
|
+
post.updated_at = row[:modified]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
import_tags do
|
65
|
+
@pants[:tags].each do |tag|
|
66
|
+
Thoth.db[:tags] << {
|
67
|
+
:id => tag[:id],
|
68
|
+
:name => tag[:name].downcase
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
@pants[:tags_articles_map].each do |tagmap|
|
73
|
+
Thoth.db[:tags_posts_map] << {
|
74
|
+
:id => tagmap[:id],
|
75
|
+
:tag_id => tagmap[:tag_id],
|
76
|
+
:post_id => tagmap[:article_id]
|
77
|
+
}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# Poseidon 0.3 -> Thoth importer.
|
3
|
+
#
|
4
|
+
|
5
|
+
class PoseidonImporter < Thoth::Importer
|
6
|
+
|
7
|
+
before_import do
|
8
|
+
unless uri = ARGV.shift
|
9
|
+
puts "Please enter a connection string for the Poseidon database you want to import."
|
10
|
+
puts "Example: mysql://user:pass@localhost/dbname"
|
11
|
+
print "> "
|
12
|
+
|
13
|
+
uri = STDIN.gets.strip
|
14
|
+
puts
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
@poseidon = Sequel.connect(uri)
|
19
|
+
rescue => e
|
20
|
+
abort("Error: unable to connect to database: #{e}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
import_comments do
|
25
|
+
@poseidon[:comments].all do |row|
|
26
|
+
user = @poseidon[:users].filter(:id => row[:userid]).first
|
27
|
+
|
28
|
+
Thoth::Comment.create do |comment|
|
29
|
+
comment.id = row[:id]
|
30
|
+
comment.author = user[:username]
|
31
|
+
comment.author_url = ''
|
32
|
+
comment.title = row[:title]
|
33
|
+
comment.body = row[:content]
|
34
|
+
comment.created_at = Time.at(row[:posted])
|
35
|
+
comment.updated_at = Time.at(row[:posted])
|
36
|
+
comment.ip = row[:ip]
|
37
|
+
comment.post_id = row[:contentid]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
import_posts do
|
43
|
+
@poseidon[:content].each do |row|
|
44
|
+
Thoth::Post.create do |post|
|
45
|
+
post.id = row[:id]
|
46
|
+
post.title = row[:title]
|
47
|
+
post.body = row[:content]
|
48
|
+
post.created_at = Time.at(row[:posted])
|
49
|
+
post.updated_at = Time.at(row[:posted])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|