rethoth 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +26 -0
  3. data/bin/thoth +233 -0
  4. data/lib/proto/config.ru +45 -0
  5. data/lib/proto/thoth.conf.sample +206 -0
  6. data/lib/thoth/cache.rb +53 -0
  7. data/lib/thoth/config.rb +158 -0
  8. data/lib/thoth/controller/admin.rb +75 -0
  9. data/lib/thoth/controller/api/comment.rb +73 -0
  10. data/lib/thoth/controller/api/page.rb +134 -0
  11. data/lib/thoth/controller/api/post.rb +122 -0
  12. data/lib/thoth/controller/api/tag.rb +59 -0
  13. data/lib/thoth/controller/archive.rb +50 -0
  14. data/lib/thoth/controller/comment.rb +173 -0
  15. data/lib/thoth/controller/main.rb +193 -0
  16. data/lib/thoth/controller/media.rb +172 -0
  17. data/lib/thoth/controller/page.rb +167 -0
  18. data/lib/thoth/controller/post.rb +310 -0
  19. data/lib/thoth/controller/search.rb +86 -0
  20. data/lib/thoth/controller/tag.rb +107 -0
  21. data/lib/thoth/controller.rb +48 -0
  22. data/lib/thoth/errors.rb +35 -0
  23. data/lib/thoth/helper/admin.rb +86 -0
  24. data/lib/thoth/helper/cookie.rb +45 -0
  25. data/lib/thoth/helper/error.rb +122 -0
  26. data/lib/thoth/helper/pagination.rb +131 -0
  27. data/lib/thoth/helper/wiki.rb +77 -0
  28. data/lib/thoth/helper/ysearch.rb +89 -0
  29. data/lib/thoth/importer/pants.rb +81 -0
  30. data/lib/thoth/importer/poseidon.rb +54 -0
  31. data/lib/thoth/importer/thoth.rb +103 -0
  32. data/lib/thoth/importer.rb +131 -0
  33. data/lib/thoth/layout/default.rhtml +47 -0
  34. data/lib/thoth/middleware/minify.rb +82 -0
  35. data/lib/thoth/migrate/001_create_schema.rb +108 -0
  36. data/lib/thoth/migrate/002_add_media_size.rb +37 -0
  37. data/lib/thoth/migrate/003_add_post_draft.rb +38 -0
  38. data/lib/thoth/migrate/004_add_comment_email.rb +37 -0
  39. data/lib/thoth/migrate/005_add_page_position.rb +37 -0
  40. data/lib/thoth/migrate/006_add_comment_close_delete.rb +43 -0
  41. data/lib/thoth/migrate/007_add_comment_summary.rb +37 -0
  42. data/lib/thoth/model/comment.rb +216 -0
  43. data/lib/thoth/model/media.rb +87 -0
  44. data/lib/thoth/model/page.rb +204 -0
  45. data/lib/thoth/model/post.rb +262 -0
  46. data/lib/thoth/model/tag.rb +80 -0
  47. data/lib/thoth/model/tags_posts_map.rb +34 -0
  48. data/lib/thoth/monkeypatch/sequel/model/errors.rb +37 -0
  49. data/lib/thoth/plugin/thoth_delicious.rb +105 -0
  50. data/lib/thoth/plugin/thoth_flickr.rb +86 -0
  51. data/lib/thoth/plugin/thoth_pinboard.rb +98 -0
  52. data/lib/thoth/plugin/thoth_tags.rb +68 -0
  53. data/lib/thoth/plugin/thoth_twitter.rb +175 -0
  54. data/lib/thoth/plugin.rb +59 -0
  55. data/lib/thoth/public/css/admin.css +223 -0
  56. data/lib/thoth/public/css/thoth.css +592 -0
  57. data/lib/thoth/public/images/admin-sprite.png +0 -0
  58. data/lib/thoth/public/images/thoth-sprite.png +0 -0
  59. data/lib/thoth/public/js/admin/comments.js +116 -0
  60. data/lib/thoth/public/js/admin/name.js +244 -0
  61. data/lib/thoth/public/js/admin/tagcomplete.js +332 -0
  62. data/lib/thoth/public/js/lazyload-min.js +4 -0
  63. data/lib/thoth/public/js/thoth.js +203 -0
  64. data/lib/thoth/public/robots.txt +5 -0
  65. data/lib/thoth/version.rb +37 -0
  66. data/lib/thoth/view/admin/index.rhtml +1 -0
  67. data/lib/thoth/view/admin/login.rhtml +23 -0
  68. data/lib/thoth/view/admin/toolbar.rhtml +117 -0
  69. data/lib/thoth/view/admin/welcome.rhtml +58 -0
  70. data/lib/thoth/view/archive/index.rhtml +24 -0
  71. data/lib/thoth/view/comment/comment.rhtml +47 -0
  72. data/lib/thoth/view/comment/delete.rhtml +15 -0
  73. data/lib/thoth/view/comment/form.rhtml +81 -0
  74. data/lib/thoth/view/comment/index.rhtml +68 -0
  75. data/lib/thoth/view/comment/list.rhtml +48 -0
  76. data/lib/thoth/view/media/delete.rhtml +15 -0
  77. data/lib/thoth/view/media/edit.rhtml +12 -0
  78. data/lib/thoth/view/media/form.rhtml +7 -0
  79. data/lib/thoth/view/media/list.rhtml +35 -0
  80. data/lib/thoth/view/media/media.rhtml +44 -0
  81. data/lib/thoth/view/media/new.rhtml +7 -0
  82. data/lib/thoth/view/page/delete.rhtml +15 -0
  83. data/lib/thoth/view/page/edit.rhtml +15 -0
  84. data/lib/thoth/view/page/form.rhtml +57 -0
  85. data/lib/thoth/view/page/index.rhtml +9 -0
  86. data/lib/thoth/view/page/list.rhtml +49 -0
  87. data/lib/thoth/view/page/new.rhtml +15 -0
  88. data/lib/thoth/view/post/comments.rhtml +12 -0
  89. data/lib/thoth/view/post/compact.rhtml +48 -0
  90. data/lib/thoth/view/post/delete.rhtml +15 -0
  91. data/lib/thoth/view/post/edit.rhtml +15 -0
  92. data/lib/thoth/view/post/form.rhtml +83 -0
  93. data/lib/thoth/view/post/index.rhtml +48 -0
  94. data/lib/thoth/view/post/list.rhtml +61 -0
  95. data/lib/thoth/view/post/new.rhtml +15 -0
  96. data/lib/thoth/view/post/tiny.rhtml +4 -0
  97. data/lib/thoth/view/search/index.rhtml +45 -0
  98. data/lib/thoth/view/tag/index.rhtml +34 -0
  99. data/lib/thoth/view/thoth/css.rhtml +9 -0
  100. data/lib/thoth/view/thoth/footer.rhtml +15 -0
  101. data/lib/thoth/view/thoth/header.rhtml +23 -0
  102. data/lib/thoth/view/thoth/index.rhtml +11 -0
  103. data/lib/thoth/view/thoth/js.rhtml +6 -0
  104. data/lib/thoth/view/thoth/sidebar.rhtml +38 -0
  105. data/lib/thoth/view/thoth/util/pager.rhtml +23 -0
  106. data/lib/thoth/view/thoth/util/simple_pager.rhtml +15 -0
  107. data/lib/thoth/view/thoth/util/table_sortheader.rhtml +20 -0
  108. data/lib/thoth.rb +394 -0
  109. metadata +409 -0
@@ -0,0 +1,98 @@
1
+ #--
2
+ # Copyright (c) 2010 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
+ require 'timeout'
33
+
34
+ module Thoth; module Plugin
35
+
36
+ # Pinboard plugin for Thoth.
37
+ module Pinboard
38
+ FEED_URL = 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20rss%20where%20url%3D%22http%3A%2F%2Ffeeds.pinboard.in%2Frss%2Fu%3A{username}%22%20limit%20{limit}&format=json'
39
+
40
+ Config << {
41
+ 'pinboard' => {
42
+
43
+ # Time in seconds to cache results.
44
+ 'cache_ttl' => 900,
45
+
46
+ # Request timeout in seconds.
47
+ 'request_timeout' => 5
48
+
49
+ }
50
+ }
51
+
52
+ class << self
53
+
54
+ # Gets recent Pinboard bookmarks for the specified _username_. The
55
+ # return value of this method is cached to improve performance.
56
+ #
57
+ # Available options:
58
+ # [<tt>:count</tt>] Number of bookmarks to return (default is 5)
59
+ #
60
+ def recent_bookmarks(username, options = {})
61
+ cache = Ramaze::Cache.plugin
62
+ options = {:count => 5}.merge(options)
63
+ request = FEED_URL.gsub('{username}', ::CGI.escape(username)).
64
+ gsub('{limit}', options[:count].to_s)
65
+
66
+ if value = cache[request]
67
+ return value
68
+ end
69
+
70
+ response = []
71
+
72
+ Timeout.timeout(Config.pinboard['request_timeout'], StandardError) do
73
+ response = JSON.parse(open(request).read)
74
+ end
75
+
76
+ # Parse the response into a more friendly format.
77
+ data = []
78
+
79
+ response['query']['results']['item'].each do |item|
80
+ data << {
81
+ :url => item['link'],
82
+ :title => item['title'].strip,
83
+ :note => (item['description'] || '').strip,
84
+ :tags => (item['subject'] || '').strip.split(' ')
85
+ }
86
+ end
87
+
88
+ return cache.store(request, data, :ttl => Config.pinboard['cache_ttl'])
89
+
90
+ rescue => e
91
+ Ramaze::Log.error "Thoth::Plugin::Pinboard: #{e.message}"
92
+ return []
93
+ end
94
+
95
+ end
96
+ end
97
+
98
+ end; end
@@ -0,0 +1,68 @@
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 Plugin
30
+
31
+ # Tags plugin for Thoth.
32
+ module Tags
33
+
34
+ Config << {
35
+ 'tags' => {
36
+
37
+ # Time in seconds to cache tag data. It's a good idea to keep this nice
38
+ # and high to improve the performance of your site. Default is 1800
39
+ # seconds (30 minutes).
40
+ 'cache_ttl' => 1800
41
+
42
+ }
43
+ }
44
+
45
+ class << self
46
+
47
+ # Gets an Array of the most heavily-used tags. The first element of the
48
+ # array is a Tag object, the second element is the number of times it's
49
+ # used.
50
+ def top_tags(limit = 10)
51
+ cache = Ramaze::Cache.plugin
52
+
53
+ if tags = cache["top_tags_#{limit}"]
54
+ return tags
55
+ end
56
+
57
+ tags = []
58
+ tag_ids = TagsPostsMap.group_and_count(:tag_id).reverse_order(:count).
59
+ limit(limit)
60
+
61
+ tag_ids.all {|row| tags << [Tag[row[:tag_id]], row[:count]] }
62
+ cache.store("top_tags_#{limit}", tags, :ttl => Config.tags['cache_ttl'])
63
+ end
64
+
65
+ end
66
+ end
67
+
68
+ end; end
@@ -0,0 +1,175 @@
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
+ require 'timeout'
33
+ require 'uri'
34
+
35
+ module Thoth; module Plugin
36
+
37
+ # Twitter plugin for Thoth.
38
+ module Twitter
39
+
40
+ Config << {
41
+ 'twitter' => {
42
+
43
+ # Whether or not to include replies. If this is false, the most recent
44
+ # non-reply tweets will be displayed.
45
+ 'include_replies' => false,
46
+
47
+ # Time in seconds to cache results. It's a good idea to keep this nice
48
+ # and high both to improve the performance of your site and to avoid
49
+ # pounding on Twitter's servers. Default is 600 seconds (10 minutes).
50
+ 'cache_ttl' => 600,
51
+
52
+ # Request timeout in seconds.
53
+ 'request_timeout' => 3,
54
+
55
+ # If Twitter fails to respond at least this many times in a row, no new
56
+ # requests will be sent until the failure_timeout expires in order to
57
+ # avoid hindering your blog's performance.
58
+ 'failure_threshold' => 3,
59
+
60
+ # After the failure_threshold is reached, the plugin will wait this many
61
+ # seconds before trying again. Default is 600 seconds (10 minutes).
62
+ 'failure_timeout' => 600
63
+
64
+ }
65
+ }
66
+
67
+ class << self
68
+
69
+ # Parses tweet text and converts it into HTML. Explicit URLs and @username
70
+ # or #hashtag references will be turned into links.
71
+ def parse_tweet(tweet)
72
+ index = 0
73
+ html = tweet.dup
74
+ protocols = ['ftp', 'ftps', 'git', 'http', 'https', 'mailto', 'scp',
75
+ 'sftp', 'ssh', 'telnet']
76
+ urls = []
77
+
78
+ # Extract URLs and replace them with placeholders for later.
79
+ URI.extract(html.dup, protocols) do |url|
80
+ html.sub!(url, "__URL#{index}__")
81
+ urls << url
82
+ index += 1
83
+ end
84
+
85
+ # Replace URL placeholders with links.
86
+ urls.each_with_index do |url, index|
87
+ html.sub!("__URL#{index}__", "<a href=\"#{url}\">" <<
88
+ "#{url.length > 26 ? url[0..26] + '...' : url}</a>")
89
+ end
90
+
91
+ # Turn @username into a link to the specified user's Twitter profile.
92
+ html.gsub!(/@([a-zA-Z0-9_]{1,16})([^a-zA-Z0-9_])?/,
93
+ '@<a href="http://twitter.com/\1">\1</a>\2')
94
+
95
+ # Turn #hashtags into links.
96
+ html.gsub!(/#([a-zA-Z0-9_]{1,32})([^a-zA-Z0-9_])?/,
97
+ '<a href="http://search.twitter.com/search?q=%23\1">#\1</a>\2')
98
+
99
+ return html
100
+ end
101
+
102
+ # Gets a Hash containing recent tweets for the specified _user_. The only
103
+ # valid option currently is <code>:count</code>, which specifies the
104
+ # maximum number of tweets that should be returned.
105
+ def recent_tweets(user, options = {})
106
+ if @skip_until
107
+ return [] if @skip_until > Time.now
108
+ @skip_until = nil
109
+ end
110
+
111
+ cache = Ramaze::Cache.plugin
112
+ options = {:count => 5}.merge(options)
113
+ count = options[:count].to_i
114
+
115
+ count += 10 unless Config.twitter['include_replies']
116
+ count = 200 if count > 200
117
+
118
+ url = "http://twitter.com/statuses/user_timeline/#{user}.json?count=" <<
119
+ count.to_s
120
+
121
+ if value = cache[url]
122
+ return value
123
+ end
124
+
125
+ tweets = []
126
+
127
+ Timeout.timeout(Config.twitter['request_timeout'], StandardError) do
128
+ tweets = JSON.parse(open(url).read)
129
+ end
130
+
131
+ # Weed out replies if necessary.
132
+ unless Config.twitter['include_replies']
133
+ tweets.delete_if do |tweet|
134
+ !tweet['in_reply_to_status_id'].nil? ||
135
+ !tweet['in_reply_to_user_id'].nil?
136
+ end
137
+
138
+ tweets = tweets.slice(0, options[:count].to_i)
139
+ end
140
+
141
+ # Parse the tweets into an easier-to-use format.
142
+ tweets.map! do |tweet|
143
+ {
144
+ :created_at => Time.parse(tweet['created_at']),
145
+ :html => parse_tweet(tweet['text']),
146
+ :id => tweet['id'],
147
+ :source => tweet['source'],
148
+ :text => tweet['text'],
149
+ :truncated => tweet['truncated'],
150
+ :url => "http://twitter.com/#{user}/statuses/#{tweet['id']}"
151
+ }
152
+ end
153
+
154
+ @failures = 0
155
+
156
+ return cache.store(url, tweets, :ttl => Config.twitter['cache_ttl'])
157
+
158
+ rescue => e
159
+ Ramaze::Log.error "Thoth::Plugin::Twitter: #{e.message}"
160
+
161
+ @failures ||= 0
162
+ @failures += 1
163
+
164
+ if @failures >= Config.twitter['failure_threshold']
165
+ @skip_until = Time.now + Config.twitter['failure_timeout']
166
+ Ramaze::Log.error "Thoth::Plugin::Twitter: Twitter failed to respond #{@failures} times. Will retry after #{@skip_until}."
167
+ end
168
+
169
+ return []
170
+ end
171
+
172
+ end
173
+
174
+ end
175
+ end; end
@@ -0,0 +1,59 @@
1
+ #--
2
+ # Copyright (c) 2017 John Pagonis <john@pagonis.org>
3
+ # Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ # * Neither the name of this project nor the names of its contributors may be
15
+ # used to endorse or promote products derived from this software without
16
+ # specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ #++
29
+
30
+ module Thoth
31
+
32
+ # Namespace for Thoth plugins. See
33
+ # http://wiki.github.com/pagojo/rethoth/creating-plugins for more info on
34
+ # creating and using plugins.
35
+ module Plugin
36
+ def self.const_missing(name)
37
+ self.load(name)
38
+ self.const_get(name)
39
+ end
40
+
41
+ # Attempts to load the specified plugin, first from the project's
42
+ # <tt>/plugin</tt> directory, then from Thoth's and then as a gem.
43
+ def self.load(name)
44
+ plugin = "thoth_#{name.to_s.downcase.gsub(/^thoth_/, '')}"
45
+ files = Dir["{#{HOME_DIR}/plugin,#{LIB_DIR}/plugin," <<
46
+ "#{$:.join(',')}}/#{plugin}.rb"]
47
+
48
+ # First try to load a local copy of the plugin, then try the gem.
49
+ unless (files.any? && require(files.first)) || require(plugin)
50
+ raise LoadError, "Thoth::Plugin::#{name} not found"
51
+ end
52
+
53
+ Ramaze::Log.info "Loaded plugin: #{plugin}"
54
+
55
+ true
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,223 @@
1
+ /* -- Icons ----------------------------------------------------------------- */
2
+ .adminicon {
3
+ background: url(../images/admin-sprite.png) no-repeat;
4
+ display: -moz-inline-box;
5
+ display: inline-block;
6
+ height: 16px;
7
+ vertical-align: middle;
8
+ width: 16px;
9
+ }
10
+
11
+ .adminicon.comment-delete { background-position: -180px 0; }
12
+ .adminicon.comment-list { background-position: -196px 0; }
13
+ .adminicon.logout { background-position: -213px 0; }
14
+ .adminicon.media-delete { background-position: -147px 0; }
15
+ .adminicon.media-list { background-position: -164px 0; }
16
+ .adminicon.media-new { background-position: -130px 0; }
17
+ .adminicon.page-delete { background-position: -97px 0; }
18
+ .adminicon.page-edit { background-position: -81px 0; }
19
+ .adminicon.page-list { background-position: -113px 0; }
20
+ .adminicon.page-new { background-position: -65px 0; }
21
+ .adminicon.post-delete { background-position: -32px 0; }
22
+ .adminicon.post-edit { background-position: -16px 0; }
23
+ .adminicon.post-list { background-position: -48px 0; }
24
+
25
+ .adminicon.sort {
26
+ height: 5px;
27
+ width: 7px;
28
+ }
29
+
30
+ .adminicon.sort.asc { background-position: -230px 0; }
31
+ .adminicon.sort.desc { background-position: -230px -6px; }
32
+
33
+ /* -- Toolbar Login Form ---------------------------------------------------- */
34
+ #adminToolbar form {
35
+ float: right;
36
+ margin: 0;
37
+ }
38
+
39
+ #adminToolbar form div { display: inline; }
40
+
41
+ /* -- Toolbar Icons --------------------------------------------------------- */
42
+ .toolbar {
43
+ background: #f5f5f5;
44
+ border: 1px solid #dfdfdf;
45
+ padding: 3px 4px 4px 4px;
46
+ }
47
+
48
+ .toolbar ul {
49
+ float: left;
50
+ margin: 0;
51
+ padding: 0 6px;
52
+ }
53
+
54
+ .toolbar ul.edit { padding-left: 0; }
55
+ .toolbar ul.tools { border-left: 1px solid #dfdfdf; }
56
+
57
+ .toolbar ul:after {
58
+ clear: left;
59
+ content: '.';
60
+ display: block;
61
+ height: 0;
62
+ visibility: hidden;
63
+ }
64
+
65
+ .toolbar ul li {
66
+ float: left;
67
+ list-style: none;
68
+ margin-left: 1px;
69
+ }
70
+
71
+ .toolbar ul li:first-child { margin-left: 0; }
72
+
73
+ .toolbar a {
74
+ border: 1px solid transparent;
75
+ cursor: pointer;
76
+ display: block;
77
+ padding: 3px;
78
+ }
79
+
80
+ .toolbar a:hover {
81
+ background: #dfebff;
82
+ border: 1px solid #0A46AF;
83
+ }
84
+
85
+ .toolbar a img {
86
+ border: 0;
87
+ height: 16px;
88
+ width: 16px;
89
+ }
90
+
91
+ @media print {
92
+ .toolbar { display: none; }
93
+ }
94
+
95
+ /* -- Mini-Toolbar ---------------------------------------------------------- */
96
+ .toolbar.mini {
97
+ background: none;
98
+ border: 0;
99
+ padding: 0;
100
+ }
101
+
102
+ /* -- Comment Mini-Toolbar -------------------------------------------------- */
103
+ .comment { position: relative; }
104
+
105
+ .comment .toolbar {
106
+ position: absolute;
107
+ right: -3px;
108
+ top: 3px;
109
+ }
110
+
111
+ /* -- Misc. Forms ----------------------------------------------------------- */
112
+ fieldset.default {
113
+ border: 0;
114
+ padding: 0;
115
+ }
116
+
117
+ form div.field { margin-bottom: 1em; }
118
+ form div.field label {
119
+ display: block;
120
+ font-weight: bold;
121
+ }
122
+
123
+ form p.buttons { margin: 0.5em 0 1em; }
124
+
125
+ ol.suggested-tags {
126
+ margin: 0.5em 0;
127
+ padding: 0;
128
+ }
129
+
130
+ ol.suggested-tags li {
131
+ float: left;
132
+ list-style: none;
133
+ margin-right: 0.3em;
134
+ }
135
+
136
+ ol.suggested-tags li:after { content: ', '; }
137
+ ol.suggested-tags li:last-child:after { content: ''; }
138
+ ol.suggested-tags li a { white-space: nowrap; }
139
+
140
+ #page-form,
141
+ #post-form { margin-bottom: 2em; }
142
+
143
+ #page-form #body,
144
+ #page-form #title,
145
+ #post-form #body,
146
+ #post-form #title,
147
+ #post-form #tags { width: 99%; }
148
+
149
+ #page-form #name,
150
+ #post-form #name { width: 15em; }
151
+
152
+ .tips {
153
+ background: #eff7ff;
154
+ border: 1px solid #afd4ff;
155
+ margin-left: 0;
156
+ padding: 0.8em;
157
+ padding-left: 1.8em;
158
+ }
159
+
160
+ .tips li { margin-bottom: 0.5em; }
161
+
162
+ .tips kbd {
163
+ background: #f7f1d8;
164
+ border: 1px solid #efdb7f;
165
+ font-size: 11px;
166
+ padding: 0 3px 1px;
167
+ white-space: nowrap;
168
+ }
169
+
170
+ /* -- Lists ----------------------------------------------------------------- */
171
+ table.list {
172
+ border: 1px solid #dfdfdf;
173
+ width: 100%;
174
+ }
175
+
176
+ table.list th,
177
+ table.list td { padding: 1px 2px; }
178
+
179
+ table.list thead th {
180
+ font-weight: bold;
181
+ text-align: left;
182
+ white-space: nowrap;
183
+ }
184
+
185
+ table.list thead tr { background: #dfeeff; }
186
+ table.list tbody tr.empty { font-style: italic; }
187
+ table.list tbody tr.even { background: #f7fbff; }
188
+ table.list tbody tr.odd { background: none; }
189
+ table.list tbody tr:hover { background: #d0dbf7; }
190
+
191
+ table.list tbody td { border: 1px solid transparent; }
192
+ table.list tbody tr:hover td { border: 1px solid #9ab3f7; }
193
+
194
+ table.list td.created,
195
+ table.list td.updated,
196
+ table.pages td.name { white-space: nowrap; }
197
+
198
+ table.media td.size { text-align: right; }
199
+
200
+ /* -- Media ----------------------------------------------------------------- */
201
+ fieldset.replace { padding: 0.3em 1em; }
202
+
203
+ table.details th {
204
+ font-weight: bold;
205
+ padding-right: 4px;
206
+ text-align: right;
207
+ }
208
+
209
+ table.details.media tr.filename td,
210
+ table.details.media tr.path td {
211
+ font-family: Menlo, 'Bitstream Vera Sans Mono', Consolas, Monaco, 'Courier New', monospaced;
212
+ }
213
+
214
+ /* -- Welcome Page ---------------------------------------------------------- */
215
+ .welcome .version {
216
+ color: #666;
217
+ font-size: 12px;
218
+ float: right;
219
+ }
220
+
221
+ .welcome dl.customizing { margin-left: 2ex; }
222
+ .welcome dl.customizing dt { font-weight: bold; }
223
+ .welcome dl.customizing dd { margin: 0 0 1em 0; }