jekyll-octopod 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -1
- data/assets/_config.yml.sample +47 -0
- data/assets/_includes/disqus_count.html +13 -0
- data/assets/_includes/disqus_thread.html +13 -0
- data/assets/_includes/flattr_loader.html +14 -0
- data/assets/_includes/post.html +18 -0
- data/assets/_includes/post_header.html +7 -0
- data/assets/_includes/post_line.html +3 -0
- data/assets/_includes/sidebar.html +100 -0
- data/assets/_includes/tweet_us.html +3 -0
- data/assets/_layouts/default.html +87 -0
- data/assets/_layouts/feed.xml +66 -0
- data/assets/_layouts/page.html +15 -0
- data/assets/_layouts/player_index.html +40 -0
- data/assets/_layouts/post.html +10 -0
- data/assets/_plugins/flattr_filters.rb +108 -0
- data/assets/_plugins/octopod_filters.rb +399 -0
- data/assets/_plugins/podcast_player_page_generator.rb +35 -0
- data/assets/_plugins/site.rb +16 -0
- data/assets/_plugins/static_file.rb +30 -0
- data/assets/_posts/2016-03-22-episode0.md +26 -0
- data/assets/apple-touch-icon-precomposed.png +0 -0
- data/assets/css/bootflat.css +2557 -0
- data/assets/css/bootstrap.min.css +5 -0
- data/assets/css/custom_styles.css +7 -0
- data/assets/css/font-awesome.min.css +4 -0
- data/assets/episodes.m4a.rss +5 -0
- data/assets/episodes.mp3.rss +5 -0
- data/assets/episodes.ogg.rss +5 -0
- data/assets/episodes/episode0.m4a +0 -0
- data/assets/episodes/episode0.mp3 +0 -0
- data/assets/episodes/episode0.ogg +0 -0
- data/assets/favicon.ico +0 -0
- data/assets/fonts/FontAwesome.otf +0 -0
- data/assets/fonts/fontawesome-webfont.eot +0 -0
- data/assets/fonts/fontawesome-webfont.svg +655 -0
- data/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/assets/fonts/fontawesome-webfont.woff +0 -0
- data/assets/fonts/fontawesome-webfont.woff2 +0 -0
- data/assets/general_feed.xml +31 -0
- data/assets/img/favicon.ico +0 -0
- data/assets/img/glyphicons-halflings-white.png +0 -0
- data/assets/img/glyphicons-halflings.png +0 -0
- data/assets/img/logo-360x360.png +0 -0
- data/assets/img/logo-itunes.jpg +0 -0
- data/assets/img/logo.jpg +0 -0
- data/assets/img/logo/android-icon-144x144.png +0 -0
- data/assets/img/logo/android-icon-192x192.png +0 -0
- data/assets/img/logo/android-icon-36x36.png +0 -0
- data/assets/img/logo/android-icon-48x48.png +0 -0
- data/assets/img/logo/android-icon-72x72.png +0 -0
- data/assets/img/logo/android-icon-96x96.png +0 -0
- data/assets/img/logo/apple-icon-114x114.png +0 -0
- data/assets/img/logo/apple-icon-120x120.png +0 -0
- data/assets/img/logo/apple-icon-144x144.png +0 -0
- data/assets/img/logo/apple-icon-152x152.png +0 -0
- data/assets/img/logo/apple-icon-180x180.png +0 -0
- data/assets/img/logo/apple-icon-57x57.png +0 -0
- data/assets/img/logo/apple-icon-60x60.png +0 -0
- data/assets/img/logo/apple-icon-72x72.png +0 -0
- data/assets/img/logo/apple-icon-76x76.png +0 -0
- data/assets/img/logo/apple-icon-precomposed.png +0 -0
- data/assets/img/logo/apple-icon.png +0 -0
- data/assets/img/logo/browserconfig.xml +2 -0
- data/assets/img/logo/favicon-16x16.png +0 -0
- data/assets/img/logo/favicon-32x32.png +0 -0
- data/assets/img/logo/favicon-96x96.png +0 -0
- data/assets/img/logo/favicon.ico +0 -0
- data/assets/img/logo/manifest.json +41 -0
- data/assets/img/logo/ms-icon-144x144.png +0 -0
- data/assets/img/logo/ms-icon-150x150.png +0 -0
- data/assets/img/logo/ms-icon-310x310.png +0 -0
- data/assets/img/logo/ms-icon-70x70.png +0 -0
- data/assets/index.html +14 -0
- data/assets/inprint.md +19 -0
- data/assets/js/bootstrap.min.js +7 -0
- data/assets/js/custom.js +9 -0
- data/assets/js/icheck.min.js +11 -0
- data/assets/js/jquery.fs.selecter.min.js +9 -0
- data/assets/js/jquery.fs.stepper.min.js +9 -0
- data/assets/podlove-web-player/bin/flashmediaelement.swf +0 -0
- data/assets/podlove-web-player/bin/silverlightmediaelement.xap +0 -0
- data/assets/podlove-web-player/css/pwp-blue-orange.css +3526 -0
- data/assets/podlove-web-player/css/pwp-blue-orange.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-creamy.css +3526 -0
- data/assets/podlove-web-player/css/pwp-creamy.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-dark-blaze.css +3526 -0
- data/assets/podlove-web-player/css/pwp-dark-blaze.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-dark-gray.css +3526 -0
- data/assets/podlove-web-player/css/pwp-dark-gray.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-dark-green.css +3526 -0
- data/assets/podlove-web-player/css/pwp-dark-green.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-dark.css +3526 -0
- data/assets/podlove-web-player/css/pwp-dark.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-jungle-green.css +3526 -0
- data/assets/podlove-web-player/css/pwp-jungle-green.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-light-gray.css +3526 -0
- data/assets/podlove-web-player/css/pwp-light-gray.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-light.css +3526 -0
- data/assets/podlove-web-player/css/pwp-light.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-midnightblue.css +3526 -0
- data/assets/podlove-web-player/css/pwp-midnightblue.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-silver-blaze.css +3526 -0
- data/assets/podlove-web-player/css/pwp-silver-blaze.min.css +1 -0
- data/assets/podlove-web-player/css/pwp-silver.css +3526 -0
- data/assets/podlove-web-player/css/pwp-silver.min.css +1 -0
- data/assets/podlove-web-player/css/vendor/progress-polyfill.css +47 -0
- data/assets/podlove-web-player/css/vendor/style.css +72 -0
- data/assets/podlove-web-player/font/podlove.eot +0 -0
- data/assets/podlove-web-player/font/podlove.svg +103 -0
- data/assets/podlove-web-player/font/podlove.ttf +0 -0
- data/assets/podlove-web-player/font/podlove.woff +0 -0
- data/assets/podlove-web-player/img/arrow-down-black.png +0 -0
- data/assets/podlove-web-player/img/arrow-down-white.png +0 -0
- data/assets/podlove-web-player/img/download-overlay.png +0 -0
- data/assets/podlove-web-player/img/icon-podlove-subscribe-600.png +0 -0
- data/assets/podlove-web-player/js/podlove-web-moderator.js +1829 -0
- data/assets/podlove-web-player/js/podlove-web-moderator.min.js +1 -0
- data/assets/podlove-web-player/js/podlove-web-player.js +6058 -0
- data/assets/podlove-web-player/js/podlove-web-player.min.js +3 -0
- data/assets/podlove-web-player/js/vendor/html5shiv-printshiv.js +524 -0
- data/assets/podlove-web-player/js/vendor/html5shiv-printshiv.min.js +4 -0
- data/assets/podlove-web-player/js/vendor/html5shiv.js +326 -0
- data/assets/podlove-web-player/js/vendor/html5shiv.min.js +4 -0
- data/assets/podlove-web-player/js/vendor/jquery.js +10351 -0
- data/assets/podlove-web-player/js/vendor/jquery.min.js +6 -0
- data/assets/podlove-web-player/js/vendor/jquery.min.map +1 -0
- data/assets/podlove-web-player/js/vendor/progress-polyfill.js +224 -0
- data/assets/podlove-web-player/js/vendor/progress-polyfill.min.js +5 -0
- data/assets/podlove-web-player/js/vendor/tests.js +83 -0
- data/assets/podlove-web-player/js/vendor/user-interaction.js +44 -0
- data/lib/jekyll/octopod/version.rb +1 -1
- metadata +132 -2
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module FlattrFilters
|
5
|
+
|
6
|
+
# Generates the query string part for the flattr load.js from the
|
7
|
+
# configurations in _config.yml
|
8
|
+
#
|
9
|
+
# {{ site | flattr_loader_options }}
|
10
|
+
def flattr_loader_options(site)
|
11
|
+
return if site['flattr_uid'].nil?
|
12
|
+
keys = %w[mode https popout uid button language category]
|
13
|
+
options = flattr_options(site, nil, keys).delete_if { |_, v| v.to_s.empty? }
|
14
|
+
|
15
|
+
options.map { |k, v| "#{k}=#{ERB::Util.url_encode(v)}" }.join('&')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a flattr button
|
19
|
+
#
|
20
|
+
# {{ site | flattr_button:page }}
|
21
|
+
def flattr_button(site, page = nil)
|
22
|
+
return if site['flattr_uid'].nil?
|
23
|
+
|
24
|
+
keys = %w[url title description uid popout button category language tags]
|
25
|
+
options = flattr_options(site, page, keys)
|
26
|
+
|
27
|
+
button = '<a class="FlattrButton" style="display:none;" '
|
28
|
+
button << %Q{title="#{options.delete('title')}" href="#{options.delete('url')}" }
|
29
|
+
button << options.map { |k, v|
|
30
|
+
%Q{data-flattr-#{k}="#{v}"} unless k == 'description'
|
31
|
+
}.join(' ')
|
32
|
+
button << ">\n\n#{options['description'].gsub(/<\/?[^>]*>/, "")}\n</a>"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a RSS payment link.
|
36
|
+
#
|
37
|
+
# {{ site | flattr_rss:post }}
|
38
|
+
def flattr_rss(site, page = nil)
|
39
|
+
return if site['flattr_uid'].nil?
|
40
|
+
link = '<atom:link rel="payment" href="https://flattr.com/submit/auto?'
|
41
|
+
link << %Q{#{flattr_feed_options(site, page)}" type="text/html" />}
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns a ATOM payment link.
|
45
|
+
#
|
46
|
+
# {{ site | flattr_atom:post }}
|
47
|
+
def flattr_atom(site, page = nil)
|
48
|
+
return if site['flattr_uid'].nil?
|
49
|
+
link = '<link rel="payment" href="https://flattr.com/submit/auto?'
|
50
|
+
link << %Q{#{flattr_feed_options(site, page)}" type="text/html" />}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Removes all leading "flattr_" from the keys of the given hash.
|
54
|
+
#
|
55
|
+
# flattrize({ 'octopod' => 'awesome', 'flattr_uid' => 'pattex' })
|
56
|
+
# => { "octopod" => "awesome", "uid" => "pattex" }
|
57
|
+
def flattrize(hsh)
|
58
|
+
config = {}
|
59
|
+
hsh.to_hash.each { |k, v|
|
60
|
+
if new_key = k.to_s.match(/\Aflattr_(.*)\z/)
|
61
|
+
config[new_key[1]] = v
|
62
|
+
else
|
63
|
+
config[k] = v
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
config
|
68
|
+
end
|
69
|
+
|
70
|
+
def flattr_options(site, page, keys)
|
71
|
+
page = {} if page.nil?
|
72
|
+
site = flattrize(site)
|
73
|
+
page = flattrize(page)
|
74
|
+
options = {}
|
75
|
+
|
76
|
+
keys.each { |k|
|
77
|
+
case k
|
78
|
+
when 'https'
|
79
|
+
options[k] = 1
|
80
|
+
when 'url'
|
81
|
+
options[k] = "#{site['url']}#{page['url']}"
|
82
|
+
when 'description'
|
83
|
+
options[k] = page['content'] || site['description'] || site['title']
|
84
|
+
when 'category'
|
85
|
+
options[k] = page['category'] || site['category'] || 'audio'
|
86
|
+
when 'language'
|
87
|
+
options[k] = page['language'] || site['language'] || 'en_GB'
|
88
|
+
when 'tags'
|
89
|
+
options[k] = page['tags'].join(', ') if page['tags']
|
90
|
+
else
|
91
|
+
options[k] = page[k] || site[k]
|
92
|
+
end
|
93
|
+
}
|
94
|
+
|
95
|
+
options
|
96
|
+
end
|
97
|
+
|
98
|
+
def flattr_feed_options(site, page)
|
99
|
+
keys = %w[url uid]
|
100
|
+
options = flattr_options(site, page, keys).map { |k, v|
|
101
|
+
"#{k == 'uid' ? 'user_id' : k}=#{ERB::Util.url_encode(v)}"
|
102
|
+
}.join('&')
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
Liquid::Template.register_filter(Jekyll::FlattrFilters)
|
@@ -0,0 +1,399 @@
|
|
1
|
+
#require 'erb'
|
2
|
+
require 'uri'
|
3
|
+
require 'digest/sha1'
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module OctopodFilters
|
7
|
+
JSON_ENTITIES = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C', "'" => '\u0027' }
|
8
|
+
|
9
|
+
# Escapes some text for CDATA
|
10
|
+
def cdata_escape(input)
|
11
|
+
input.gsub(/<!\[CDATA\[/, '<![CDATA[').gsub(/\]\]>/, ']]>')
|
12
|
+
end
|
13
|
+
|
14
|
+
# Escapes HTML entities in JSON strings.
|
15
|
+
# More or less a copy of the equivalent method in Active Support.
|
16
|
+
# https://github.com/rails/rails/tree/master/activesupport
|
17
|
+
def j(str)
|
18
|
+
str.to_s.gsub(/[&"><']/) { |e| JSON_ENTITIES[e] }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Replaces relative urls with full urls
|
22
|
+
#
|
23
|
+
# {{ "about.html" | expand_urls }} => "/about.html"
|
24
|
+
# {{ "about.html" | expand_urls:site.url }} => "http://example.com/about.html"
|
25
|
+
def expand_urls(input, url='')
|
26
|
+
url ||= '/'
|
27
|
+
input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\"'>]*)/ do
|
28
|
+
$1+url+$3
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Removes scripts tag and audio tags in multiline moderator
|
33
|
+
#
|
34
|
+
# {{ page.content | remove_script_and_audio }}
|
35
|
+
def remove_script_and_audio(input)
|
36
|
+
input.gsub(/<audio.*audio>/m, '').gsub(/<script.*script>/m, '')
|
37
|
+
end
|
38
|
+
|
39
|
+
def http_only(input)
|
40
|
+
input.gsub(/https/,"http")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Formats a Time to be RSS compatible like "Wed, 15 Jun 2005 19:00:00 GMT"
|
44
|
+
#
|
45
|
+
# {{ site.time | time_to_rssschema }}
|
46
|
+
def time_to_rssschema(time)
|
47
|
+
time.strftime("%a, %d %b %Y %H:%M:%S %z")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the first argument if it's not nil or empty otherwise it returns
|
51
|
+
# the second one.
|
52
|
+
#
|
53
|
+
# {{ post.author | otherwise:site.author }}
|
54
|
+
def otherwise(first, second)
|
55
|
+
first = first.to_s
|
56
|
+
first.empty? ? second : first
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the value of a given hash. Is no key as second parameter given, it
|
60
|
+
# trys first "mp3", than "m4a" and than it will return a more or less random
|
61
|
+
# value.
|
62
|
+
#
|
63
|
+
# {{ post.audio | audio:"m4a" }} => "my-episode.m4a"
|
64
|
+
def audio(hsh, key = nil)
|
65
|
+
if key.nil?
|
66
|
+
hsh['mp3'] ? hsh['mp3'] : hsh['m4a'] ? hsh['m4a'] : hsh.values.first
|
67
|
+
else
|
68
|
+
hsh[key]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the MIME-Type of a given file format.
|
73
|
+
#
|
74
|
+
# {{ "m4a" | mime_type }} => "audio/mp4a-latm"
|
75
|
+
def mime_type(format)
|
76
|
+
types = {
|
77
|
+
'mp3' => 'mpeg',
|
78
|
+
'm4a' => 'mp4a-latm',
|
79
|
+
'ogg' => 'ogg; codecs=vorbis',
|
80
|
+
'opus' => 'ogg; codecs=opus'
|
81
|
+
}
|
82
|
+
|
83
|
+
"audio/#{types[format]}"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the size of a given file in bytes. If there is just a filename
|
87
|
+
# without a path, this method assumes that the file is an episode audio file
|
88
|
+
# which lives in /episodes.
|
89
|
+
#
|
90
|
+
# {{ "example.m4a" | file_size }} => 4242
|
91
|
+
def file_size(path, rel = nil)
|
92
|
+
return 0 if path.nil?
|
93
|
+
path = path =~ /\// ? path : File.join('episodes', path)
|
94
|
+
path = rel + path if rel
|
95
|
+
File.size(path)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns a slug based on the id of a given page.
|
99
|
+
#
|
100
|
+
# {{ page | slug }} => '2012_10_02_octopod'
|
101
|
+
def slug(page)
|
102
|
+
page['id'][1..-1].gsub('/', '_')
|
103
|
+
end
|
104
|
+
|
105
|
+
# Splits a chapter, like it is written to the post YAML front matter into
|
106
|
+
# the components 'start' which refers to a single point in time relative to
|
107
|
+
# the beginning of the media file nad 'title' which defines the text to be
|
108
|
+
# the title of the chapter.
|
109
|
+
#
|
110
|
+
# {{ '00:00:00.000 Welcome to Octopod!' | split_chapter }}
|
111
|
+
# => { 'start' => '00:00:00.000', 'title' => 'Welcome to Octopod!' }
|
112
|
+
#
|
113
|
+
# {{ '00:00:00.000 Welcome to Octopod!' | split_chapter:'title' }}
|
114
|
+
# => 'Welcome to Octopod!'
|
115
|
+
#
|
116
|
+
# {{ '00:00:00.000 Welcome to Octopod!' | split_chapter:'start' }}
|
117
|
+
# => '00:00:00.000'
|
118
|
+
def split_chapter(chapter_str, attribute = nil)
|
119
|
+
attributes = chapter_str.split(/ /, 2)
|
120
|
+
return nil unless attributes.first.match(/\A(\d|:|\.)+\z/)
|
121
|
+
|
122
|
+
if attribute.nil?
|
123
|
+
{ 'start' => attributes.first, 'title' => attributes.last }
|
124
|
+
else
|
125
|
+
attribute == 'start' ? attributes.first : attributes.last
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns an <audio>-tag for a given page with <source>-tags in it for every
|
130
|
+
# audio file in the page's YAML front matter.
|
131
|
+
#
|
132
|
+
# {{ page | audio_tag:site }}
|
133
|
+
def audio_tag(page, site)
|
134
|
+
out = "<audio>" + page['audio'].map { |format, filename|
|
135
|
+
%Q{<source src="#{site['url']}/episodes/#{ERB::Util.url_encode(filename)}" type="#{mime_type(format)}"></source>}
|
136
|
+
}.join("\n") + "\n</audio>\n"
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Returns the web player iframe for the episode of a given page.
|
141
|
+
#
|
142
|
+
# {{ page | web_player_moderator:site }}
|
143
|
+
def web_player_moderator(page, site)
|
144
|
+
return if page['audio'].nil?
|
145
|
+
out = %Q{<div class="podlove-player-wrapper">}
|
146
|
+
out = out + %Q{ <audio data-podlove-web-player-source="/players/#{page['slug']}/index.html">\n}
|
147
|
+
out = out + " <source src='episodes/#{page['audio']['mp3']}' type='audio/mp3'>\n"
|
148
|
+
out = out + " </audio>\n"
|
149
|
+
out = out + "</div>\n"
|
150
|
+
out = out + "<script>$('audio').podlovewebplayer();</script>\n"
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# Returns the web player for the episode of a given page for the iframe mentioned in the filter above.
|
155
|
+
#
|
156
|
+
# {{ page | web_player:site }}
|
157
|
+
def web_player(page, site)
|
158
|
+
return if page['audio'].nil?
|
159
|
+
|
160
|
+
options = {
|
161
|
+
alwaysShowHours: 'true',
|
162
|
+
startVolume: '0.8',
|
163
|
+
width: 'auto',
|
164
|
+
summaryVisible: 'true',
|
165
|
+
timecontrolsVisible: 'true',
|
166
|
+
chaptersVisible: 'true',
|
167
|
+
sharebuttonsVisible: 'true'
|
168
|
+
}
|
169
|
+
|
170
|
+
simple_keys = %w[]
|
171
|
+
|
172
|
+
if sitehash = site.posts.first.site.config.dup
|
173
|
+
sitehash.delete('title')
|
174
|
+
sitehash.delete('subtitle')
|
175
|
+
options = options.merge(sitehash)
|
176
|
+
end
|
177
|
+
options = options.merge(page)
|
178
|
+
out = audio_tag(page, sitehash)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns the script tag initializing the web player for the episode of a given page.
|
182
|
+
#
|
183
|
+
# {{ page | web_player_script_tag:site }}
|
184
|
+
def web_player_script_tag(page, site)
|
185
|
+
return if page['audio'].nil?
|
186
|
+
|
187
|
+
options = {
|
188
|
+
alwaysShowHours: 'true',
|
189
|
+
startVolume: '0.8',
|
190
|
+
width: 'auto',
|
191
|
+
summaryVisible: 'true',
|
192
|
+
timecontrolsVisible: 'true',
|
193
|
+
chaptersVisible: 'true',
|
194
|
+
sharebuttonsVisible: 'true'
|
195
|
+
}
|
196
|
+
|
197
|
+
simple_keys = %w[]
|
198
|
+
|
199
|
+
if sitehash = site.posts.first.site.config.dup
|
200
|
+
sitehash.delete('title')
|
201
|
+
sitehash.delete('subtitle')
|
202
|
+
options = options.merge(sitehash)
|
203
|
+
end
|
204
|
+
options = options.merge(page)
|
205
|
+
|
206
|
+
out = "<script>\n$('audio').podlovewebplayer("
|
207
|
+
out << { poster: sitehash['url'] + (options['episode_cover'] || '/img/logo-360x360.png'),
|
208
|
+
subtitle: options['subtitle'],
|
209
|
+
title: options['title'],
|
210
|
+
alwaysShowHours: options['alwaysShowHours'],
|
211
|
+
startVolume: options['startVolume'],
|
212
|
+
width: options['width'],
|
213
|
+
summaryVisible: options['summaryVisible'],
|
214
|
+
timecontrolsVisible: options['timecontrolsVisible'],
|
215
|
+
chaptersVisible: options['chaptersVisible'],
|
216
|
+
sharebuttonsVisible: options['sharebuttonsVisible'],
|
217
|
+
show: { title: site['title'],
|
218
|
+
subtitle: site['subtitle'],
|
219
|
+
summary: site['description'],
|
220
|
+
poster: sitehash['url'] + '/img/logo-360x360.png',
|
221
|
+
url: sitehash['url'] },
|
222
|
+
chapters: options['chapters'].map {|chapter| split_chapter(chapter)},
|
223
|
+
downloads: [
|
224
|
+
{ assetTitle: options['title'],
|
225
|
+
size: file_size(page['audio']['mp3']),
|
226
|
+
downloadUrl: sitehash["url"] + "/episodes/" + page['audio']['mp3'] },
|
227
|
+
],
|
228
|
+
summary: options['summary'],
|
229
|
+
duration: string_of_duration(options['duration']),
|
230
|
+
permalink: sitehash['url'] + page['url'],
|
231
|
+
activeTab: "chapters"
|
232
|
+
}.to_json
|
233
|
+
out << ")\n</script>"
|
234
|
+
end
|
235
|
+
|
236
|
+
# Gets a number of seconds and returns an human readable duration string of
|
237
|
+
# it.
|
238
|
+
#
|
239
|
+
# {{ 1252251 | string_of_duration }} => "00:03:13"
|
240
|
+
def string_of_duration(duration)
|
241
|
+
seconds = duration.to_i
|
242
|
+
minutes = seconds / 60
|
243
|
+
hours = minutes / 60
|
244
|
+
|
245
|
+
"#{"%02d" % hours}:#{"%02d" % (minutes % 60)}:#{"%02d" % (seconds % 60)}"
|
246
|
+
end
|
247
|
+
|
248
|
+
# Gets a number of bytes and returns an human readable string of it.
|
249
|
+
#
|
250
|
+
# {{ 1252251 | string_of_size }} => "1.19M"
|
251
|
+
def string_of_size(bytes)
|
252
|
+
bytes = bytes.to_i.to_f
|
253
|
+
out = '0'
|
254
|
+
return out if bytes == 0.0
|
255
|
+
|
256
|
+
jedec = %w[b K M G]
|
257
|
+
[3, 2, 1, 0].each { |i|
|
258
|
+
if bytes > 1024 ** i
|
259
|
+
out = "%.1f#{jedec[i]}" % (bytes / 1024 ** i)
|
260
|
+
break
|
261
|
+
end
|
262
|
+
}
|
263
|
+
|
264
|
+
return out
|
265
|
+
end
|
266
|
+
|
267
|
+
# Returns the host a given url
|
268
|
+
#
|
269
|
+
# {{ 'https://github.com/pattex/octopod' | host_from_url }} => "github.com"
|
270
|
+
def host_from_url(url)
|
271
|
+
URI.parse(url).host
|
272
|
+
end
|
273
|
+
|
274
|
+
# Generates the config for disqus integration
|
275
|
+
# If a page object is given, it generates the config variables only for this
|
276
|
+
# page. Otherwise it generate only the global config variables.
|
277
|
+
#
|
278
|
+
# {{ site | disqus_config }}
|
279
|
+
# {{ site | disqus_config:page }}
|
280
|
+
def disqus_config(site, page = nil)
|
281
|
+
if page
|
282
|
+
disqus_vars = {
|
283
|
+
'disqus_identifier' => page['url'],
|
284
|
+
'disqus_url' => "#{site['url']}#{page['url']}",
|
285
|
+
'disqus_category_id' => page['disqus_category_id'] || site['disqus_category_id'],
|
286
|
+
'disqus_title' => j(page['title'] || site['site'])
|
287
|
+
}
|
288
|
+
else
|
289
|
+
disqus_vars = {
|
290
|
+
'disqus_developer' => site['disqus_developer'],
|
291
|
+
'disqus_shortname' => site['disqus_shortname']
|
292
|
+
}
|
293
|
+
end
|
294
|
+
|
295
|
+
disqus_vars.delete_if { |_, v| v.nil? }
|
296
|
+
disqus_vars.map { |k, v| "var #{k} = '#{v}';" }.compact.join("\n")
|
297
|
+
end
|
298
|
+
|
299
|
+
# Returns the hex-encoded hash value of a given string. The optional
|
300
|
+
# second argument defines the length of the returned string.
|
301
|
+
#
|
302
|
+
# {{ "Octopod" | sha1 }} => "8b20a59c"
|
303
|
+
# {{ "Octopod" | sha1:23 }} => "8b20a59c8e2dcb5e1f845ba"
|
304
|
+
def sha1(str, lenght = 8)
|
305
|
+
sha1 = Digest::SHA1.hexdigest(str)
|
306
|
+
sha1[0, lenght.to_i]
|
307
|
+
end
|
308
|
+
|
309
|
+
# Returns a, ready to use, navigation list of all pages that have
|
310
|
+
# <tt>navigation</tt> set in their YAML front matter. The list is sorted by
|
311
|
+
# the value of <tt>navigation</tt>.
|
312
|
+
#
|
313
|
+
# {{ site | navigation_list:page }}
|
314
|
+
def navigation_list(site, page)
|
315
|
+
pages = site['pages'].select { |p|
|
316
|
+
p.data['navigation'] && p.data['title']
|
317
|
+
}.sort_by { |p| p.data['navigation'] }
|
318
|
+
|
319
|
+
list = ['<ul class="nav navbar-nav">']
|
320
|
+
list << pages.map { |p|
|
321
|
+
active = (p.url == page['url']) || (page.has_key?('next') && File.join(p.dir, p.basename) == '/index')
|
322
|
+
navigation_list_item(File.join(site['url'], p.url), p.data['title'], active)
|
323
|
+
}
|
324
|
+
list << ['</ul>']
|
325
|
+
|
326
|
+
list.join("\n")
|
327
|
+
end
|
328
|
+
|
329
|
+
def navigation_list_item(url, title, active = false)
|
330
|
+
a_class = active ? ' class="active"' : ''
|
331
|
+
%Q{<li#{a_class}><a #{a_class} href="#{url}">#{title}</a></li>}
|
332
|
+
end
|
333
|
+
|
334
|
+
# Returns an array of all episode feeds named by the convetion
|
335
|
+
# 'episodes.<episode_file_format>.rss' within the root directory. Also it
|
336
|
+
# contains all additional feeds specified by 'additional_feeds' in the
|
337
|
+
# '_config.yml'. If an 'episode_file_format' or key of 'additional_feeds'
|
338
|
+
# equals the optional parameter 'except', it will be skipped.
|
339
|
+
#
|
340
|
+
# episode_feeds(site, except = nil) =>
|
341
|
+
# [
|
342
|
+
# ["m4a Episode RSS-Feed", "/episodes.m4a.rss"],
|
343
|
+
# ["mp3 Episode RSS-Feed", "/episodes.mp3.rss"],
|
344
|
+
# ["Torrent Feed m4a", "http://bitlove.org/octopod/octopod_m4a/feed"],
|
345
|
+
# ["Torrent Feed mp3", "http://bitlove.org/octopod/octopod_mp3/feed"]
|
346
|
+
# ]
|
347
|
+
def episode_feeds(site, except = nil)
|
348
|
+
feeds = []
|
349
|
+
|
350
|
+
if site['episode_feed_formats']
|
351
|
+
site['episode_feed_formats'].map { |f|
|
352
|
+
feeds << ["#{f} Episode RSS-Feed", "#{site['url']}/episodes.#{f}.rss"] unless f == except
|
353
|
+
}
|
354
|
+
end
|
355
|
+
if site['additional_feeds']
|
356
|
+
site['additional_feeds'].each { |k, v|
|
357
|
+
feeds << [k.gsub('_', ' '), v] unless k == except
|
358
|
+
}
|
359
|
+
end
|
360
|
+
|
361
|
+
feeds
|
362
|
+
end
|
363
|
+
|
364
|
+
# Returns HTML links to all episode feeds named by the convetion
|
365
|
+
# 'episodes.<episode_file_format>.rss' within the root directory. Also it
|
366
|
+
# returns all additional feeds specified by 'additional_feeds' in the
|
367
|
+
# '_config.yml'. If an 'episode_file_format' or key of 'additional_feeds'
|
368
|
+
# equals the optional parameter 'except', it will be skipped.
|
369
|
+
#
|
370
|
+
# {{ site | episode_feeds_html:'m4a' }} =>
|
371
|
+
# <link rel="alternate" type="application/rss+xml" title="mp3 Episode RSS-Feed" href="/episodes.mp3.rss" />
|
372
|
+
# <link rel="alternate" type="application/rss+xml" title="Torrent Feed m4a" href="http://bitlove.org/octopod/octopod_m4a/feed" />
|
373
|
+
# <link rel="alternate" type="application/rss+xml" title="Torrent Feed mp3" href="http://bitlove.org/octopod/octopod_mp3/feed" />
|
374
|
+
def episode_feeds_html(site, except = nil)
|
375
|
+
episode_feeds(site, except).map { |f|
|
376
|
+
%Q{<link rel="alternate" type="application/rss+xml" title="#{f.first || f.last}" href="#{f.last}" />}
|
377
|
+
}.join("\n")
|
378
|
+
end
|
379
|
+
|
380
|
+
# Returns RSS-XML links to all episode feeds named by the convetion
|
381
|
+
# 'episodes.<episode_file_format>.rss' within the root directory. Also it
|
382
|
+
# returns all additional feeds specified by 'additional_feeds' in the
|
383
|
+
# '_config.yml'. If an 'episode_file_format' or key of 'additional_feeds'
|
384
|
+
# equals the optional parameter 'except', it will be skipped.
|
385
|
+
#
|
386
|
+
# {{ site | episode_feeds_rss:'m4a' }} =>
|
387
|
+
# <atom:link rel="alternate" href="/episodes.mp3.rss" type="application/rss+xml" title="mp3 Episode RSS-Feed"/>
|
388
|
+
# <atom:link rel="alternate" href="http://bitlove.org/octopod/octopod_m4a/feed" type="application/rss+xml" title="Torrent Feed m4a"/>
|
389
|
+
# <atom:link rel="alternate" href="http://bitlove.org/octopod/octopod_mp3/feed" type="application/rss+xml" title="Torrent Feed mp3"/>
|
390
|
+
def episode_feeds_rss(site, except = nil)
|
391
|
+
episode_feeds(site, except).map { |f|
|
392
|
+
%Q{<atom:link rel="alternate" href="#{f.last}" type="application/rss+xml" title="#{f.first || f.last}"/>}
|
393
|
+
}.join("\n")
|
394
|
+
end
|
395
|
+
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
Liquid::Template.register_filter(Jekyll::OctopodFilters)
|