jekyll 2.0.0.alpha.1 → 2.0.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jekyll might be problematic. Click here for more details.

Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -0
  3. data/.travis.yml +27 -0
  4. data/History.markdown +66 -1
  5. data/LICENSE +2 -2
  6. data/README.markdown +2 -2
  7. data/Rakefile +4 -44
  8. data/bin/jekyll +10 -113
  9. data/docs/jp/CONTRIBUTING.jp.markdown +93 -0
  10. data/docs/jp/README.jp.markdown +69 -0
  11. data/features/create_sites.feature +12 -12
  12. data/features/drafts.feature +23 -2
  13. data/features/embed_filters.feature +7 -5
  14. data/features/include_tag.feature +7 -7
  15. data/features/markdown.feature +4 -4
  16. data/features/pagination.feature +2 -2
  17. data/features/permalinks.feature +7 -7
  18. data/features/post_data.feature +21 -21
  19. data/features/post_excerpts.feature +6 -6
  20. data/features/site_configuration.feature +17 -17
  21. data/features/site_data.feature +15 -15
  22. data/features/step_definitions/jekyll_steps.rb +4 -4
  23. data/features/support/env.rb +2 -2
  24. data/jekyll.gemspec +17 -284
  25. data/lib/jekyll.rb +21 -5
  26. data/lib/jekyll/command.rb +72 -20
  27. data/lib/jekyll/commands/build.rb +82 -58
  28. data/lib/jekyll/commands/docs.rb +30 -0
  29. data/lib/jekyll/commands/doctor.rb +18 -1
  30. data/lib/jekyll/commands/new.rb +19 -6
  31. data/lib/jekyll/commands/serve.rb +80 -49
  32. data/lib/jekyll/configuration.rb +3 -3
  33. data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -1
  34. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +1 -0
  35. data/lib/jekyll/convertible.rb +19 -21
  36. data/lib/jekyll/draft.rb +5 -0
  37. data/lib/jekyll/excerpt.rb +5 -5
  38. data/lib/jekyll/layout.rb +2 -2
  39. data/lib/jekyll/layout_reader.rb +15 -2
  40. data/lib/jekyll/page.rb +17 -17
  41. data/lib/jekyll/post.rb +33 -33
  42. data/lib/jekyll/related_posts.rb +5 -5
  43. data/lib/jekyll/site.rb +84 -85
  44. data/lib/jekyll/static_file.rb +13 -0
  45. data/lib/jekyll/stevenson.rb +1 -1
  46. data/lib/jekyll/tags/highlight.rb +16 -6
  47. data/lib/jekyll/tags/include.rb +17 -17
  48. data/lib/jekyll/url.rb +2 -0
  49. data/lib/jekyll/utils.rb +79 -0
  50. data/lib/jekyll/version.rb +3 -0
  51. data/lib/site_template/_config.yml +3 -1
  52. data/lib/site_template/_includes/footer.html +61 -0
  53. data/lib/site_template/_includes/head.html +12 -0
  54. data/lib/site_template/_includes/header.html +27 -0
  55. data/lib/site_template/_layouts/default.html +9 -34
  56. data/lib/site_template/_layouts/page.html +14 -0
  57. data/lib/site_template/_layouts/post.html +11 -5
  58. data/lib/site_template/_posts/0000-00-00-this-post-demonstrates-post-content-styles.md +88 -0
  59. data/lib/site_template/about/index.md +10 -0
  60. data/lib/site_template/css/main.css +333 -100
  61. data/lib/site_template/feed.xml +21 -0
  62. data/lib/site_template/index.html +8 -4
  63. data/lib/site_template/projects/index.md +14 -0
  64. data/script/cibuild +0 -1
  65. data/script/rebund +1 -1
  66. data/site/_includes/analytics.html +2 -2
  67. data/site/_includes/css/normalize.css +1 -1
  68. data/site/_includes/css/style.css +28 -4
  69. data/site/_includes/docs_option.html +1 -1
  70. data/site/_includes/docs_ul.html +3 -3
  71. data/site/_includes/footer.html +1 -1
  72. data/site/_includes/header.html +2 -2
  73. data/site/_includes/news_item.html +1 -1
  74. data/site/_includes/primary-nav-items.html +4 -4
  75. data/site/_includes/section_nav.html +2 -2
  76. data/site/_includes/top.html +6 -7
  77. data/site/_layouts/news_item.html +1 -1
  78. data/site/_posts/2013-07-25-jekyll-1-0-4-released.markdown +1 -1
  79. data/site/_posts/2013-07-25-jekyll-1-1-2-released.markdown +1 -1
  80. data/site/_posts/2013-09-14-jekyll-1-2-1-released.markdown +1 -1
  81. data/site/_posts/2014-03-24-jekyll-1-5-0-released.markdown +19 -0
  82. data/site/docs/assets.md +14 -0
  83. data/site/docs/configuration.md +65 -56
  84. data/site/docs/contributing.md +7 -2
  85. data/site/docs/deployment-methods.md +1 -1
  86. data/site/docs/github-pages.md +1 -1
  87. data/site/docs/history.md +21 -0
  88. data/site/docs/index.md +7 -1
  89. data/site/docs/installation.md +28 -0
  90. data/site/docs/migrations.md +1 -1
  91. data/site/docs/plugins.md +6 -0
  92. data/site/docs/structure.md +3 -3
  93. data/site/docs/templates.md +44 -44
  94. data/site/docs/usage.md +1 -1
  95. data/site/docs/variables.md +15 -2
  96. data/site/favicon.png +0 -0
  97. data/site/feed.xml +0 -1
  98. data/site/img/article-footer.png +0 -0
  99. data/site/img/footer-arrow.png +0 -0
  100. data/site/img/footer-logo.png +0 -0
  101. data/site/img/logo-2x.png +0 -0
  102. data/site/img/octojekyll.png +0 -0
  103. data/site/img/tube.png +0 -0
  104. data/site/img/tube1x.png +0 -0
  105. data/site/index.html +5 -5
  106. data/site/js/modernizr-2.7.1.min.js +4 -0
  107. data/test/helper.rb +11 -0
  108. data/test/source/_drafts/draft-properties.text +11 -0
  109. data/test/source/_posts/2011-04-12-md-extension.md +1 -1
  110. data/test/source/_posts/2014-01-06-permalink-traversal.md +5 -0
  111. data/test/source/exploit.md +5 -0
  112. data/test/source/static_files.html +4 -0
  113. data/test/test_configuration.rb +2 -2
  114. data/test/test_draft.rb +56 -0
  115. data/test/test_excerpt.rb +2 -2
  116. data/test/test_filters.rb +1 -1
  117. data/test/test_generated_site.rb +10 -1
  118. data/test/test_kramdown.rb +1 -1
  119. data/test/test_layout_reader.rb +17 -0
  120. data/test/test_page.rb +10 -0
  121. data/test/test_pager.rb +4 -2
  122. data/test/test_path_sanitization.rb +14 -0
  123. data/test/test_post.rb +12 -1
  124. data/test/test_sass.rb +1 -64
  125. data/test/test_site.rb +26 -1
  126. data/test/test_tags.rb +39 -2
  127. data/test/{test_core_ext.rb → test_utils.rb} +12 -12
  128. metadata +200 -86
  129. data/lib/jekyll/converters/sass.rb +0 -58
  130. data/lib/jekyll/core_ext.rb +0 -55
  131. data/lib/site_template/css/syntax.css +0 -60
  132. data/site/js/modernizr-2.5.3.min.js +0 -4
Binary file
Binary file
Binary file
@@ -18,19 +18,19 @@ overview: true
18
18
  <p>
19
19
  No more databases, comment moderation, or pesky updates to install—just <em>your content</em>.
20
20
  </p>
21
- <a href="/docs/usage/" class="">How Jekyll works &rarr;</a>
21
+ <a href="/docs/usage/">How Jekyll works &rarr;</a>
22
22
  </div>
23
23
  <div class="unit one-third">
24
24
  <h2>Static</h2>
25
25
  <p><a href="http://daringfireball.net/projects/markdown/">Markdown</a> (or <a href="http://textile.sitemonks.com/">Textile</a>), <a href="http://wiki.shopify.com/Liquid">Liquid</a>, HTML <span class="amp">&amp;</span> CSS go in. Static sites come out ready for deployment.</p>
26
- <a href="/docs/templates/" class="">Jekyll template guide &rarr;</a>
26
+ <a href="/docs/templates/">Jekyll template guide &rarr;</a>
27
27
  </div>
28
28
  <div class="unit one-third">
29
29
  <h2>Blog-aware</h2>
30
30
  <p>
31
31
  Permalinks, categories, pages, posts, and custom layouts are all first-class citizens here.
32
32
  </p>
33
- <a href="/docs/migrations/" class="">Migrate your blog &rarr;</a>
33
+ <a href="/docs/migrations/">Migrate your blog &rarr;</a>
34
34
  </div>
35
35
  <div class="clear"></div>
36
36
  </div>
@@ -76,11 +76,11 @@ overview: true
76
76
  <div class="unit whole">
77
77
  <div class="grid pane">
78
78
  <div class="unit whole center-on-mobiles">
79
- <img src="img/octojekyll.png" alt="Free Jekyll hosting on GitHub Pages">
79
+ <img src="img/octojekyll.png" width="300" height="251" alt="Free Jekyll hosting on GitHub Pages">
80
80
  <div class="pane-content">
81
81
  <h2 class="center-on-mobiles"><strong>Free hosting</strong> with GitHub Pages</h2>
82
82
  <p>Sick of dealing with hosting companies? <a href="http://pages.github.com/">GitHub Pages</a> are <em>powered by Jekyll</em>, so you can easily deploy your site using GitHub for free&mdash;<a href="https://help.github.com/articles/setting-up-a-custom-domain-with-pages">custom domain name</a> and&nbsp;all.</p>
83
- <a href="http://pages.github.com/" class="">Learn more about GitHub Pages &rarr;</a>
83
+ <a href="http://pages.github.com/">Learn more about GitHub Pages &rarr;</a>
84
84
  </div>
85
85
  </div>
86
86
  <div class="clear"></div>
@@ -0,0 +1,4 @@
1
+ /* Modernizr 2.7.1 (Custom Build) | MIT & BSD
2
+ * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
3
+ */
4
+ ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.7.1",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function q(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return s.shivMethods?o(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(s,b.frag)}function r(a){a||(a=b);var c=n(a);return s.shivCSS&&!g&&!c.hasCSS&&(c.hasCSS=!!l(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||q(a,c),a}var c="3.7.0",d=a.html5||{},e=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,f=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,g,h="_html5shiv",i=0,j={},k;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
@@ -28,6 +28,17 @@ STDERR.reopen(test(?e, '/dev/null') ? '/dev/null' : 'NUL:')
28
28
  class Test::Unit::TestCase
29
29
  include RR::Adapters::TestUnit
30
30
 
31
+ def build_configs(overrides, base_hash = Jekyll::Configuration::DEFAULTS)
32
+ Utils.deep_merge_hashes(base_hash, overrides)
33
+ end
34
+
35
+ def site_configuration(overrides = {})
36
+ build_configs({
37
+ "source" => source_dir,
38
+ "destination" => dest_dir
39
+ }, build_configs(overrides))
40
+ end
41
+
31
42
  def dest_dir(*subdirs)
32
43
  test_dir('dest', *subdirs)
33
44
  end
@@ -0,0 +1,11 @@
1
+ ---
2
+ categories: foo bar baz
3
+ foo: bar
4
+ layout: default
5
+ tags: ay bee cee
6
+ title: Properties Draft
7
+ ---
8
+
9
+ All the properties.
10
+
11
+ Plus an excerpt.
@@ -2,6 +2,6 @@
2
2
  date: 2011-04-12 13:07:09
3
3
  ---
4
4
 
5
- under default configuration, this post should get processed by the identity converter. By changing
5
+ under default configuration, this post should get processed by the identity converter. By changing
6
6
  textile extension or markdown extension configuration parameters, you should be able to associate
7
7
  it with either of those converters
@@ -0,0 +1,5 @@
1
+ ---
2
+ permalink: /%2e%2e/%2e%2e/%2e%2e/baddie.html
3
+ ---
4
+
5
+ # Test
@@ -0,0 +1,5 @@
1
+ ---
2
+ permalink: /%2e%2e/%2e%2e/%2e%2e/baddie.html
3
+ ---
4
+
5
+ # Test
@@ -0,0 +1,4 @@
1
+ ---
2
+ ---
3
+ {% for file in site.static_files %}
4
+ - {{ file.path }} last edited at {{ file.modified_time }} with extname {{ file.extname }}{% endfor %}
@@ -156,7 +156,7 @@ class TestConfiguration < Test::Unit::TestCase
156
156
  should "load different config if specified" do
157
157
  mock(SafeYAML).load_file(@paths[:other]) { {"baseurl" => "http://wahoo.dev"} }
158
158
  mock($stdout).puts("Configuration file: #{@paths[:other]}")
159
- assert_equal Jekyll::Configuration::DEFAULTS.deep_merge({ "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => @paths[:other] })
159
+ assert_equal Utils.deep_merge_hashes(Jekyll::Configuration::DEFAULTS, { "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => @paths[:other] })
160
160
  end
161
161
 
162
162
  should "load default config if path passed is empty" do
@@ -186,7 +186,7 @@ class TestConfiguration < Test::Unit::TestCase
186
186
  mock(SafeYAML).load_file(@paths[:other]) { {"baseurl" => "http://wahoo.dev"} }
187
187
  mock($stdout).puts("Configuration file: #{@paths[:default]}")
188
188
  mock($stdout).puts("Configuration file: #{@paths[:other]}")
189
- assert_equal Jekyll::Configuration::DEFAULTS.deep_merge({ "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => [@paths[:default], @paths[:other]] })
189
+ assert_equal Utils.deep_merge_hashes(Jekyll::Configuration::DEFAULTS, { "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => [@paths[:default], @paths[:other]] })
190
190
  end
191
191
  end
192
192
  end
@@ -0,0 +1,56 @@
1
+ require 'helper'
2
+
3
+ class TestDraft < Test::Unit::TestCase
4
+ def setup_draft(file)
5
+ Draft.new(@site, source_dir, '', file)
6
+ end
7
+
8
+ context "A Draft" do
9
+ setup do
10
+ clear_dest
11
+ stub(Jekyll).configuration { Jekyll::Configuration::DEFAULTS }
12
+ @site = Site.new(Jekyll.configuration)
13
+ end
14
+
15
+ should "ensure valid drafts are valid" do
16
+ assert Draft.valid?("2008-09-09-foo-bar.textile")
17
+ assert Draft.valid?("foo/bar/2008-09-09-foo-bar.textile")
18
+ assert Draft.valid?("lol2008-09-09-foo-bar.textile")
19
+
20
+ assert !Draft.valid?("blah")
21
+ end
22
+
23
+ should "make properties accessible through #[]" do
24
+ draft = setup_draft('draft-properties.text')
25
+ # ! need to touch the file! Or get its timestamp
26
+ date = File.mtime(File.join(source_dir, '_drafts', 'draft-properties.text'))
27
+ ymd = date.strftime("%Y/%m/%d")
28
+
29
+ attrs = {
30
+ categories: %w(foo bar baz),
31
+ content: "All the properties.\n\nPlus an excerpt.\n",
32
+ date: date,
33
+ dir: "/foo/bar/baz/#{ymd}",
34
+ excerpt: "All the properties.\n\n",
35
+ foo: 'bar',
36
+ id: "/foo/bar/baz/#{ymd}/draft-properties",
37
+ layout: 'default',
38
+ name: nil,
39
+ path: "_drafts/draft-properties.text",
40
+ permalink: nil,
41
+ published: nil,
42
+ tags: %w(ay bee cee),
43
+ title: 'Properties Draft',
44
+ url: "/foo/bar/baz/#{ymd}/draft-properties.html"
45
+ }
46
+
47
+ attrs.each do |attr, val|
48
+ attr_str = attr.to_s
49
+ result = draft[attr_str]
50
+ assert_equal val, result, "For <draft[\"#{attr_str}\"]>:"
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -36,7 +36,7 @@ class TestExcerpt < Test::Unit::TestCase
36
36
  end
37
37
 
38
38
  context "#include(string)" do
39
-
39
+
40
40
  setup do
41
41
  @excerpt.output = "Here is a fake output stub"
42
42
  end
@@ -61,7 +61,7 @@ class TestExcerpt < Test::Unit::TestCase
61
61
  assert_equal @excerpt.content, @excerpt.to_s
62
62
  end
63
63
 
64
- should "return its output if output present" do
64
+ should "return its output if output present" do
65
65
  @excerpt.output = "Fake Output"
66
66
  assert_equal @excerpt.output, @excerpt.to_s
67
67
  end
@@ -131,7 +131,7 @@ class TestFilters < Test::Unit::TestCase
131
131
  assert_equal 2, g["items"].size
132
132
  when ""
133
133
  assert g["items"].is_a?(Array), "The list of grouped items for '' is not an Array."
134
- assert_equal 8, g["items"].size
134
+ assert_equal 10, g["items"].size
135
135
  end
136
136
  end
137
137
  end
@@ -14,7 +14,7 @@ class TestGeneratedSite < Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  should "ensure post count is as expected" do
17
- assert_equal 38, @site.posts.size
17
+ assert_equal 39, @site.posts.size
18
18
  end
19
19
 
20
20
  should "insert site.posts into the index" do
@@ -44,6 +44,15 @@ class TestGeneratedSite < Test::Unit::TestCase
44
44
  assert File.exists?(dest_dir('/about/index.html'))
45
45
  assert File.exists?(dest_dir('/contacts.html'))
46
46
  end
47
+
48
+ should "print a nice list of static files" do
49
+ expected_output = Regexp.new <<-OUTPUT
50
+ - /css/screen.css last edited at \\d+ with extname .css
51
+ - /products.yml last edited at \\d+ with extname .yml
52
+ - /symlink-test/symlinked-dir/screen.css last edited at \\d+ with extname .css
53
+ OUTPUT
54
+ assert_match expected_output, File.read(dest_dir('static_files.html'))
55
+ end
47
56
  end
48
57
 
49
58
  context "generating limited posts" do
@@ -35,7 +35,7 @@ class TestKramdown < Test::Unit::TestCase
35
35
  assert_match /<p>(&#8220;|“)Pit(&#8217;|’)hy(&#8221;|”)<\/p>/, @markdown.convert(%{"Pit'hy"}).strip
36
36
 
37
37
  override = { 'kramdown' => { 'smart_quotes' => 'lsaquo,rsaquo,laquo,raquo' } }
38
- markdown = Converters::Markdown.new(@config.deep_merge(override))
38
+ markdown = Converters::Markdown.new(Utils.deep_merge_hashes(@config, override))
39
39
  assert_match /<p>(&#171;|«)Pit(&#8250;|›)hy(&#187;|»)<\/p>/, markdown.convert(%{"Pit'hy"}).strip
40
40
  end
41
41
 
@@ -13,5 +13,22 @@ class TestLayoutReader < Test::Unit::TestCase
13
13
  layouts = LayoutReader.new(@site).read
14
14
  assert_equal ["default", "simple", "post/simple"].sort, layouts.keys.sort
15
15
  end
16
+
17
+ context "when no _layouts directory exists in CWD" do
18
+ should "know to use the layout directory relative to the site source" do
19
+ assert_equal LayoutReader.new(@site).layout_directory, source_dir("_layouts")
20
+ end
21
+ end
22
+
23
+ context "when a _layouts directory exists in CWD" do
24
+ setup do
25
+ stub(File).directory? { true }
26
+ stub(Dir).pwd { source_dir("blah") }
27
+ end
28
+
29
+ should "know to use the layout directory relative to CWD" do
30
+ assert_equal LayoutReader.new(@site).layout_directory, source_dir("blah/_layouts")
31
+ end
32
+ end
16
33
  end
17
34
  end
@@ -129,6 +129,16 @@ class TestPage < Test::Unit::TestCase
129
129
  assert_equal @page.permalink, @page.url
130
130
  assert_equal "/about/", @page.dir
131
131
  end
132
+
133
+ should "not be writable outside of destination" do
134
+ unexpected = File.expand_path("../../../baddie.html", dest_dir)
135
+ File.delete unexpected if File.exist?(unexpected)
136
+ page = setup_page("exploit.md")
137
+ do_render(page)
138
+ page.write(dest_dir)
139
+
140
+ assert !File.exist?(unexpected)
141
+ end
132
142
  end
133
143
 
134
144
  context "with specified layout of nil" do
@@ -3,12 +3,14 @@ require 'helper'
3
3
  class TestPager < Test::Unit::TestCase
4
4
 
5
5
  def build_site(config = {})
6
- base = Jekyll::Configuration::DEFAULTS.deep_merge({
6
+ base = build_configs({
7
7
  'source' => source_dir,
8
8
  'destination' => dest_dir,
9
9
  'paginate' => 1
10
10
  })
11
- site = Jekyll::Site.new(base.deep_merge(config))
11
+ site = Jekyll::Site.new(site_configuration(
12
+ {"paginate" => 1}.merge(config)
13
+ ))
12
14
  site.process
13
15
  site
14
16
  end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+
3
+ class TestPathSanitization < Test::Unit::TestCase
4
+ context "on Windows with absolute source" do
5
+ setup do
6
+ @source = "C:/Users/xmr/Desktop/mpc-hc.org"
7
+ @dest = "./_site/"
8
+ stub(Dir).pwd { "C:/Users/xmr/Desktop/mpc-hc.org" }
9
+ end
10
+ should "strip drive name from path" do
11
+ assert_equal "C:/Users/xmr/Desktop/mpc-hc.org/_site", Jekyll.sanitized_path(@source, @dest)
12
+ end
13
+ end
14
+ end
@@ -38,7 +38,7 @@ class TestPost < Test::Unit::TestCase
38
38
  id: "/foo/bar/baz/2013/12/20/properties",
39
39
  layout: 'default',
40
40
  name: nil,
41
- # path: "properties.html",
41
+ path: "_posts/2013-12-20-properties.text",
42
42
  permalink: nil,
43
43
  published: nil,
44
44
  tags: %w(ay bee cee),
@@ -103,6 +103,17 @@ class TestPost < Test::Unit::TestCase
103
103
  assert_equal "/my_category/permalinked-post", @post.url
104
104
  end
105
105
 
106
+ should "not be writable outside of destination" do
107
+ unexpected = File.expand_path("../../../baddie.html", dest_dir)
108
+ File.delete unexpected if File.exist?(unexpected)
109
+ post = setup_post("2014-01-06-permalink-traversal.md")
110
+ do_render(post)
111
+ post.write(dest_dir)
112
+
113
+ assert !File.exist?(unexpected)
114
+ assert File.exist?(File.expand_path("baddie.html", dest_dir))
115
+ end
116
+
106
117
  context "with CRLF linebreaks" do
107
118
  setup do
108
119
  @real_file = "2009-05-24-yaml-linebreak.markdown"
@@ -1,15 +1,8 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestSass < Test::Unit::TestCase
4
- def site_configuration(overrides = {})
5
- Jekyll::Configuration::DEFAULTS.deep_merge(overrides).deep_merge({
6
- "source" => source_dir,
7
- "destination" => dest_dir
8
- })
9
- end
10
-
11
4
  def converter(overrides = {})
12
- Jekyll::Sass.new(site_configuration({"sass" => overrides}))
5
+ Jekyll::Converters::Sass.new(site_configuration({"sass" => overrides}))
13
6
  end
14
7
 
15
8
  def sass_content
@@ -37,62 +30,6 @@ body {\n font-family: Helvetica, sans-serif;\n font-color: fuschia; }
37
30
  CSS
38
31
  end
39
32
 
40
- context "matching file extensions" do
41
- should "match .scss files" do
42
- assert converter.matches(".scss")
43
- end
44
-
45
- should "match .sass files" do
46
- assert converter.matches(".sass")
47
- end
48
- end
49
-
50
- context "determining the output file extension" do
51
- should "always outputs the .css file extension" do
52
- assert_equal ".css", converter.output_ext(".always-css")
53
- end
54
- end
55
-
56
- context "when building configurations" do
57
- should "not allow caching in safe mode" do
58
- verter = converter
59
- verter.instance_variable_get(:@config)["safe"] = true
60
- assert_equal false, verter.sass_configs[:cache]
61
- end
62
-
63
- should "allow caching in unsafe mode" do
64
- assert_equal true, converter.sass_configs[:cache]
65
- end
66
-
67
- should "set the load paths to the _sass dir relative to site source" do
68
- assert_equal [source_dir("_sass")], converter.sass_configs[:load_paths]
69
- end
70
-
71
- should "allow the user to specify a different sass dir" do
72
- assert_equal [source_dir("_scss")], converter({"sass_dir" => "_scss"}).sass_configs[:load_paths]
73
- end
74
-
75
- should "set syntax :scss when SCSS content" do
76
- assert_equal :scss, converter.sass_configs(scss_content)[:syntax]
77
- end
78
-
79
- should "set syntax :sass when Sass content" do
80
- assert_equal :sass, converter.sass_configs(sass_content)[:syntax]
81
- end
82
-
83
- should "default to :sass syntax when content is empty" do
84
- assert_equal :sass, converter.sass_configs[:syntax]
85
- end
86
-
87
- should "not allow sass_dirs outside of site source" do
88
- assert_equal source_dir("etc/passwd"), converter({"sass_dir" => "/etc/passwd"}).sass_dir_relative_to_site_source
89
- end
90
-
91
- should "override user-set syntax based on content" do
92
- assert_equal :sass, converter({"syntax" => :scss}).sass_configs(sass_content)[:syntax]
93
- end
94
- end
95
-
96
33
  context "converting sass" do
97
34
  should "produce CSS" do
98
35
  assert_equal css_output, converter.convert(sass_content)
@@ -158,7 +158,24 @@ class TestSite < Test::Unit::TestCase
158
158
  stub.proxy(Dir).entries { |entries| entries.reverse }
159
159
  @site.process
160
160
  # files in symlinked directories may appear twice
161
- sorted_pages = %w(.htaccess about.html bar.html coffeescript.coffee contacts.html deal.with.dots.html foo.md index.html index.html main.scss main.scss properties.html sitemap.xml symlinked-file)
161
+ sorted_pages = %w(
162
+ .htaccess
163
+ about.html
164
+ bar.html
165
+ coffeescript.coffee
166
+ contacts.html
167
+ deal.with.dots.html
168
+ exploit.md
169
+ foo.md
170
+ index.html
171
+ index.html
172
+ main.scss
173
+ main.scss
174
+ properties.html
175
+ sitemap.xml
176
+ static_files.html
177
+ symlinked-file
178
+ )
162
179
  assert_equal sorted_pages, @site.pages.map(&:name)
163
180
  end
164
181
 
@@ -169,6 +186,14 @@ class TestSite < Test::Unit::TestCase
169
186
  assert_equal posts.size - @num_invalid_posts, @site.posts.size
170
187
  end
171
188
 
189
+ should "expose jekyll version to site payload" do
190
+ assert_equal Jekyll::VERSION, @site.site_payload['jekyll']['version']
191
+ end
192
+
193
+ should "expose list of static files to site payload" do
194
+ assert_equal @site.static_files, @site.site_payload['site']['static_files']
195
+ end
196
+
172
197
  should "deploy payload" do
173
198
  clear_dest
174
199
  @site.process