alula-plugins 0.1.1 → 0.4.0b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/.gitignore +2 -1
  2. data/Rakefile +0 -0
  3. data/VERSION +1 -1
  4. data/alula-plugins.gemspec +1 -1
  5. data/lib/alula/plugins/disqus.rb +34 -0
  6. data/lib/alula/plugins/emphasis.rb +19 -0
  7. data/lib/alula/plugins/fancybox.rb +60 -0
  8. data/lib/alula/plugins/sublimevideo.rb +75 -0
  9. data/lib/alula/plugins.rb +1 -0
  10. data/plugins/disqus/assets/stylesheets/disqus.css +0 -0
  11. data/plugins/emphasis/assets/javascripts/emphasis.js +529 -0
  12. data/plugins/emphasis/assets/stylesheets/emphasis.css +0 -0
  13. data/plugins/fancybox/assets/images/blank.gif +0 -0
  14. data/plugins/fancybox/assets/images/fancybox_loading.gif +0 -0
  15. data/plugins/fancybox/assets/images/fancybox_sprite.png +0 -0
  16. data/plugins/fancybox/assets/images/zoom_icon.png +0 -0
  17. data/plugins/fancybox/assets/javascripts/fancybox.js.coffee +15 -0
  18. data/plugins/{lightbox/stylesheets/jquery.fancybox.css → fancybox/assets/stylesheets/fancybox.css.erb} +30 -4
  19. data/plugins/sublimevideo/assets/images/zoom_icon.png +0 -0
  20. data/plugins/sublimevideo/assets/javascripts/sublimevideo.js +3 -0
  21. data/plugins/sublimevideo/assets/stylesheets/sublimevideo.css.erb +28 -0
  22. metadata +40 -19
  23. data/lib/alula/plugins/lightbox.rb +0 -46
  24. data/plugins/.DS_Store +0 -0
  25. data/plugins/lightbox/javascripts/.DS_Store +0 -0
  26. data/plugins/lightbox/javascripts/lightbox.js.coffee +0 -5
  27. data/plugins/lightbox/stylesheets/lightbox.css +0 -3
  28. /data/plugins/{lightbox/javascripts/lightbox_body.js → disqus/assets/javascripts/disqus.js} +0 -0
  29. /data/plugins/{lightbox → fancybox/assets}/javascripts/jquery.fancybox.js +0 -0
data/.gitignore CHANGED
@@ -17,4 +17,5 @@ test/version_tmp
17
17
  tmp
18
18
  */.DS_Store
19
19
 
20
- .DS_Store
20
+ .DS_Store
21
+ plugins/.DS_Store
data/Rakefile CHANGED
File without changes
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.4.0b
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Alula::Plugins::VERSION
17
17
 
18
- gem.add_dependency 'alula', '~> 0.2'
18
+ gem.add_dependency 'alula', '~> 0.4.0b'
19
19
 
20
20
  gem.add_development_dependency 'version', '~> 1.0.0'
21
21
  end
@@ -0,0 +1,34 @@
1
+ require 'alula/plugin'
2
+
3
+ module Alula
4
+ class Disqus
5
+ def self.asset_path
6
+ File.join(File.dirname(__FILE__), %w{.. .. .. plugins disqus})
7
+ end
8
+
9
+ def self.install(options)
10
+ return false unless options.shortname
11
+ # Force defer mode on script loading
12
+ # Alula::Plugin.script_load_mode = :defer
13
+
14
+ # Add Emphasis -powered link to footer
15
+ Alula::Plugin.addon(:post_bottom, ->(context) {
16
+ <<-EOS
17
+ <script type="text/javascript">
18
+ var disqus_shortname = '#{options['shortname']}';
19
+ var disqus_identifier = '#{context.item.metadata.disqus_identifier || context.item.slug}';
20
+ (function() {
21
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
22
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
23
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
24
+ })();
25
+ </script>
26
+ <a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
27
+ EOS
28
+ }
29
+ )
30
+ end
31
+ end
32
+ end
33
+
34
+ Alula::Plugin.register :disqus, Alula::Disqus
@@ -0,0 +1,19 @@
1
+ require 'alula/plugin'
2
+
3
+ module Alula
4
+ class Emphasis
5
+ def self.asset_path
6
+ File.join(File.dirname(__FILE__), %w{.. .. .. plugins emphasis})
7
+ end
8
+
9
+ def self.install(options)
10
+ # Force defer mode on script loading
11
+ Alula::Plugin.script_load_mode = :defer
12
+
13
+ # Add Emphasis -powered link to footer
14
+ Alula::Plugin.addon(:footer, "<a href=\"https://github.com/NYTimes/Emphasis\" title=\"Emphasis\">&para;</a>&nbsp;&ndash;Emphasis</a><br />")
15
+ end
16
+ end
17
+ end
18
+
19
+ Alula::Plugin.register :emphasis, Alula::Emphasis
@@ -0,0 +1,60 @@
1
+ require 'alula/core_ext/tags/image'
2
+ require 'alula/plugin'
3
+
4
+ module Alula
5
+ class Fancybox < ImageTag
6
+ def self.asset_path
7
+ File.join(File.dirname(__FILE__), %w{.. .. .. plugins fancybox})
8
+ end
9
+
10
+ def self.install(options)
11
+ # Display license unless acknoledged
12
+ unless options.kind_of?(Hash) and options['personal']
13
+ puts <<-ENDOFNOTICE
14
+ *** fancyBox
15
+ Please note, that fancyBox is licensed under the therms of the
16
+ Creative Commons Attribution-NonCommercial 3.0 License
17
+ (http://creativecommons.org/licenses/by-nc/3.0/).
18
+
19
+ If you would like to use fancyBox for commercial purposes,
20
+ you can purchase a license from http://fancyapps.com/store/
21
+
22
+ To remove this notice, please include following options in config.yml
23
+ ---
24
+ plugins:
25
+ fancybox:
26
+ personal: true
27
+ ENDOFNOTICE
28
+ end
29
+
30
+ # Register for image tags
31
+ Alula::Tag.register :image, self
32
+ end
33
+
34
+ def content
35
+ image = attachment_url(@source, :image)
36
+ thumbnail = attachment_url(@source, :thumbnail)
37
+ hires = hires_url(@source, :image)
38
+ info = info(@source, :image)
39
+ tn_info = info(@source, :thumbnail)
40
+
41
+ return super unless image and thumbnail
42
+
43
+ tag = "<a"
44
+ tag += " class=\"img fancybox fb_zoomable #{@options["classes"].join(" ")}\""
45
+ tag += " href=\"#{image}\""
46
+ tag += " data-width=\"#{info.width}\""
47
+ tag += " data-height=\"#{info.height}\""
48
+ tag += " data-hires=\"#{hires}\"" if context.site.config.attachments.image.hires and hires
49
+ tag += " data-fancybox-group=\"#{context.item.id}\""
50
+ tag += " title=\"#{@options["title"]}\"" if @options["title"]
51
+ tag += " style=\"width: #{tn_info.width}px; height: #{tn_info.height}px;\""
52
+ tag += ">"
53
+ tag += imagetag(@source, :thumbnail, classes: [])
54
+ tag += " <span class=\"fb_zoom_icon\"></span>"
55
+ tag += "</a>"
56
+ end
57
+ end
58
+ end
59
+
60
+ Alula::Plugin.register :fancybox, Alula::Fancybox
@@ -0,0 +1,75 @@
1
+ require 'alula/core_ext/tags/video'
2
+ require 'alula/plugin'
3
+
4
+ module Alula
5
+ class Sublimevideo < VideoTag
6
+ def self.asset_path
7
+ File.join(File.dirname(__FILE__), %w{.. .. .. plugins sublimevideo})
8
+ end
9
+
10
+ def self.install(options)
11
+ # Require valid sublime token present in configuration
12
+ return false unless options.token
13
+
14
+ # Register addons
15
+ Alula::Plugin.addon :head, ->(context) {
16
+ "<script src=\"http://cdn.sublimevideo.net/js/#{options.token}.js\"></script>" if context.item.content[/\<video/]
17
+ }
18
+
19
+ # Register for image tags
20
+ Alula::Tag.register :video, self
21
+ end
22
+
23
+ def content
24
+ sublime_videotag(@source)
25
+ end
26
+
27
+ def sublime_videotag(source)
28
+ poster = source.gsub(/#{File.extname(source)}$/, '.png')
29
+ info = info(poster, :thumbnail)
30
+ poster_hires = hires_url(poster, :thumbnail)
31
+ poster = attachment_url(poster, :thumbnail)
32
+
33
+ tag = "<a"
34
+ tag += " class=\"sublime zoomable\""
35
+ tag += " href=\"#{sources.first[:url]}\""
36
+ tag += " style=\"width: #{info.width}px; height: #{info.height}px;\""
37
+ tag += ">"
38
+ tag += " <img"
39
+ tag += " alt=\"#{@options["alternative"]}\""
40
+ tag += " width=\"#{info.width}\" height=\"#{info.height}\""
41
+ if context.site.config.attachments.image.lazyload
42
+ tag += " src=\"#{asset_url("grey.gif")}\""
43
+ tag += " data-original=\"#{poster}\""
44
+ else
45
+ tag += " src=\"#{poster}\""
46
+ end
47
+ tag += " data-hires=\"#{poster_hires}\"" if context.site.config.attachments.image.hires and poster_hires
48
+
49
+ tag += " />"
50
+ tag += " <span class=\"zoom_icon\"></span>"
51
+ tag += "</a>"
52
+
53
+ info = info(sources.first[:name], :video)
54
+ tag += "<video"
55
+ tag += " controls"
56
+ tag += " class=\"sublime lightbox\""
57
+ tag += " style=\"display: none;\""
58
+ tag += " width=\"#{info.width}\""
59
+ tag += " height=\"#{info.height}\""
60
+ tag += " poster=\"#{poster}\""
61
+ tag += " preload=\"none\""
62
+ tag += " data-uid=\"#{source}\""
63
+ tag += ">"
64
+
65
+ sources.each do |source|
66
+ tag += " <source src=\"#{source[:url]}\" #{source[:hires] ? "data-quality=\"hd\"" : ""} />"
67
+ end
68
+
69
+ tag += "</video>"
70
+
71
+ end
72
+ end
73
+ end
74
+
75
+ Alula::Plugin.register :sublimevideo, Alula::Sublimevideo
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), "plugins", "*.rb")].each {|f| require f}
File without changes
@@ -0,0 +1,529 @@
1
+ //=require jquery
2
+ /* --------------------------------------------------
3
+
4
+ Emphasis
5
+ by Michael Donohoe (@donohoe)
6
+ https://github.com/NYTimes/Emphasis
7
+ http://open.blogs.nytimes.com/2011/01/10/emphasis-update-and-source/
8
+
9
+ - - - - - - - - - -
10
+
11
+ jQueryized by Rob Flaherty (@ravelrumba)
12
+ https://github.com/robflaherty/Emphasis
13
+
14
+ - - - - - - - - - -
15
+
16
+ Copyright (C) 2011 The New York Times (http://www.nytimes.com)
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the "Software"), to deal
20
+ in the Software without restriction, including without limitation the rights
21
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in
26
+ all copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
+ SOFTWARE.
35
+
36
+ -------------------------------------------------- */
37
+
38
+ jQuery(function($) {
39
+ var Emphasis = {
40
+ init: function() {
41
+ this.config();
42
+ this.pl = false; // Paragraph List
43
+ this.p = false; // Paragraph Anchor
44
+ this.h = false; // Highlighted paragraphs
45
+ this.s = false; // Highlighted sentences
46
+ this.vu = false; // Are paragraph links visible or not
47
+ this.kh = "|";
48
+
49
+ this.addCSS();
50
+ this.readHash();
51
+
52
+ $(document).bind('keydown', this.keydown);
53
+ },
54
+
55
+ config: function() {
56
+ /*
57
+ Eligible Paragraphs
58
+ This uses some common markup for plain and simple paragraphs - those that are not empty, no classes.
59
+ We use PrototypeJS for its css selector awesomeness, but your needs might be simpler (getElementsByTagName('p') etc.)
60
+ */
61
+ // this.paraSelctors = $('#article-content p');
62
+ this.paraSelctors = $('.articleBody p');
63
+
64
+ // Class names
65
+ this.classReady = "emReady";
66
+ this.classActive = "emActive";
67
+ this.classHighlight = "emHighlight";
68
+ this.classInfo = "emInfo";
69
+ this.classAnchor = "emAnchor";
70
+ this.classActiveAnchor = "emActiveAnchor";
71
+ },
72
+
73
+ addCSS: function() {
74
+ /* Inject the minimum styles rules required */
75
+ var st = document.createElement('style');
76
+ st.setAttribute('type', 'text/css');
77
+ /* for validation goodness */
78
+ var stStr = 'p.' + this.classActive + ' span { background-color:#f2f4f5; } p span.' + this.classHighlight + ' { background-color:#fff0b3; } span.' + this.classInfo + ' { position:absolute; margin:-1px 0px 0px -8px; padding:0; font-size:10px; background-color: transparent !important} span.' + this.classInfo + ' a { text-decoration: none; } a.' + this.classActiveAnchor + ' { color: #000; font-size: 11px; }';
79
+ try {
80
+ /* try the sensible way */
81
+ st.innerHTML = stStr;
82
+ } catch(e) {
83
+ /* IE's way */
84
+ st.styleSheet.cssText = stStr;
85
+ }
86
+ document.getElementsByTagName("head")[0].appendChild(st);
87
+ },
88
+
89
+ readHash: function() {
90
+ /* Read and interpret the URL hash */
91
+ var lh = decodeURI(location.hash),
92
+ p = false,
93
+ h = [],
94
+ s = {},
95
+ a, re, f, r, i, findp, findh, undef, hi, key, pos, b, j;
96
+
97
+
98
+ if (lh.indexOf('[')<0 && lh.indexOf(']')<0) {
99
+ /* Version 1 Legacy support
100
+ #p20h4s2,6,10,h6s5,1 -> p = 20, h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5, 1 ] }
101
+ */
102
+ re = /[ph][0-9]+|s[0-9,]+|[0-9]/g;
103
+ if (lh) {
104
+ while ((a = re.exec(lh)) !== null) {
105
+ f = a[0].substring(0, 1);
106
+ r = a[0].substring(1);
107
+ if (f === 'p') {
108
+ p = parseInt(r, 10);
109
+ } else if (f === 'h') {
110
+ h.push(parseInt(r, 10));
111
+ } else {
112
+ a = r.split(',');
113
+ for (i = 0; i < a.length; i++) {
114
+ a[i] = parseInt(a[i], 10);
115
+ }
116
+ s[h[h.length - 1]] = a;
117
+ }
118
+ }
119
+ }
120
+ } else {
121
+ /* Version 2
122
+ #h[tbsaoa,Sstaoo,2,4],p[FWaadw] -> p = "FWaadw", h = [ "tbsaoa", "Sstaoo" ], s = { "Sstaoo" : [ 2, 4 ] }
123
+ */
124
+ findp = lh.match(/p\[([^[\]]*)\]/);
125
+ findh = lh.match(/h\[([^[\]]*)\]/);
126
+
127
+ p = (findp && findp.length>0) ? findp[1] : false;
128
+ hi = (findh && findh.length>0) ? findh[1] : false;
129
+
130
+ if (hi) {
131
+ hi = hi.match(/[a-zA-Z]+(,[0-9]+)*/g);
132
+ for (i = 0; i < hi.length; i++) {
133
+ a = hi[i].split(',');
134
+ key = a[0];
135
+ pos = this.findKey(key).index;
136
+
137
+ if (pos !== undef) {
138
+ h.push(parseInt(pos, 10)+1);
139
+ b = a;
140
+ b.shift();
141
+ if (b.length>0) {
142
+ for (j=1; j<b.length; j++) {
143
+ b[j] = parseInt(b[j], 10);
144
+ }
145
+ }
146
+ s[h[h.length - 1]] = b;
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ this.p = p; this.h = h; this.s = s;
153
+
154
+ this.goAnchor(p);
155
+ this.goHighlight(h, s);
156
+ },
157
+
158
+ keydown: function(e){
159
+ /* Look for double-shift keypress */
160
+ var self = Emphasis,
161
+ kc = e.keyCode;
162
+
163
+ self.kh = self.kh + kc + '|';
164
+ if (self.kh.indexOf('|16|16|')>-1) {
165
+ self.vu = (self.vu) ? false : true;
166
+ self.paragraphInfo(self.vu);
167
+ }
168
+ setTimeout(function(){ self.kh = '|'; }, 500);
169
+ },
170
+
171
+ paragraphList: function() {
172
+ /* Build a list of Paragrphs, keys, and add meta-data to each Paragraph in DOM, saves list for later re-use */
173
+ if (this.pl && this.pl.list.length > 0) {
174
+ return this.pl;
175
+ }
176
+ var instance = this,
177
+ list = [],
178
+ keys = [],
179
+ c = 0,
180
+ len = this.paraSelctors.length,
181
+ p, pr, k;
182
+
183
+ for (p=0; p<len; p++) {
184
+ pr = this.paraSelctors[p];
185
+ if ((pr.innerText || pr.textContent || "").length>0) {
186
+ k = instance.createKey(pr);
187
+ list.push(pr);
188
+ keys.push(k);
189
+ pr.setAttribute("data-key", k); // Unique Key
190
+ pr.setAttribute("data-num", c); // Order
191
+
192
+ $(pr).bind('click', function(e) {
193
+ instance.paragraphClick(e);
194
+ });
195
+ c++;
196
+ }
197
+ }
198
+
199
+ this.pl = { list: list, keys: keys };
200
+ return this.pl;
201
+ },
202
+
203
+ paragraphClick: function(e) {
204
+ /* Clicking a Paragrsph has consequences for Highlighting, selecting and changing active Anchor */
205
+ if (!this.vu) { return; }
206
+
207
+ var hasChanged = false,
208
+ pr = (e.currentTarget.nodeName === "P") ? e.currentTarget : false, // Paragraph
209
+ $pr = $(pr),
210
+ sp = (e.target.nodeName === "SPAN") ? e.target : false, // Span
211
+ an = (e.target.nodeName === "A") ? e.target : false, // Anchor
212
+ lines, jLen, j, txt, chr;
213
+
214
+ if (an) {
215
+ /* Click an Anchor link */
216
+ if (!$(an).hasClass(this.classActiveAnchor)) {
217
+ this.updateAnchor(an);
218
+ hasChanged = true;
219
+ e.preventDefault();
220
+ }
221
+ }
222
+
223
+ if (!pr && !sp) {
224
+ this.removeClass(this.classActive);
225
+ return;
226
+ }
227
+
228
+ if ($pr.hasClass(this.classReady)) {
229
+ if (!$pr.hasClass(this.classActive) && (sp && !$(sp).hasClass(this.classHighlight))) {
230
+ // If not current Active p tag, clear any others out there and make this the Active p tag
231
+ $(this).removeClass(this.classActive);
232
+ $pr.addClass(this.classActive); // Mark as Active
233
+ } else {
234
+ if (!$pr.hasClass(this.classActive)) {
235
+ $(this).removeClass(this.classActive);
236
+ $pr.addClass(this.classActive); // Mark as Active
237
+ }
238
+
239
+ if (sp) {
240
+ $(sp).toggleClass(this.classHighlight);
241
+ hasChanged = true;
242
+ }
243
+ }
244
+ } else {
245
+ // Add span tags to all Sentences within Paragraph and mark Paragraph as Ready
246
+ lines = this.getSentences(pr);
247
+ jLen = lines.length;
248
+
249
+ for (j=0; j<jLen; j++) {
250
+ lines[j] = "<span data-num='" + (j+1) + "'>" + this.rtrim(lines[j]) + "</span>";
251
+ }
252
+
253
+ txt = lines.join('. ').replace(/__DOT__/g, ".").replace(/<\/span>\./g, ".<\/span>");
254
+ chr = txt.substring(txt.length-8).charCodeAt(0);
255
+ if ("|8221|63|46|41|39|37|34|33|".indexOf(chr) === -1) { txt += "."; }
256
+
257
+ pr.innerHTML = txt;
258
+ pr.setAttribute('data-sentences', jLen);
259
+
260
+ $(this).removeClass(this.classActive);
261
+ $pr.addClass(this.classActive); // Mark as Active
262
+ $pr.addClass(this.classReady); // Mark as Ready
263
+ hasChanged = true;
264
+ }
265
+
266
+ if (hasChanged) {
267
+ this.updateURLHash();
268
+ }
269
+ },
270
+
271
+ paragraphInfo: function(mode) {
272
+ /* Toggle anchor links next to Paragraphs */
273
+ var hasSpan, pl, len, i, para, key, isActive, spans;
274
+
275
+ if (mode) {
276
+ hasSpan = $('span.' + this.classInfo);
277
+ if (hasSpan.length === 0) {
278
+ pl = this.paragraphList();
279
+ len = pl.list.length;
280
+ for (i=0; i<len; i++) {
281
+ para = pl.list[i] || false;
282
+ if (para) {
283
+ key = pl.keys[i];
284
+ isActive = (key===this.p) ? (" " + this.classActiveAnchor) : "";
285
+ para.innerHTML = "<span class='" + this.classInfo + "'><a class='"+ this.classAnchor + isActive + "' href='#p[" + key + "]' data-key='" + key + "' title='Link to " + this.ordinal(i+1) + " paragraph'>&para;</a></span>" + para.innerHTML;
286
+ }
287
+ }
288
+ }
289
+ } else {
290
+ spans = $('span.' + this.classInfo);
291
+
292
+ len = spans.length;
293
+ for (i=0; i<len; i++) {
294
+ $(spans[i]).remove();
295
+ }
296
+ $(this).removeClass(this.classActive);
297
+ }
298
+ },
299
+
300
+ updateAnchor: function(an) {
301
+ /* Make this A tag the one and only Anchor */
302
+ this.p = an.getAttribute("data-key");
303
+ $(this).removeClass(this.classActiveAnchor);
304
+ $(an).addClass(this.classActiveAnchor);
305
+ },
306
+
307
+ updateURLHash: function() {
308
+ /* Scan the Paragraphs, note selections, highlights and update the URL with the new Hash */
309
+ var h = "h[",
310
+ paras = $('p.emReady'),
311
+ pLen = paras.length,
312
+ p, key, spans, sLen, nSent, anchor, hash,s;
313
+
314
+ for (p=0; p < pLen; p++) {
315
+ key = paras[p].getAttribute("data-key");
316
+ if ($(paras[p]).hasClass(this.classHighlight)) {
317
+ h += "," + key; // Highlight full paragraph
318
+ } else {
319
+ spans = $('span.' + this.classHighlight, paras[p]);
320
+ sLen = spans.length;
321
+ nSent = paras[p].getAttribute("data-sentences");
322
+
323
+ if (sLen>0) { h += "," + key; }
324
+
325
+ if (nSent!==sLen) {
326
+ for (s=0; s<sLen; s++) {
327
+ h += "," + spans[s].getAttribute("data-num");
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ anchor = ((this.p) ? "p[" + this.p + "]," : "");
334
+ hash = (anchor + (h.replace("h[,", "h[") + "]")).replace(",h[]", "");
335
+ location.hash = hash;
336
+ },
337
+
338
+ createKey: function(p) {
339
+ /* From a Paragraph, generate a Key */
340
+ var key = "",
341
+ len = 6,
342
+ txt = (p.innerText || p.textContent || '').replace(/[^a-z\. ]+/gi, ''),
343
+ lines, first, last, k, max, i;
344
+
345
+ if (txt && txt.length>1) {
346
+
347
+ lines = this.getSentences(txt);
348
+ if (lines.length>0) {
349
+ first = this.cleanArray(lines[0].replace(/[\s\s]+/gi, ' ').split(' ')).slice(0, (len/2));
350
+ last = this.cleanArray(lines[lines.length-1].replace(/[\s\s]+/gi, ' ').split(' ')).slice(0, (len/2));
351
+ k = first.concat(last);
352
+
353
+ max = (k.length>len) ? len : k.length;
354
+ for (i=0; i<max; i++) {
355
+ key += k[i].substring(0, 1);
356
+ }
357
+ }
358
+ }
359
+ return key;
360
+ },
361
+
362
+ findKey: function(key) {
363
+ /* From a list of Keys, locate the Key and corresponding Paragraph */
364
+ var pl = this.paragraphList(),
365
+ ln = pl.keys.length,
366
+ ix = false,
367
+ el = false,
368
+ i, ls, le;
369
+
370
+ for (i=0;i<ln;i++) {
371
+ if (key===pl.keys[i]) { // Direct Match
372
+ return { index: i, elm: pl.list[i] };
373
+ } else { // Look for 1st closest Match
374
+ if (!ix) {
375
+ ls = this.lev(key.slice(0, 3), pl.keys[i].slice(0, 3));
376
+ le = this.lev(key.slice(-3) , pl.keys[i].slice(-3));
377
+ if ((ls+le)<3) {
378
+ ix = i;
379
+ el = pl.list[i];
380
+ }
381
+ }
382
+ }
383
+ }
384
+ return { index: ix, elm: el };
385
+ },
386
+
387
+ goAnchor: function(p) {
388
+ /* Move view to top of a given Paragraph */
389
+ if (!p) {
390
+ return;
391
+ }
392
+ var pg = (isNaN(p)) ? this.findKey(p)['elm'] : (this.paragraphList().list[p-1] || false);
393
+
394
+ if (pg) {
395
+ setTimeout(function(){
396
+ $(window).scrollTop($(pg).offset().top);
397
+ }, 500);
398
+ }
399
+ },
400
+
401
+ goHighlight: function(h, s) {
402
+ /* Highlight a Paragraph, or specific Sentences within it */
403
+ if (!h) {
404
+ return;
405
+ }
406
+ var hLen = h.length,
407
+ i, para, sntns, multi, lines, jLen, j, k, line;
408
+
409
+ for (i=0; i<hLen; i++) {
410
+ para = this.paragraphList().list[h[i]-1] || false;
411
+ if (para) {
412
+ sntns = s[h[i].toString()] || false;
413
+ multi = !sntns || sntns.length===0; // Individual sentences, or whole paragraphy?
414
+ lines = this.getSentences(para);
415
+ jLen = lines.length;
416
+
417
+ /* First pass. Add SPAN tags to all lines. */
418
+ for (j=0; j<jLen; j++) {
419
+ k = (multi) ? j : sntns[j]-1;
420
+ lines[j] = "<span data-num='" + (j+1) + "'>" + lines[j] + "</span>";
421
+ }
422
+
423
+ /* Second pass, update span to Highlight selected lines */
424
+ for (j=0; j<jLen; j++) {
425
+ k = (multi) ? j : sntns[j]-1;
426
+ line = lines[k] || false;
427
+ if (line) {
428
+ lines[k] = lines[k].replace("<span", "<span class='" + this.classHighlight + "'");
429
+ }
430
+ }
431
+
432
+ para.setAttribute("data-sentences", jLen);
433
+ para.innerHTML = lines.join('. ').replace(/__DOT__/g, ".").replace(/<\/span>\./g, ".<\/span>");
434
+ $(para).addClass('emReady'); /* Mark the paragraph as having SPANs */
435
+ }
436
+ }
437
+ },
438
+
439
+ getSentences: function(el) {
440
+ /* Break a Paragraph into Sentences, bearing in mind that the "." is not the definitive way to do so */
441
+ var html = (typeof el==="string") ? el : el.innerHTML,
442
+ mrsList = "Mr,Ms,Mrs,Miss,Msr,Dr,Gov,Pres,Sen,Prof,Gen,Rep,St,Messrs,Col,Sr,Jf,Ph,Sgt,Mgr,Fr,Rev,No,Jr,Snr",
443
+ topList = "A,B,C,D,E,F,G,H,I,J,K,L,M,m,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,etc,oz,cf,viz,sc,ca,Ave,St",
444
+ geoList = "Calif,Mass,Penn,AK,AL,AR,AS,AZ,CA,CO,CT,DC,DE,FL,FM,GA,GU,HI,IA,ID,IL,IN,KS,KY,LA,MA,MD,ME,MH,MI,MN,MO,MP,MS,MT,NC,ND,NE,NH,NJ,NM,NV,NY,OH,OK,OR,PA,PR,PW,RI,SC,SD,TN,TX,UT,VA,VI,VT,WA,WI,WV,WY,AE,AA,AP,NYC,GB,IRL,IE,UK,GB,FR",
445
+ numList = "0,1,2,3,4,5,6,7,8,9",
446
+ webList = "aero,asia,biz,cat,com,coop,edu,gov,info,int,jobs,mil,mobi,museum,name,net,org,pro,tel,travel,xxx",
447
+ extList = "www",
448
+ d = "__DOT__",
449
+
450
+ list = (topList+","+geoList+","+numList+","+extList).split(","),
451
+ len = list.length,
452
+ i, lines;
453
+
454
+ for (i=0;i<len;i++) {
455
+ html = html.replace(new RegExp((" "+list[i]+"\\."), "g"), (" "+list[i]+d));
456
+ }
457
+
458
+ list = (mrsList+","+numList).split(",");
459
+ len = list.length;
460
+ for (i=0;i<len;i++) {
461
+ html = html.replace(new RegExp((list[i]+"\\."), "g"), (list[i]+d));
462
+ }
463
+
464
+ list = (webList).split(",");
465
+ len = list.length;
466
+ for (i=0;i<len;i++) {
467
+ html = html.replace(new RegExp(("\\."+list[i]), "g"), (d+list[i]));
468
+ }
469
+
470
+ lines = this.cleanArray(html.split('. '));
471
+ return lines;
472
+ },
473
+
474
+ ordinal: function(n) {
475
+ var sfx = ["th","st","nd","rd"],
476
+ val = n%100;
477
+ return n + (sfx[(val-20)%10] || sfx[val] || sfx[0]);
478
+ },
479
+
480
+ lev: function(a, b) {
481
+ /* Get the Levenshtein distance - a measure of difference between two sequences */
482
+ var m = a.length,
483
+ n = b.length,
484
+ r = [],
485
+ c, o, i, j;
486
+
487
+ r[0] = [];
488
+
489
+ if (m < n) { c = a; a = b; b = c; o = m; m = n; n = o; }
490
+ for (c = 0; c < n+1; c++) { r[0][c] = c; }
491
+ for (i = 1; i < m+1; i++) {
492
+ r[i] = [];
493
+ r[i][0] = i;
494
+ for (j=1; j<n+1; j++) {
495
+ r[i][j] = this.smallest(r[i-1][j]+1, r[i][j-1]+1, r[i-1][j-1]+((a.charAt(i-1)===b.charAt(j-1))? 0 : 1));
496
+ }
497
+ }
498
+ return r[m][n];
499
+ },
500
+
501
+ smallest: function(x,y,z) {
502
+ /* Return smallest of two values */
503
+ if (x < y && x < z) { return x; }
504
+ if (y < x && y < z) { return y; }
505
+ return z;
506
+ },
507
+
508
+ rtrim: function(txt) {
509
+ /* Trim whitespace from right of string */
510
+ return txt.replace(/\s+$/, "");
511
+ },
512
+
513
+ cleanArray: function(a){
514
+ /* Remove empty items from an array */
515
+ var n = [],
516
+ i;
517
+ for (i = 0; i<a.length; i++){
518
+ if (a[i] && a[i].replace(/ /g,'').length>0){ n.push(a[i]); }
519
+ }
520
+ return n;
521
+ }
522
+
523
+ };
524
+
525
+ $(window).bind('load', function() {
526
+ Emphasis.init();
527
+ });
528
+
529
+ });
File without changes
@@ -0,0 +1,15 @@
1
+ #=require jquery
2
+ #=require jquery.fancybox
3
+
4
+ jQuery ->
5
+ if $.getDevicePixelRatio() > 1
6
+ $(".fancybox").each ->
7
+ if $(this).data('retina')
8
+ $(this).attr 'href', $(this).data 'retina'
9
+
10
+ $(".fancybox").fancybox
11
+ beforeLoad: ->
12
+ if @element.attributes['data-width']
13
+ @maxWidth = @element.attributes['data-width'].value
14
+ if @element.attributes['data-height']
15
+ @maxHeight = @element.attributes['data-height'].value
@@ -67,7 +67,7 @@
67
67
  }
68
68
 
69
69
  #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
70
- background-image: url('fancybox_sprite.png');
70
+ background-image: url('<%= asset_url("fancybox_sprite.png") %>');
71
71
  }
72
72
 
73
73
  #fancybox-loading {
@@ -85,7 +85,7 @@
85
85
  #fancybox-loading div {
86
86
  width: 44px;
87
87
  height: 44px;
88
- background: url('fancybox_loading.gif') center center no-repeat;
88
+ background: url('<%= asset_url("fancybox_loading.gif") %>') center center no-repeat;
89
89
  }
90
90
 
91
91
  .fancybox-close {
@@ -104,7 +104,7 @@
104
104
  width: 40%;
105
105
  height: 100%;
106
106
  cursor: pointer;
107
- background: transparent url('blank.gif'); /* helps IE */
107
+ background: transparent url('<%= asset_url("blank.gif") %>'); /* helps IE */
108
108
  z-index: 1003;
109
109
  }
110
110
 
@@ -219,4 +219,30 @@
219
219
  padding: 10px;
220
220
  background: #000;
221
221
  background: rgba(0, 0, 0, .8);
222
- }
222
+ }
223
+
224
+ /* Zoom icon*/
225
+ a.fb_zoomable {
226
+ max-width: 100%;
227
+ display:block;
228
+ width:180px;
229
+ height:76px;
230
+ position:relative;
231
+ }
232
+
233
+ a.fb_zoomable span.fb_zoom_icon {
234
+ display:block;
235
+ width:100%;
236
+ height:100%;
237
+ position:absolute;
238
+ top:0;
239
+ left:0;
240
+ background:url(<%= asset_url('zoom_icon.png') %>) no-repeat bottom right;
241
+ opacity:0.3;
242
+ -o-transition:opacity 0.25s;
243
+ -moz-transition:opacity 0.25s;
244
+ -webkit-transition:opacity 0.25s;
245
+ transition:opacity 0.25s;
246
+ }
247
+
248
+ a.fb_zoomable:hover span.fb_zoom_icon {opacity:1}
@@ -0,0 +1,3 @@
1
+ /*
2
+ Empty Javascript file for SublimeVideo
3
+ */
@@ -0,0 +1,28 @@
1
+ a.zoomable {
2
+ max-width: 100%;
3
+ display:block;
4
+ width:180px;
5
+ height:76px;
6
+ background:#000;
7
+ position:relative;
8
+ -webkit-box-shadow:rgba(0,0,0,0.4) 0 4px 10px;
9
+ -moz-box-shadow:rgba(0,0,0,0.4) 0 4px 10px;
10
+ box-shadow:rgba(0,0,0,0.4) 0 4px 10px;
11
+ }
12
+
13
+ a.zoomable span.zoom_icon {
14
+ display:block;
15
+ width:100%;
16
+ height:100%;
17
+ position:absolute;
18
+ top:0;
19
+ left:0;
20
+ background:url(<%= asset_url('zoom_icon.png') %>) no-repeat bottom right;
21
+ opacity:0.3;
22
+ -o-transition:opacity 0.25s;
23
+ -moz-transition:opacity 0.25s;
24
+ -webkit-transition:opacity 0.25s;
25
+ transition:opacity 0.25s;
26
+ }
27
+
28
+ a.zoomable:hover span.zoom_icon {opacity:1}
metadata CHANGED
@@ -1,30 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alula-plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
5
- prerelease:
4
+ version: 0.4.0b
5
+ prerelease: 5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mikko Kokkonen
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-07 00:00:00.000000000 Z
12
+ date: 2012-07-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: alula
16
- requirement: &70241112620360 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0.2'
21
+ version: 0.4.0b
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70241112620360
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.4.0b
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: version
27
- requirement: &70241112619860 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: 1.0.0
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70241112619860
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.0
36
46
  description: Plugins for Alula blog
37
47
  email:
38
48
  - mikko@owlforestry.com
@@ -47,15 +57,26 @@ files:
47
57
  - Rakefile
48
58
  - VERSION
49
59
  - alula-plugins.gemspec
50
- - lib/alula/plugins/lightbox.rb
60
+ - lib/alula/plugins.rb
61
+ - lib/alula/plugins/disqus.rb
62
+ - lib/alula/plugins/emphasis.rb
63
+ - lib/alula/plugins/fancybox.rb
64
+ - lib/alula/plugins/sublimevideo.rb
51
65
  - lib/alula/plugins/version.rb
52
- - plugins/.DS_Store
53
- - plugins/lightbox/javascripts/.DS_Store
54
- - plugins/lightbox/javascripts/jquery.fancybox.js
55
- - plugins/lightbox/javascripts/lightbox.js.coffee
56
- - plugins/lightbox/javascripts/lightbox_body.js
57
- - plugins/lightbox/stylesheets/jquery.fancybox.css
58
- - plugins/lightbox/stylesheets/lightbox.css
66
+ - plugins/disqus/assets/javascripts/disqus.js
67
+ - plugins/disqus/assets/stylesheets/disqus.css
68
+ - plugins/emphasis/assets/javascripts/emphasis.js
69
+ - plugins/emphasis/assets/stylesheets/emphasis.css
70
+ - plugins/fancybox/assets/images/blank.gif
71
+ - plugins/fancybox/assets/images/fancybox_loading.gif
72
+ - plugins/fancybox/assets/images/fancybox_sprite.png
73
+ - plugins/fancybox/assets/images/zoom_icon.png
74
+ - plugins/fancybox/assets/javascripts/fancybox.js.coffee
75
+ - plugins/fancybox/assets/javascripts/jquery.fancybox.js
76
+ - plugins/fancybox/assets/stylesheets/fancybox.css.erb
77
+ - plugins/sublimevideo/assets/images/zoom_icon.png
78
+ - plugins/sublimevideo/assets/javascripts/sublimevideo.js
79
+ - plugins/sublimevideo/assets/stylesheets/sublimevideo.css.erb
59
80
  homepage: ''
60
81
  licenses: []
61
82
  post_install_message:
@@ -71,12 +92,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
92
  required_rubygems_version: !ruby/object:Gem::Requirement
72
93
  none: false
73
94
  requirements:
74
- - - ! '>='
95
+ - - ! '>'
75
96
  - !ruby/object:Gem::Version
76
- version: '0'
97
+ version: 1.3.1
77
98
  requirements: []
78
99
  rubyforge_project:
79
- rubygems_version: 1.8.17
100
+ rubygems_version: 1.8.23
80
101
  signing_key:
81
102
  specification_version: 3
82
103
  summary: Simple, ready to use plugins for Alula blogs.
@@ -1,46 +0,0 @@
1
- module Alula
2
- module Plugins
3
- class Lightbox < Liquid::Tag
4
- def self.install(options)
5
- @@options = options
6
-
7
- # Register custom tag
8
- Liquid::Template.register_tag('lightbox', Alula::Plugins::Lightbox)
9
-
10
- # Register attachment insertion
11
- Alula::Plugins.register_attachment_handler(:image, ->(asset){
12
- "{% lightbox #{asset} %}"
13
- })
14
-
15
- # Return path to assets
16
- File.expand_path(File.join(File.dirname(__FILE__), *%w{.. .. .. plugins lightbox}))
17
- end
18
-
19
- def initialize(tag_name, markup, tokens)
20
- /(?<src>(?:https?:\/\/|\/|\S+\/)\S+)(?<title>\s+.+)?/ =~ markup
21
- /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/ =~ title
22
-
23
- @name = src
24
- @title = title || ""
25
- @alt = alt || ""
26
- end
27
-
28
- def render(context)
29
- asset_path = context.registers[:site].config["asset_path"]
30
- manifest = context.registers[:site].config["manifest"]
31
-
32
- original = File.join(asset_path, manifest.assets[File.join("images", @name)])
33
- thumbnail = File.join(asset_path, manifest.assets[File.join("thumbnails", @name)])
34
-
35
- # Fetch image size
36
- img = Magick::Image.read(File.join("public", thumbnail)).first
37
- width = img.columns
38
- height = img.rows
39
-
40
- tag = "<a class=\"fancybox\" rel=\"#{context.environments.first["page"]["id"]}\" href=\"#{original}\">"
41
- tag += "<img src=\"#{thumbnail}\" alt=\"#{@alt}\" title=\"#{@title}\" width=\"#{width}\" height=\"#{height}\">"
42
- tag += "</a>"
43
- end
44
- end
45
- end
46
- end
data/plugins/.DS_Store DELETED
Binary file
Binary file
@@ -1,5 +0,0 @@
1
- //=require jquery
2
- //=require jquery.fancybox
3
-
4
- jQuery ->
5
- $(".fancybox").fancybox()
@@ -1,3 +0,0 @@
1
- /*
2
- *=require jquery.fancybox
3
- */