diff --git a/.slugignore b/.slugignore new file mode 100644 index 0000000..0a41d01 --- /dev/null +++ b/.slugignore @@ -0,0 +1,3 @@ +plugins +sass +source diff --git a/.themes/classic/source/_includes/asides/delicious.html b/.themes/classic/source/_includes/asides/delicious.html index 560e4af..8c75b82 100644 --- a/.themes/classic/source/_includes/asides/delicious.html +++ b/.themes/classic/source/_includes/asides/delicious.html @@ -1,7 +1,8 @@ {% if site.delicious_user %}

On Delicious

- +
+

My Delicious Bookmarks »

-{% endif %} +{% endif %} \ No newline at end of file diff --git a/.themes/classic/source/_includes/head.html b/.themes/classic/source/_includes/head.html index 16beda3..fd7e236 100644 --- a/.themes/classic/source/_includes/head.html +++ b/.themes/classic/source/_includes/head.html @@ -21,7 +21,7 @@ - + {% include custom/head.html %} diff --git a/.themes/classic/source/_layouts/default.html b/.themes/classic/source/_layouts/default.html index 17c4e66..0b1fc3a 100644 --- a/.themes/classic/source/_layouts/default.html +++ b/.themes/classic/source/_layouts/default.html @@ -1,6 +1,6 @@ {% capture root_url %}{{ site.root | strip_slash }}{% endcapture %} {% include head.html %} - +
{% include header.html %}
diff --git a/.themes/classic/source/javascripts/ender.js b/.themes/classic/source/javascripts/ender.js index 9958885..c5c7c2c 100644 --- a/.themes/classic/source/javascripts/ender.js +++ b/.themes/classic/source/javascripts/ender.js @@ -1,2 +1,38 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('!5(O){5 2j(o,42){F(u k Y 42){k!=\'28\'&&k!=\'4T\'&&(o[k]=42[k])}7 o}5 2P(s,r){u R;B(X.4E&&N s==\'1p\'||s.4R||s.E&&\'3g\'Y s||s==1O){R=X.4E(s,r);R.H=s}1h{R=5F(s.E)?s:[s]}7 2j(R,2P)}5 X(s,r){7 2P(s,r)}2j(X,{4T:\'0.2.0\',X:5(o,4Z){2j(4Z?2P:X,o)}});2j(2P,{6E:5(D,1Z){F(u i=0,l=8.E;i.+?<\\\\/"+t+">","g"));K(5Y,5(m){m=m.1g(/<(.+)>(.+?)<\\/\\1>/,\'$2\');u 4l=I.3e(t);4l.2m(I.7Y(m));6.2m(4l)})}1h{6.4j=G}u 4Q=6.4y;6=6.1C;R.13(6);1d(6=6.25){(6.1j==1)&&R.13(6)}7 R}():4k(G)?[G.66(19)]:[]};U.I=5(){u w=W.6s,h=W.6v,4s=8.63();7{1N:65.62(w,4s.1N),1I:65.62(h,4s.1I)}};U.1C=5(6){F(u c=6.4y,i=0,j=(c&&c.E)||0,e;i\\{\\}\\$\\*\\^\'"]*\\])/,5X=/([.*+?\\^=!:${}()|\\[\\]\\/\\\\])/g,4W=/^([a-6J-9]+)?(?:([\\.\\#]+[\\w\\-\\.#]+)?)/,3y=/\\[([\\w\\-]+)(?:([\\|\\^\\$\\*\\~]?\\=)[\'"]?([ \\w\\-\\/\\?\\&\\=\\:\\.\\(\\)\\!,@#%<>\\{\\}\\$\\*\\^]+)["\']?)?\\]/,6g=1a 1E(4W.6l+\'(\'+3y.6l+\')?\');5 1R(Q){r=[];F(i=0,3W=Q.E;i<3W;i++){r[i]=Q[i]}7 r}u 2o=5(){8.c={}};2o.2g={g:5(k){7 8.c[k]||1w},s:5(k,v){8.c[k]=v;7 v}};u 30=1a 2o(),4i=1a 2o(),1x=1a 2o(),3Q=1a 2o();5 q(2n){7 2n.1c(6g)}5 3H(6y,1n,2Z,4t,4n,60,1l){u m,c,k;B(1n&&8.3T.6f()!==1n){7 1i}B(2Z&&(m=2Z.1c(2i))&&m[1]!==8.2i){7 1i}B(2Z&&(3x=2Z.1c(6j))){F(i=3x.E;i--;){c=3x[i].3u(1);B(!(30.g(c)||30.s(c,1a 1E(\'(^|\\\\s+)\'+c+\'(\\\\s+|$)\'))).12(8.1q)){7 1i}}}B(4t&&!1l){o=8.6T;F(k Y o){B(6O.2g.1T.11(o,k)&&(o[k].73||k)==4n){7 8}}}B(4t&&!5W(60,8.1S(4n)||\'\',1l)){7 1i}7 8}5 64(1s){u r=[],4B=1s.81(),4G=q(4B),1n=4G[1]||\'*\',i,l,R,V=1s.E&&(m=1s[0].1c(4a))?I.47(m[1]):I;B(!V){7 r}R=V.3o(1n);F(i=0,l=R.E;i]+)/.exec(a),d=c.createElement(b&&k[b[1].toLowerCase()]||"div"),e=[];d.innerHTML=a;var f=d.childNodes;d=d.firstChild,e.push(d);while(d=d.nextSibling)d.nodeType==1&&e.push(d);return e}():A(a)?[a.cloneNode(!0)]:[]},N.doc=function(){var a=this.viewport();return{width:Math.max(c.body.scrollWidth,d.scrollWidth,a.width),height:Math.max(c.body.scrollHeight,d.scrollHeight,a.height)}},N.firstChild=function(a){for(var b=a.childNodes,c=0,d=b&&b.length||0,e;c])\s*/g,B=/[\s\>\+\~]/,C=/(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/,D=/([.*+?\^=!:${}()|\[\]\/\\])/g,E=/^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,F=/\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,G=/:([\w\-]+)(\(['"]?([\s\w\+\-]+)['"]?\))?/,H=new RegExp("("+B.source+")"+C.source,"g"),I=new RegExp(B.source+C.source),J=new RegExp(E.source+"("+F.source+")?"+"("+G.source+")?"),K={" ":function(a){return a&&a!==t&&a.parentNode},">":function(a,b){return a&&a.parentNode==b.parentNode&&a.parentNode},"~":function(a){return a&&a.previousSibling},"+":function(a,b,c,d){if(!a)return!1;c=R(a),d=R(b);return c&&d&&c==d&&c}};L.prototype={g:function(a){return this.c[a]||undefined},s:function(a,b){this.c[a]=b;return b}};var M=new L,N=new L,O=new L,P=new L,ba="compareDocumentPosition"in t?function(a,b){return(b.compareDocumentPosition(a)&16)==16}:"contains"in t?function(a,c){c=c==b||c==window?t:c;return c!==a&&c.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0},bb=function(){if(!b.querySelector||!b.querySelectorAll)return!1;try{return b.querySelectorAll(":nth-of-type(1)").length>0}catch(a){return!1}}(),bc=bb?function(a,c){return b.getElementsByClassName&&(h=a.match(x))?Q(c.getElementsByClassName(h[1])):Q(c.querySelectorAll(a))}:function(a,c){a=a.replace(A,"$1");var d=[],f,i,j=[],l;if(h=a.match(z)){r=c.getElementsByTagName(h[1]||"*"),k=M.g(h[2])||M.s(h[2],new RegExp("(^|\\s+)"+h[2]+"(\\s+|$)"));for(l=0,g=r.length,e=0;l]+)/.exec(b)[1],f=(c||a).createElement(e[d]||"div"),g=[];f.innerHTML=b;var h=f.childNodes;f=f.firstChild,g.push(f);while(f=f.nextSibling)f.nodeType==1&&g.push(f);return g}var c=require("qwery"),d="table",e={thead:d,tbody:d,tfoot:d,tr:"tbody",th:"tr",td:"tr",fieldset:"form",option:"select"};b._select=function(a,b){return/^\s*'+repos[i].name+'

'+repos[i].description+'

'; - - t.innerHTML = fragment; + for(i = 0; i < repos.length; i++) { + fragment += '
  • '+repos[i].name+'

    '+repos[i].description+'

  • '; } - return { - showRepos: function(options){ - var feed = new jXHR(); - feed.onerror = function (msg,url) { - $(options.target + ' li.loading').addClass('error').text("Error loading feed"); - } - feed.onreadystatechange = function(data){ - if (feed.readyState === 4) { - var repos = []; - var i; - for (i = 0; i < data.repositories.length; i++){ - if (options.skip_forks && data.repositories[i].fork) - continue; - repos.push(data.repositories[i]); - } - repos.sort(function(a, b){ - var a = new Date(a.pushed_at), - b = new Date(b.pushed_at); + t.innerHTML = fragment; + } + return { + showRepos: function(options){ + var feed = new jXHR(); + feed.onerror = function (msg,url) { + $(options.target + ' li.loading').addClass('error').text("Error loading feed"); + }; + feed.onreadystatechange = function(data) { + if (feed.readyState === 4) { + var repos = []; + for (var i = 0; i < data.repositories.length; i++){ + if (options.skip_forks && data.repositories[i].fork) { continue; } + repos.push(data.repositories[i]); + } + repos.sort(function(a, b) { + var aDate = new Date(a.pushed_at).valueOf(), + bDate = new Date(b.pushed_at).valueOf(); - if (a.valueOf() == b.valueOf()) return 0; - return a.valueOf() > b.valueOf() ? -1 : 1; - }); + if (aDate === bDate) { return 0; } + return aDate > bDate ? -1 : 1; + }); - if (options.count) - repos.splice(options.count); - - render(options.target, repos) - } - }; - feed.open("GET","http://github.com/api/v2/json/repos/show/"+options.user+"?callback=?"); - feed.send(); + if (options.count) { repos.splice(options.count); } + render(options.target, repos); } - }; + }; + feed.open("GET","http://github.com/api/v2/json/repos/show/"+options.user+"?callback=?"); + feed.send(); + } + }; })(); \ No newline at end of file diff --git a/.themes/classic/source/javascripts/octopress.js b/.themes/classic/source/javascripts/octopress.js index a23ab50..c369625 100644 --- a/.themes/classic/source/javascripts/octopress.js +++ b/.themes/classic/source/javascripts/octopress.js @@ -1,24 +1,27 @@ function getNav() { var mobileNav = $('nav[role=navigation] fieldset[role=search]').after('
    ').next().append(''); mobileNav.children('select').append(''); + $('ul[role=main-navigation]').addClass('main-navigation'); $('ul.main-navigation a').each(function(link) { mobileNav.children('select').append(''); }); mobileNav.children('select').bind('change', function(event) { - if (event.target.value) window.location.href = event.target.value; + if (event.target.value) { window.location.href = event.target.value; } }); } function addSidebarToggler() { - $('#content').append(''); - $('.toggle-sidebar').bind('click', function(e) { - e.preventDefault(); - if ($('body').hasClass('collapse-sidebar')) { - $('body').removeClass('collapse-sidebar'); - } else { - $('body').addClass('collapse-sidebar'); - } - }); + if(!$('body').hasClass('sidebar-footer')) { + $('#content').append(''); + $('.toggle-sidebar').bind('click', function(e) { + e.preventDefault(); + if ($('body').hasClass('collapse-sidebar')) { + $('body').removeClass('collapse-sidebar'); + } else { + $('body').addClass('collapse-sidebar'); + } + }); + } var sections = $('aside.sidebar > section'); if (sections.length > 1) { sections.each(function(section, index){ @@ -49,7 +52,7 @@ function testFeatures() { } function addCodeLineNumbers() { - if (navigator.appName == 'Microsoft Internet Explorer') { return; } + if (navigator.appName === 'Microsoft Internet Explorer') { return; } $('div.gist-highlight').each(function(code) { var tableStart = '
    ', lineNumbers = '
    ',
    @@ -69,7 +72,7 @@ function flashVideoFallback(){
           flashplayerskin = "/assets/jwplayer/glow/glow.xml";
       $('video').each(function(video){
         video = $(video);
    -    if (!Modernizr.video.h264 && swfobject.getFlashPlayerVersion() || window.location.hash.indexOf("flash-test") != -1){
    +    if (!Modernizr.video.h264 && swfobject.getFlashPlayerVersion() || window.location.hash.indexOf("flash-test") !== -1){
           video.children('source[src$=mp4]').first().map(function(source){
             var src = $(source).attr('src'),
                 id = 'video_'+Math.round(1 + Math.random()*(100000)),
    @@ -89,7 +92,7 @@ function flashVideoFallback(){
     function wrapFlashVideos() {
       $('object').each(function(object) {
         object = $(object);
    -    if (object.children('param[name=movie]')) {
    +    if ( $('param[name=movie]', object).length ) {
           var wrapper = object.before('
    ').previous(); $(wrapper).children().append(object); } @@ -101,6 +104,15 @@ function wrapFlashVideos() { }); } +function renderDeliciousLinks(items) { + var output = "
      "; + for (var i=0,l=items.length; i' + items[i].d + ''; + } + output += "
    "; + $('#delicious').html(output); +} + $.domReady(function() { testFeatures(); wrapFlashVideos(); diff --git a/.themes/classic/source/javascripts/twitter.js b/.themes/classic/source/javascripts/twitter.js index a4e8555..ea1580e 100644 --- a/.themes/classic/source/javascripts/twitter.js +++ b/.themes/classic/source/javascripts/twitter.js @@ -1,43 +1,5 @@ // JSON-P Twitter fetcher for Octopress // (c) Brandon Mathis // MIT Lisence -function getTwitterFeed(user, count, replies) { - var feed = new jXHR(); - - feed.onerror = function (msg,url) { - $('#tweets li.loading').addClass('error').text("Twitter's busted"); - } - feed.onreadystatechange = function(data){ - if (feed.readyState === 4) { - var tweets = new Array(); - var i = 0; - for (i in data){ - if(tweets.length < count){ - if(replies || data[i].in_reply_to_user_id == null){ - tweets.push(data[i]); - } - } - } - showTwitterFeed(tweets, user); - } - }; - feed.open("GET","http://twitter.com/statuses/user_timeline/"+user+".json?trim_user=true&count="+(parseInt(count)+60)+"&callback=?"); - feed.send(); -} - -function showTwitterFeed(tweets, twitter_user){ - var timeline = document.getElementById('tweets'); - timeline.innerHTML=''; - for (t in tweets){ - timeline.innerHTML+='
  • '+'

    '+''+prettyDate(tweets[t].created_at)+''+linkifyTweet(tweets[t].text.replace(/\n/g, '
    '))+'

    '+'
  • '; - } -} -function linkifyTweet(text){ - return text.replace(/(https?:\/\/)([\w\-:;?&=+.%#\/]+)/gi, '$2') - .replace(/(^|\W)@(\w+)/g, '$1@$2') - .replace(/(^|\W)#(\w+)/g, '$1#$2'); -} - - // jXHR.js (JSON-P XHR) | v0.1 (c) Kyle Simpson | MIT License | http://mulletxhr.com/ // uncompressed version available in source/javascripts/libs/jXHR.js @@ -45,38 +7,71 @@ function linkifyTweet(text){ /* Sky Slavin, Ludopoli. MIT license. * based on JavaScript Pretty Date * Copyright (c) 2008 John Resig (jquery.com) * Licensed under the MIT license. */ - function prettyDate(time) { - if (navigator.appName == 'Microsoft Internet Explorer') { + if (navigator.appName === 'Microsoft Internet Explorer') { return ""; // because IE date parsing isn't fun. + } + + var say = { + just_now: " now", + minute_ago: "1m", + minutes_ago: "m", + hour_ago: "1h", + hours_ago: "h", + yesterday: "1d", + days_ago: "d", + weeks_ago: "w" }; - var say = {}; - say.just_now = " now", - say.minute_ago = "1m", - say.minutes_ago = "m", - say.hour_ago = "1h", - say.hours_ago = "h", - say.yesterday = "1d", - say.days_ago = "d", - say.weeks_ago = "w" + var current_date = new Date(), + current_date_time = current_date.getTime(), + current_date_full = current_date_time + (1 * 60000), + date = new Date(time), + diff = ((current_date_full - date.getTime()) / 1000), + day_diff = Math.floor(diff / 86400); - var current_date = new Date(); - current_date_time = current_date.getTime(); - current_date_full = current_date_time + (1 * 60000); - var date = new Date(time); - var diff = ((current_date_full - date.getTime()) / 1000); - var day_diff = Math.floor(diff / 86400); + if (isNaN(day_diff) || day_diff < 0) { return ""; } - if (isNaN(day_diff) || day_diff < 0) return ""; - - return day_diff == 0 && ( + return day_diff === 0 && ( diff < 60 && say.just_now || diff < 120 && say.minute_ago || diff < 3600 && Math.floor(diff / 60) + say.minutes_ago || diff < 7200 && say.hour_ago || diff < 86400 && Math.floor(diff / 3600) + say.hours_ago) || - day_diff == 1 && say.yesterday || + day_diff === 1 && say.yesterday || day_diff < 7 && day_diff + say.days_ago || day_diff > 7 && Math.ceil(day_diff / 7) + say.weeks_ago; } + +function linkifyTweet(text, url) { + for (var u in url) { + var shortUrl = new RegExp(url[u].url, 'g'); + text = text.replace(shortUrl, '' + url[u].expanded_url.replace(/https?:\/\//, '') + ''); + } + return text.replace(/(^|\W)@(\w+)/g, '$1@$2') + .replace(/(^|\W)#(\w+)/g, '$1#$2'); +} + +function showTwitterFeed(tweets, twitter_user) { + var timeline = document.getElementById('tweets'), + content = ''; + + for (var t in tweets) { + content += '
  • '+'

    '+''+prettyDate(tweets[t].created_at)+''+linkifyTweet(tweets[t].text.replace(/\n/g, '
    '), tweets[t].entities.urls)+'

    '+'
  • '; + } + timeline.innerHTML = content; +} + +function getTwitterFeed(user, count, replies) { + var feed = new jXHR(); + feed.onerror = function (msg,url) { + $('#tweets li.loading').addClass('error').text("Twitter's busted"); + }; + feed.onreadystatechange = function(data){ + if (feed.readyState === 4) { showTwitterFeed(data, user); } + }; + + // Documentation: https://dev.twitter.com/docs/api/1/get/statuses/user_timeline + feed.open("GET","http://api.twitter.com/1/statuses/user_timeline/" + user + ".json?trim_user=true&count=" + (parseInt(count, 10)) + "&include_entities=1&exclude_replies=" + (replies ? "0" : "1") + "&callback=?"); + feed.send(); +} \ No newline at end of file diff --git a/Rakefile b/Rakefile index 3457134..eb0dc41 100644 --- a/Rakefile +++ b/Rakefile @@ -218,7 +218,7 @@ end desc "Deploy website via rsync" task :rsync do puts "## Deploying website via Rsync" - ok_failed system("rsync -avz --delete #{public_dir}/ #{ssh_user}:#{document_root}") + ok_failed system("rsync -avze 'ssh -p #{ssh_port}' --delete #{public_dir}/ #{ssh_user}:#{document_root}") end desc "deploy public directory to github pages" @@ -227,6 +227,7 @@ multitask :push do (Dir["#{deploy_dir}/*"]).each { |f| rm_rf(f) } Rake::Task[:copydot].invoke(public_dir, deploy_dir) puts "\n## copying #{public_dir} to #{deploy_dir}" + system "cp -R #{public_dir}/* #{deploy_dir}" cd "#{deploy_dir}" do system "git add ." system "git add -u" @@ -234,7 +235,7 @@ multitask :push do message = "Site updated at #{Time.now.utc}" system "git commit -m \"#{message}\"" puts "\n## Pushing generated #{deploy_dir} website" - system "git push origin #{deploy_branch}" + system "git push origin #{deploy_branch} --force" puts "\n## Github Pages deploy complete" end end @@ -274,25 +275,54 @@ task :set_root_dir, :dir do |t, args| end end -desc "Setup _deploy folder and deploy branch" -task :config_deploy, :branch do |t, args| - puts "!! Please provide a deploy branch, eg. rake init_deploy[gh-pages] !!" unless args.branch - puts "## Creating a clean #{args.branch} branch in ./#{deploy_dir} for Github pages deployment" +desc "Set up _deploy folder and deploy branch for Github Pages deployment" +task :setup_github_pages do + repo_url = get_stdin("Enter the read/write url for your repository: ") + user = repo_url.match(/:([^\/]+)/)[1] + branch = (repo_url.match(/\/\w+.github.com/).nil?) ? 'gh-pages' : 'master' + project = (branch == 'gh-pages') ? repo_url.match(/\/([^\.]+)/)[1] : '' + unless `git remote -v`.match(/origin.+?octopress.git/).nil? + # If octopress is still the origin remote (from cloning) rename it to octopress + system "git remote rename origin octopress" + if branch == 'master' + # If this is a user/organization pages repository, add the correct origin remote + # and checkout the source branch for committing changes to the blog source. + system "git remote add origin #{repo_url}" + puts "Added remote #{repo_url} as origin" + system "git config branch.master.remote origin" + puts "Set origin as default remote" + system "git branch -m master source" + puts "Master branch renamed to 'source' for committing your blog source files" + else + unless !public_dir.match("#{project}").nil? + system "rake set_root_dir[#{project}]" + end + end + end + url = "http://#{user}.github.com" + url += "/#{project}" unless project == '' + jekyll_config = IO.read('_config.yml') + jekyll_config.sub!(/^url:.*$/, "url: #{url}") + File.open('_config.yml', 'w') do |f| + f.write jekyll_config + end + rm_rf deploy_dir + mkdir deploy_dir cd "#{deploy_dir}" do - system "git symbolic-ref HEAD refs/heads/#{args.branch}" - system "rm .git/index" - system "git clean -fdx" + system "git init" system "echo 'My Octopress Page is coming soon …' > index.html" system "git add ." system "git commit -m \"Octopress init\"" + system "git branch -m gh-pages" unless branch == 'master' + system "git remote add origin #{repo_url}" rakefile = IO.read(__FILE__) - rakefile.sub!(/deploy_branch(\s*)=(\s*)(["'])[\w-]*["']/, "deploy_branch\\1=\\2\\3#{args.branch}\\3") + rakefile.sub!(/deploy_branch(\s*)=(\s*)(["'])[\w-]*["']/, "deploy_branch\\1=\\2\\3#{branch}\\3") rakefile.sub!(/deploy_default(\s*)=(\s*)(["'])[\w-]*["']/, "deploy_default\\1=\\2\\3push\\3") File.open(__FILE__, 'w') do |f| f.write rakefile end end - puts "## Deployment configured. Now you can deploy to the #{args.branch} branch with `rake deploy` ##" + puts "\n---\n## Now you can deploy to #{url} with `rake deploy` ##" end def ok_failed(condition) diff --git a/plugins/image_tag.rb b/plugins/image_tag.rb index 25a38df..20595cb 100644 --- a/plugins/image_tag.rb +++ b/plugins/image_tag.rb @@ -1,46 +1,47 @@ # Title: Simple Image tag for Jekyll -# Author: Brandon Mathis http://brandonmathis.com -# Description: Easily output images with optional class names and title/alt attributes +# Authors: Brandon Mathis http://brandonmathis.com +# Felix Schäfer, Frederic Hemberger +# Description: Easily output images with optional class names, width, height, title and alt attributes # -# Syntax {% image [class name(s)] url [title text] %} +# Syntax {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %} # -# Example: -# {% ima left half http://site.com/images/ninja.png Ninja Attack! %} +# Examples: +# {% img /images/ninja.png Ninja Attack! %} +# {% img left half http://site.com/images/ninja.png Ninja Attack! %} +# {% img left half http://site.com/images/ninja.png 150 150 "Ninja Attack!" "Ninja in attack posture" %} # # Output: -# Ninja Attack! +# +# Ninja Attack! +# Ninja in attack posture # module Jekyll class ImageTag < Liquid::Tag @img = nil - @title = nil - @class = '' - @width = '' - @height = '' def initialize(tag_name, markup, tokens) - if markup =~ /(\S.*\s+)?(https?:\/\/|\/)(\S+)(\s+\d+\s+\d+)?(\s+.+)?/i - @class = $1 || '' - @img = $2 + $3 - if $5 - @title = $5.strip - end - if $4 =~ /\s*(\d+)\s+(\d+)/ - @width = $1 - @height = $2 + attributes = ['class', 'src', 'width', 'height', 'title'] + + if markup =~ /(?\S.*\s+)?(?(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?\d+))?(?:\s+(?\d+))?(?\s+.+)?/i + @img = attributes.reduce({}) { |img, attr| img[attr] = $~[attr].strip if $~[attr]; img } + if /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/ =~ @img['title'] + @img['title'] = title + @img['alt'] = alt + else + @img['alt'] = @img['title'].gsub!(/"/, '"') end + @img['class'].gsub!(/"/, '') end super end def render(context) - output = super if @img - "<img class='#{@class}' src='#{@img}' width='#{@width}' height='#{@height}' alt='#{@title}' title='#{@title}'>" + "<img #{@img.collect {|k,v| "#{k}=\"#{v}\"" if v}.join(" ")}>" else - "Error processing input, expected syntax: {% img [class name(s)] /url/to/image [width height] [title text] %}" + "Error processing input, expected syntax: {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | \"title text\" [\"alt text\"]] %}" end end end diff --git a/plugins/jsfiddle.rb b/plugins/jsfiddle.rb new file mode 100644 index 0000000..3ae173e --- /dev/null +++ b/plugins/jsfiddle.rb @@ -0,0 +1,40 @@ +# Title: jsFiddle tag for Jekyll +# Author: Brian Arnold (@brianarn) +# Description: +# Given a jsFiddle shortcode, outputs the jsFiddle iframe code. +# Using 'default' will preserve defaults as specified by jsFiddle. +# +# Syntax: {% jsfiddle shorttag [tabs] [skin] [height] [width] %} +# +# Examples: +# +# Input: {% jsfiddle ccWP7 %} +# Output: <iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/ccWP7/embedded/js,resources,html,css,result/light/"></iframe> +# +# Input: {% jsfiddle ccWP7 js,html,result %} +# Output: <iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/ccWP7/embedded/js,html,result/light/"></iframe> +# + +module Jekyll + class JsFiddle < Liquid::Tag + def initialize(tag_name, markup, tokens) + if /(?<fiddle>\w+)(?:\s+(?<sequence>[\w,]+))?(?:\s+(?<skin>\w+))?(?:\s+(?<height>\w+))?(?:\s+(?<width>\w+))?/ =~ markup + @fiddle = fiddle + @sequence = (sequence unless sequence == 'default') || 'js,resources,html,css,result' + @skin = (skin unless skin == 'default') || 'light' + @width = width || '100%' + @height = height || '300px' + end + end + + def render(context) + if @fiddle + "<iframe style=\"width: #{@width}; height: #{@height}\" src=\"http://jsfiddle.net/#{@fiddle}/embedded/#{@sequence}/#{@skin}/\"></iframe>" + else + "Error processing input, expected syntax: {% jsfiddle shorttag [tabs] [skin] [height] [width] %}" + end + end + end +end + +Liquid::Template.register_tag('jsfiddle', Jekyll::JsFiddle) \ No newline at end of file