octopod-exe 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +8 -0
  3. data/Rakefile +11 -0
  4. data/assets/_config.yml.sample +48 -0
  5. data/assets/_includes/disqus_count.html +13 -0
  6. data/assets/_includes/disqus_thread.html +13 -0
  7. data/assets/_includes/flattr_loader.html +14 -0
  8. data/assets/_includes/isso_thread.html +6 -0
  9. data/assets/_includes/post.html +20 -0
  10. data/assets/_includes/post_header.html +17 -0
  11. data/assets/_includes/post_line.html +3 -0
  12. data/assets/_includes/sidebar.html +109 -0
  13. data/assets/_includes/tweet_us.html +3 -0
  14. data/assets/_layouts/default.html +86 -0
  15. data/assets/_layouts/feed.xml +107 -0
  16. data/assets/_layouts/jsonfeed.json +48 -0
  17. data/assets/_layouts/page.html +15 -0
  18. data/assets/_layouts/player_index.html +36 -0
  19. data/assets/_layouts/post.html +10 -0
  20. data/assets/_layouts/with_twitter_card.html +98 -0
  21. data/assets/_posts/2016-03-22-episode0.md +24 -0
  22. data/assets/_sass/_overrides.scss +68 -0
  23. data/assets/apple-touch-icon-precomposed.png +0 -0
  24. data/assets/episodes.m4a.rss +5 -0
  25. data/assets/episodes.mp3.rss +5 -0
  26. data/assets/episodes.ogg.rss +5 -0
  27. data/assets/episodes/episode0.m4a +0 -0
  28. data/assets/episodes/episode0.mp3 +0 -0
  29. data/assets/episodes/episode0.ogg +0 -0
  30. data/assets/favicon.ico +0 -0
  31. data/assets/feed.m4a.json +5 -0
  32. data/assets/feed.mp3.json +5 -0
  33. data/assets/feed.ogg.json +5 -0
  34. data/assets/general_feed.xml +30 -0
  35. data/assets/img/favicon.ico +0 -0
  36. data/assets/img/logo-360x360.png +0 -0
  37. data/assets/img/logo-itunes.jpg +0 -0
  38. data/assets/img/logo.jpg +0 -0
  39. data/assets/img/logo/android-icon-144x144.png +0 -0
  40. data/assets/img/logo/android-icon-192x192.png +0 -0
  41. data/assets/img/logo/android-icon-36x36.png +0 -0
  42. data/assets/img/logo/android-icon-48x48.png +0 -0
  43. data/assets/img/logo/android-icon-72x72.png +0 -0
  44. data/assets/img/logo/android-icon-96x96.png +0 -0
  45. data/assets/img/logo/apple-icon-114x114.png +0 -0
  46. data/assets/img/logo/apple-icon-120x120.png +0 -0
  47. data/assets/img/logo/apple-icon-144x144.png +0 -0
  48. data/assets/img/logo/apple-icon-152x152.png +0 -0
  49. data/assets/img/logo/apple-icon-180x180.png +0 -0
  50. data/assets/img/logo/apple-icon-57x57.png +0 -0
  51. data/assets/img/logo/apple-icon-60x60.png +0 -0
  52. data/assets/img/logo/apple-icon-72x72.png +0 -0
  53. data/assets/img/logo/apple-icon-76x76.png +0 -0
  54. data/assets/img/logo/apple-icon-precomposed.png +0 -0
  55. data/assets/img/logo/apple-icon.png +0 -0
  56. data/assets/img/logo/browserconfig.xml +2 -0
  57. data/assets/img/logo/favicon-16x16.png +0 -0
  58. data/assets/img/logo/favicon-32x32.png +0 -0
  59. data/assets/img/logo/favicon-96x96.png +0 -0
  60. data/assets/img/logo/favicon.ico +0 -0
  61. data/assets/img/logo/manifest.json +41 -0
  62. data/assets/img/logo/ms-icon-144x144.png +0 -0
  63. data/assets/img/logo/ms-icon-150x150.png +0 -0
  64. data/assets/img/logo/ms-icon-310x310.png +0 -0
  65. data/assets/img/logo/ms-icon-70x70.png +0 -0
  66. data/assets/imprint.md +19 -0
  67. data/assets/index.md +14 -0
  68. data/bin/octopod +273 -0
  69. data/lib/jekyll-octopod.rb +11 -0
  70. data/lib/jekyll/date_de.rb +54 -0
  71. data/lib/jekyll/flattr_filters.rb +107 -0
  72. data/lib/jekyll/octopod_filters.rb +336 -0
  73. data/lib/jekyll/paged_feed_page.rb +22 -0
  74. data/lib/jekyll/paged_feed_page_generator.rb +20 -0
  75. data/lib/jekyll/podcast_player_page.rb +24 -0
  76. data/lib/jekyll/podcast_player_page_generator.rb +14 -0
  77. data/lib/jekyll/podigee_player_tag.rb +44 -0
  78. data/lib/jekyll/static_file.rb +20 -0
  79. data/lib/jekyll/update_config.rb +14 -0
  80. data/lib/octopod/version.rb +11 -0
  81. metadata +580 -0
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "App",
3
+ "icons": [
4
+ {
5
+ "src": "\/android-icon-36x36.png",
6
+ "sizes": "36x36",
7
+ "type": "image\/png",
8
+ "density": "0.75"
9
+ },
10
+ {
11
+ "src": "\/android-icon-48x48.png",
12
+ "sizes": "48x48",
13
+ "type": "image\/png",
14
+ "density": "1.0"
15
+ },
16
+ {
17
+ "src": "\/android-icon-72x72.png",
18
+ "sizes": "72x72",
19
+ "type": "image\/png",
20
+ "density": "1.5"
21
+ },
22
+ {
23
+ "src": "\/android-icon-96x96.png",
24
+ "sizes": "96x96",
25
+ "type": "image\/png",
26
+ "density": "2.0"
27
+ },
28
+ {
29
+ "src": "\/android-icon-144x144.png",
30
+ "sizes": "144x144",
31
+ "type": "image\/png",
32
+ "density": "3.0"
33
+ },
34
+ {
35
+ "src": "\/android-icon-192x192.png",
36
+ "sizes": "192x192",
37
+ "type": "image\/png",
38
+ "density": "4.0"
39
+ }
40
+ ]
41
+ }
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: Imprint
3
+ layout: default
4
+ navigation: 1
5
+ ---
6
+
7
+ # Media Owner and Content
8
+
9
+ ... put in information here ...
10
+
11
+ # Links
12
+
13
+ ... put in information here ...
14
+
15
+
16
+ # License
17
+
18
+ ... use cc by as below or put in information here ...
19
+ [![Creative Commons License](https://i.creativecommons.org/l/by/4.0/88x31.png)](http://creativecommons.org/licenses/by/4.0/)
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Episodes
3
+ layout: default
4
+ navigation: 0
5
+ ---
6
+ {% assign post = site.posts.first %}
7
+ {% include post.html %}
8
+
9
+ {% assign current_post = site.posts.first %}
10
+ {% for post in site.posts -%}
11
+ {% unless post.url == current_post.url -%}
12
+ {% include post_line.html %}
13
+ {% endunless %}
14
+ {% endfor %}
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env ruby
2
+ # require "byebug"
3
+ PWD = Dir.pwd
4
+
5
+ GEM_DIR = Gem::Specification.find_by_name("jekyll-octopod").gem_dir
6
+ # HAS20170501 disgusting hack for development
7
+ # GEM_DIR = "/home/user/jekyll/jekyll-octopod/"
8
+
9
+
10
+ require 'rubygems'
11
+ require 'optparse'
12
+ require 'yaml'
13
+ require 'fileutils'
14
+
15
+
16
+ octopod_help = <<HELP
17
+ Octopod - podcast publishing for geeks
18
+
19
+ Basic Command Line Usage:
20
+ Standard Jekyll commands:
21
+ octopod b[uild] # . -> ./_site
22
+ octopod build <path to write generated site> # . -> <path>
23
+ octopod build <path to source> <path to write generated site> # <path> -> <path>
24
+ octopod import <importer name> <options> # imports posts using named import script
25
+ octopod setup # Setup blog to become podcast-aware, copy assets and default config
26
+ octopod s[erver] # Starts the server
27
+
28
+ Additional Octopod commands:
29
+ octopod episode # adds a template for a new episode
30
+ octopod deploy # deploys your site
31
+
32
+ See 'octopod <command> --help' for more information on a specific command.
33
+
34
+ Configuration is read from '<source>/_config.yml' but can be overridden
35
+ using the following options:
36
+
37
+ HELP
38
+
39
+ episode_help = <<EPISODE_HELP
40
+ octopod episode - generates a template to post your next episode
41
+
42
+ octopod episode [options] [audio file[, audio file]]
43
+
44
+ Configuration is read from '<source>/_config.yml' but can be overridden
45
+ using the following options:
46
+
47
+ EPISODE_HELP
48
+
49
+ deploy_help = <<DEPLOY_HELP
50
+ octopod deploy - deploys website via rsync
51
+
52
+ octopod deploy [path to write generated site] [options]
53
+
54
+ Configuration is read from '<source>/_config.yml' but can be overridden
55
+ using the following options:
56
+
57
+ DEPLOY_HELP
58
+
59
+ DEFAULT_EXT = '.md'
60
+
61
+ class OptionParser
62
+ alias_method :_octopod_banner=, :banner=
63
+ def banner=(_)
64
+ return ''
65
+ end
66
+ end
67
+
68
+ def ok_failed(condition)
69
+ if (condition)
70
+ puts "OK"
71
+ else
72
+ puts "FAILED"
73
+ end
74
+ end
75
+
76
+ def write_file?(filename)
77
+ if File.exists?(filename)
78
+ unless ["Y","N"].include?(@answer)
79
+ puts ""
80
+ @answer = ask("File '#{filename}' already exists. Overwrite? Capitalized answer for ALL files.", ['y', 'Y', 'n', 'N'])
81
+ end
82
+ ["Y", "y"].include?(@answer)
83
+ else
84
+ true
85
+ end
86
+ end
87
+
88
+ def copy_file_or_create_dir(file)
89
+ filename = file.split(GEM_DIR + "/assets")[1]
90
+ if File.directory?(file)
91
+ FileUtils.mkdir(PWD + filename, {verbose: true}) unless File.exists?(PWD + filename)
92
+ else
93
+ if write_file?(PWD + filename)
94
+ FileUtils.cp(file, PWD + filename, {verbose: true})
95
+ end
96
+ end
97
+ end
98
+
99
+ def ask(message, valid_options = nil)
100
+ if valid_options
101
+ answer = get_stdin("#{message} #{valid_options.to_s.gsub(/"/, '').gsub(/, /,'/')} ") while !valid_options.include?(answer)
102
+ else
103
+ answer = get_stdin(message)
104
+ end
105
+ answer
106
+ end
107
+
108
+ def get_stdin(message)
109
+ print message
110
+ STDIN.gets.chomp
111
+ end
112
+
113
+ if ARGV.size > 0 && (ARGV[0] == 'episode' || ARGV[0] == 'deploy' || ARGV[0] == 'setup')
114
+ options = YAML.load_file(File.join(PWD, '_config.yml'))
115
+ options['posts_dir'] = File.join(PWD, '_posts')
116
+
117
+ case ARGV[0]
118
+
119
+ when 'episode'
120
+ post_header = {
121
+ 'title' => 'A Title',
122
+ 'subtitle' => "A Subtle Subtitle",
123
+ 'datum' => 'May 22nd, 2016',
124
+ 'layout' => 'post',
125
+ 'author' => options['author'],
126
+ 'explicit' => options['explicit'] || 'no',
127
+ 'duration' => "0:01:00",
128
+ 'audio' => {
129
+ 'm4a' => 'name.m4a',
130
+ 'mp3' => 'name.mp3',
131
+ 'ogg' => 'name.ogg'},
132
+ 'chapters' => [
133
+ '00:00:00.000 Intro.',
134
+ '00:00:30.000 Outro.'
135
+ ]
136
+ }
137
+
138
+ opts = OptionParser.new do |opts|
139
+ opts._octopod_banner = episode_help
140
+
141
+ opts.on("-a", "--author [AUTHOR]", "Name of post author") do |episode_author|
142
+ post_header['author'] = options['author'] = episode_author
143
+ end
144
+
145
+ opts.on("-c", "--chapters [chapter1,chapter2,...]", Array, "The episodes chapters.") do |episode_chapters|
146
+ warn episode_chapters.inspect
147
+ post_header['chapters'] = options['chapters'] = episode_chapters
148
+ end
149
+
150
+ opts.on("-d", "--duration [DURATION]", "Duration of the episode") do |episode_duration|
151
+ post_header['duration'] = options['duration'] = episode_duration.to_i
152
+ end
153
+
154
+ opts.on("-e", "--explicit [yes/no]", "Explicit rating for this episode (default: 'no')") do |episode_explicit|
155
+ post_header['explicit'] = options['explicit'] = episode_explicit
156
+ end
157
+
158
+ opts.on("--episode-cover [PATH]", "Path to the image that represents the episode.") do |episode_cover|
159
+ post_header['episode_cover'] = options['episode_cover'] = episode_cover
160
+ end
161
+
162
+ opts.on("-l", "--layout [LAYOUT]", "Layout to use (default: 'post')") do |episode_layout|
163
+ post_header['layout'] = options['layout'] = episode_layout
164
+ end
165
+
166
+ opts.on("-p", "--posts-dir [PATH]", "Path to the post directory (default: '_posts')") do |episode_posts_dir|
167
+ options['posts_dir'] = episode_posts_dir
168
+ end
169
+
170
+ opts.on("-s", "--subtitle [TEXT]", "Subtitle of the episode") do |episode_subtitle|
171
+ post_header['subtitle'] = options['subtitle'] = episode_subtitle
172
+ end
173
+
174
+ opts.on("--summary [TEXT]", "Summary of the episode") do |episode_summary|
175
+ post_header['summary'] = options['summary'] = episode_summary
176
+ end
177
+
178
+ opts.on("--tags [tag1,tag2,...]", Array, "Tags for the episode") do |episode_tags|
179
+ post_header['tags'] = options['tags'] = episode_tags
180
+ end
181
+
182
+ opts.on("-t", "--title [TEXT]", "Title of the episode") do |episode_title|
183
+ post_header['title'] = options['title'] = episode_title
184
+ end
185
+ end
186
+ opts.parse!
187
+
188
+ unless FileTest.directory?(options['posts_dir'])
189
+ abort("rake aborted: '#{options['posts_dir']}' directory not found.")
190
+ end
191
+
192
+ post_header['title'] = post_header['title'] || 'untitled'
193
+ slug = post_header['title'].downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '_')
194
+ date = Time.now.strftime('%Y-%m-%d')
195
+
196
+ filename = File.join(options['posts_dir'], "#{date}-#{slug}#{DEFAULT_EXT}")
197
+
198
+ abort() unless write_file?(filename)
199
+
200
+ open(filename, 'w') do |post|
201
+ post.puts post_header.to_yaml
202
+ post.puts '---'
203
+ post.puts "## {{ page.subtitle }}\n\n"
204
+ post.puts "{{ page | web_player_moderator:site }}\n\n"
205
+ post.puts "## Shownotes and Links\n\n* Note"
206
+ end
207
+
208
+ puts "Created new episode: #{filename}" if File.exists?(filename)
209
+
210
+ when 'deploy'
211
+ opts = OptionParser.new do |opts|
212
+ opts._octopod_banner = deploy_help
213
+
214
+ opts.on("--document-root [PATH]", "Path to the documwrite_fileent root on the remote machine") do |deploy_document_root|
215
+ options['document_root'] = deploy_document_root
216
+ end
217
+
218
+ opts.on("--rsync-delete", "Delete extraneous files from destination dir") do |deploy_rsync_delete|
219
+ options['rsync_delete'] = deploy_rsync_delete
220
+ end
221
+
222
+ opts.on("--ssh-host [USER@]<HOST>", "[User and] host of the destination machine") do |deploy_ssh_host|
223
+ options['ssh_host'] = deploy_ssh_host =~ /\A\w*@.*/ ? deploy_ssh_host : "#{ENV['USER']}@#{deploy_ssh_host}"
224
+ end
225
+
226
+ opts.on("--ssh-port [PORT]", "SSH port on the remote machine") do |deploy_ssh_port|
227
+ options['ssh_port'] = deploy_ssh_port.to_i
228
+ end
229
+ end
230
+ opts.parse!
231
+
232
+ options['public_dir'] = ARGV[1] ? ARGV[1] : File.join(PWD, '_site')
233
+ exclude = ""
234
+ if File.exists?('./rsync-exclude')
235
+ exclude = "--exclude-from '#{File.expand_path('./rsync-exclude')}'"
236
+ end
237
+ puts "## Deploying website via Rsync"
238
+
239
+ rsync_command = "rsync --progress -avze 'ssh -p #{options['ssh_port']}' #{exclude} \
240
+ #{"--delete" unless options['rsync_delete'] == false} \
241
+ #{options['public_dir']}/ #{options['ssh_host']}:#{options['document_root']}"
242
+
243
+ ok_failed system(rsync_command)
244
+
245
+ when 'setup'
246
+ unless File.exists?(PWD + '/_config.dist_backup.yml')
247
+ puts "", "===== Creating a backup of the configuration file ... ====="
248
+ FileUtils.cp(PWD + '/_config.yml', PWD + '/_config.dist_backup.yml', {verbose: true})
249
+ puts "===== ... done ===== ", ""
250
+ end
251
+
252
+
253
+ puts "", "If you are creating a brand new podcasting site, you can safely overwrite and answer with 'Y'."
254
+ puts "If this is an old site, it's better to answer with 'N'." , ""
255
+
256
+ puts "", "===== Copying assets ... ====="
257
+ Dir.glob(GEM_DIR + "/assets/**/*").each do |file|
258
+ copy_file_or_create_dir(file)
259
+ end
260
+
261
+ Dir.glob(GEM_DIR + "/assets/**/.*").each do |file|
262
+ copy_file_or_create_dir(file)
263
+ end
264
+
265
+ if write_file?(PWD + "/_config.yaml")
266
+ FileUtils.cp(GEM_DIR + "/assets/_config.yml.sample", PWD + "/_config.yml", {verbose: true})
267
+ end
268
+ puts "===== ... done ===== ", ""
269
+ end
270
+ else
271
+ puts octopod_help if ARGV.size > 0 && ARGV[0] == '--help'
272
+ load Gem.bin_path('jekyll', 'jekyll')
273
+ end
@@ -0,0 +1,11 @@
1
+ require "jekyll/flattr_filters"
2
+ require "jekyll/octopod_filters"
3
+ require "jekyll/paged_feed_page"
4
+ require "jekyll/paged_feed_page_generator"
5
+ require "jekyll/podcast_player_page"
6
+ require "jekyll/podcast_player_page_generator"
7
+ require "jekyll/update_config"
8
+ require "jekyll/static_file"
9
+ require "jekyll/podigee_player_tag"
10
+ require "jekyll/date_de"
11
+ require "octopod/version"
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+ require 'date'
3
+
4
+ # gem install facets
5
+ require 'facets/integer/ordinal'
6
+
7
+ module Jekyll
8
+ module DateDe
9
+ #Deutsche Lokalisation:
10
+ MONTHNAMES_DE = [nil,
11
+ "Januar", "Februar", "März", "April", "Mai", "Juni",
12
+ "Juli", "August", "September", "Oktober", "November", "Dezember" ]
13
+ ABBR_MONTHNAMES_DE = [nil,
14
+ "Jan", "Feb", "Mär", "Apr", "Mai", "Jun",
15
+ "Jul", "Aug", "Sep", "Okt", "Nov", "Dez" ]
16
+ DAYNAMES_DE = [
17
+ "Sonntag", "Montag", "Dienstag", "Mittwoch",
18
+ "Donnerstag", "Freitag", "Samstag" ]
19
+ ABBR_DAYNAMES_DE = [
20
+ "So", "Mo", "Di", "Mi",
21
+ "Do", "Fr", "Sa" ]
22
+
23
+ # Returns a datetime if the input is a string
24
+ def datetime(date)
25
+ if date.class == String
26
+ date = Time.parse(date)
27
+ end
28
+ date
29
+ end
30
+
31
+ # Formats date by given date format
32
+ def format_date(date, format)
33
+ date = datetime(date)
34
+ if format.nil? || format.empty? || format == "ordinal"
35
+ date_formatted = ordinalize(date)
36
+ else
37
+ format.gsub!(/%a/, ABBR_DAYNAMES_DE[date.wday])
38
+ format.gsub!(/%A/, DAYNAMES_DE[date.wday])
39
+ format.gsub!(/%b/, ABBR_MONTHNAMES_DE[date.mon])
40
+ format.gsub!(/%B/, MONTHNAMES_DE[date.mon])
41
+ date_formatted = date.strftime(format)
42
+ end
43
+ date_formatted
44
+ end
45
+
46
+ # Usage: {{ post.date | full_date_de }}
47
+ # Result: 13. Dezember 2017
48
+ def full_date_de(date)
49
+ format_date(date, "%d. %B %Y")
50
+ end
51
+ end
52
+ end
53
+
54
+ Liquid::Template.register_filter(Jekyll::DateDe)
@@ -0,0 +1,107 @@
1
+ require 'erb'
2
+
3
+ module Jekyll
4
+ module FlattrFilters
5
+ # Generates the query string part for the flattr load.js from the
6
+ # configurations in _config.yml
7
+ #
8
+ # {{ site | flattr_loader_options }}
9
+ def flattr_loader_options(site)
10
+ return if site['flattr_uid'].nil?
11
+ keys = %w[mode https popout uid button language category]
12
+ options = flattr_options(site, nil, keys).delete_if { |_, v| v.to_s.empty? }
13
+
14
+ options.map { |k, v| "#{k}=#{ERB::Util.url_encode(v)}" }.join('&')
15
+ end
16
+
17
+ # Returns a flattr button
18
+ #
19
+ # {{ site | flattr_button:page }}
20
+ def flattr_button(site, page = nil)
21
+ return if site['flattr_uid'].nil?
22
+
23
+ keys = %w[url title description uid popout button category language tags]
24
+ options = flattr_options(site, page, keys)
25
+
26
+ button = '<a class="FlattrButton" style="display:none;" '
27
+ button << %Q{title="#{options.delete('title')}" href="#{options.delete('url')}" }
28
+ button << options.map { |k, v|
29
+ %Q{data-flattr-#{k}="#{v}"} unless k == 'description'
30
+ }.join(' ')
31
+ button << ">\n\n#{options['description'].gsub(/<\/?[^>]*>/, "")}\n</a>"
32
+ end
33
+
34
+ # Returns a RSS payment link.
35
+ #
36
+ # {{ site | flattr_rss:post }}
37
+ def flattr_rss(site, page = nil)
38
+ return if site['flattr_uid'].nil?
39
+ link = '<atom:link rel="payment" href="https://flattr.com/submit/auto?'
40
+ link << %Q{#{flattr_feed_options(site, page)}" type="text/html" />}
41
+ end
42
+
43
+ # Returns a ATOM payment link.
44
+ #
45
+ # {{ site | flattr_atom:post }}
46
+ def flattr_atom(site, page = nil)
47
+ return if site['flattr_uid'].nil?
48
+ link = '<link rel="payment" href="https://flattr.com/submit/auto?'
49
+ link << %Q{#{flattr_feed_options(site, page)}" type="text/html" />}
50
+ end
51
+
52
+ # Removes all leading "flattr_" from the keys of the given hash.
53
+ #
54
+ # flattrize({ 'octopod' => 'awesome', 'flattr_uid' => 'pattex' })
55
+ # => { "octopod" => "awesome", "uid" => "pattex" }
56
+ def flattrize(hsh)
57
+ config = {}
58
+ hsh.to_hash.each { |k, v|
59
+ if new_key = k.to_s.match(/\Aflattr_(.*)\z/)
60
+ config[new_key[1]] = v
61
+ else
62
+ config[k] = v
63
+ end
64
+ }
65
+
66
+ config
67
+ end
68
+
69
+ def flattr_options(site, page, keys)
70
+ page = {} if page.nil?
71
+ site = flattrize(site)
72
+ page = flattrize(page)
73
+ options = {}
74
+
75
+ keys.each { |k|
76
+ case k
77
+ when 'https'
78
+ options[k] = 1
79
+ when 'url'
80
+ options[k] = "#{site['url']}#{page['url']}"
81
+ when 'description'
82
+ options[k] = page['content'] || site['description'] || site['title']
83
+ when 'category'
84
+ options[k] = page['category'] || site['category'] || 'audio'
85
+ when 'language'
86
+ options[k] = page['language'] || site['language'] || 'en_GB'
87
+ when 'tags'
88
+ options[k] = page['tags'].join(', ') if page['tags']
89
+ else
90
+ options[k] = page[k] || site[k]
91
+ end
92
+ }
93
+
94
+ options
95
+ end
96
+
97
+ def flattr_feed_options(site, page)
98
+ keys = %w[url uid]
99
+ options = flattr_options(site, page, keys).map { |k, v|
100
+ "#{k == 'uid' ? 'user_id' : k}=#{ERB::Util.url_encode(v)}"
101
+ }.join('&amp;')
102
+ end
103
+
104
+ end
105
+ end
106
+
107
+ Liquid::Template.register_filter(Jekyll::FlattrFilters)