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.
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; }