alula-plugins 0.1.1 → 0.4.0b

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 (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
- */