octopress 3.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. checksums.yaml +15 -0
  2. data/.editorconfig +22 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +20 -0
  5. data/.powrc +4 -0
  6. data/.rspec +5 -0
  7. data/.rubocop.yml +119 -0
  8. data/.slugignore +3 -0
  9. data/.themes/classic/.editorconfig +44 -0
  10. data/.themes/classic/_config/adn-timeline.yml +10 -0
  11. data/.themes/classic/_config/delicious-feed.yml +4 -0
  12. data/.themes/classic/_config/deploy/gh_pages.yml +9 -0
  13. data/.themes/classic/_config/deploy/rsync.yml +14 -0
  14. data/.themes/classic/_config/disqus.yml +11 -0
  15. data/.themes/classic/_config/facebook-like.yml +2 -0
  16. data/.themes/classic/_config/gauges-analytics.yml +6 -0
  17. data/.themes/classic/_config/github-repos.yml +24 -0
  18. data/.themes/classic/_config/google-analytics.yml +6 -0
  19. data/.themes/classic/_config/google-plus.yml +13 -0
  20. data/.themes/classic/_config/jekyll.yml +37 -0
  21. data/.themes/classic/_config/pinboard-feed.yml +4 -0
  22. data/.themes/classic/_config/require-js.yml +19 -0
  23. data/.themes/classic/_config/theme.yml +54 -0
  24. data/.themes/classic/_config/twitter-timeline.yml +9 -0
  25. data/.themes/classic/assets/javascripts/lib/ios-rotate-scaling-fix.js +18 -0
  26. data/.themes/classic/assets/javascripts/lib/jquery.cookie.js +92 -0
  27. data/.themes/classic/assets/javascripts/lib/modernizr.js +447 -0
  28. data/.themes/classic/assets/javascripts/lib/octopress.js +83 -0
  29. data/.themes/classic/assets/javascripts/modules/adn-timeline.coffee +68 -0
  30. data/.themes/classic/assets/javascripts/modules/delicious-feed.coffee +38 -0
  31. data/.themes/classic/assets/javascripts/modules/github-repos.coffee +60 -0
  32. data/.themes/classic/assets/javascripts/modules/github.coffee +60 -0
  33. data/.themes/classic/assets/javascripts/modules/helpers.coffee +96 -0
  34. data/.themes/classic/assets/javascripts/modules/pinboard-feed.coffee +42 -0
  35. data/.themes/classic/assets/javascripts/modules/site.coffee +11 -0
  36. data/.themes/classic/assets/stylesheets/_base.scss +5 -0
  37. data/.themes/classic/assets/stylesheets/_partials.scss +8 -0
  38. data/.themes/classic/assets/stylesheets/base/_layout.scss +191 -0
  39. data/.themes/classic/assets/stylesheets/base/_solarized.scss +75 -0
  40. data/.themes/classic/assets/stylesheets/base/_theme.scss +92 -0
  41. data/.themes/classic/assets/stylesheets/base/_typography.scss +168 -0
  42. data/.themes/classic/assets/stylesheets/base/_utilities.scss +27 -0
  43. data/.themes/classic/assets/stylesheets/custom/_colors.scss +49 -0
  44. data/.themes/classic/assets/stylesheets/custom/_fonts.scss +10 -0
  45. data/.themes/classic/assets/stylesheets/custom/_layout.scss +17 -0
  46. data/.themes/classic/assets/stylesheets/custom/_styles.scss +2 -0
  47. data/.themes/classic/assets/stylesheets/partials/_archive.scss +77 -0
  48. data/.themes/classic/assets/stylesheets/partials/_blog.scss +165 -0
  49. data/.themes/classic/assets/stylesheets/partials/_footer.scss +19 -0
  50. data/.themes/classic/assets/stylesheets/partials/_header.scss +18 -0
  51. data/.themes/classic/assets/stylesheets/partials/_navigation.scss +136 -0
  52. data/.themes/classic/assets/stylesheets/partials/_sharing.scss +73 -0
  53. data/.themes/classic/assets/stylesheets/partials/_sidebar.scss +4 -0
  54. data/.themes/classic/assets/stylesheets/partials/_syntax.scss +234 -0
  55. data/.themes/classic/assets/stylesheets/partials/sidebar/_base.scss +106 -0
  56. data/.themes/classic/assets/stylesheets/partials/sidebar/_delicious.scss +4 -0
  57. data/.themes/classic/assets/stylesheets/partials/sidebar/_googleplus.scss +26 -0
  58. data/.themes/classic/assets/stylesheets/partials/sidebar/_pinboard.scss +12 -0
  59. data/.themes/classic/assets/stylesheets/plugins/_plugins.scss +5 -0
  60. data/.themes/classic/assets/stylesheets/screen.scss +11 -0
  61. data/.themes/classic/source/404.markdown +9 -0
  62. data/.themes/classic/source/_includes/after_footer.html +7 -0
  63. data/.themes/classic/source/_includes/archive_post.html +12 -0
  64. data/.themes/classic/source/_includes/article.html +23 -0
  65. data/.themes/classic/source/_includes/comments.html +9 -0
  66. data/.themes/classic/source/_includes/custom/after_footer.html +3 -0
  67. data/.themes/classic/source/_includes/custom/after_page.html +1 -0
  68. data/.themes/classic/source/_includes/custom/after_post.html +0 -0
  69. data/.themes/classic/source/_includes/custom/comments.html +5 -0
  70. data/.themes/classic/source/_includes/custom/footer.html +4 -0
  71. data/.themes/classic/source/_includes/custom/head.html +7 -0
  72. data/.themes/classic/source/_includes/custom/header.html +6 -0
  73. data/.themes/classic/source/_includes/custom/navigation.html +4 -0
  74. data/.themes/classic/source/_includes/custom/page_meta.html +1 -0
  75. data/.themes/classic/source/_includes/custom/post_meta.html +1 -0
  76. data/.themes/classic/source/_includes/custom/sharing.html +3 -0
  77. data/.themes/classic/source/_includes/disqus.html +22 -0
  78. data/.themes/classic/source/_includes/facebook_like.html +10 -0
  79. data/.themes/classic/source/_includes/feed_entry.xml +10 -0
  80. data/.themes/classic/source/_includes/footer.html +1 -0
  81. data/.themes/classic/source/_includes/gauges_analytics.html +15 -0
  82. data/.themes/classic/source/_includes/google_analytics.html +13 -0
  83. data/.themes/classic/source/_includes/google_plus_one.html +9 -0
  84. data/.themes/classic/source/_includes/head.html +33 -0
  85. data/.themes/classic/source/_includes/header.html +1 -0
  86. data/.themes/classic/source/_includes/navigation.html +15 -0
  87. data/.themes/classic/source/_includes/post/author.html +8 -0
  88. data/.themes/classic/source/_includes/post/categories.html +10 -0
  89. data/.themes/classic/source/_includes/post/date.html +15 -0
  90. data/.themes/classic/source/_includes/post/disqus_thread.html +1 -0
  91. data/.themes/classic/source/_includes/post/meta.html +3 -0
  92. data/.themes/classic/source/_includes/post/sharing.html +36 -0
  93. data/.themes/classic/source/_includes/post/title.html +5 -0
  94. data/.themes/classic/source/_includes/post/variables.html +14 -0
  95. data/.themes/classic/source/_includes/sidebars/blog_index_default.html +3 -0
  96. data/.themes/classic/source/_includes/sidebars/page_default.html +4 -0
  97. data/.themes/classic/source/_includes/sidebars/post_default.html +4 -0
  98. data/.themes/classic/source/_includes/sidebars/sections/delicious.html +8 -0
  99. data/.themes/classic/source/_includes/sidebars/sections/github.html +9 -0
  100. data/.themes/classic/source/_includes/sidebars/sections/google_plus.html +5 -0
  101. data/.themes/classic/source/_includes/sidebars/sections/pinboard.html +17 -0
  102. data/.themes/classic/source/_includes/sidebars/sections/recent_posts.html +10 -0
  103. data/.themes/classic/source/_includes/twitter_sharing.html +11 -0
  104. data/.themes/classic/source/_layouts/category_feed.xml +24 -0
  105. data/.themes/classic/source/_layouts/category_index.html +19 -0
  106. data/.themes/classic/source/_layouts/default.html +14 -0
  107. data/.themes/classic/source/_layouts/page.html +34 -0
  108. data/.themes/classic/source/_layouts/post.html +39 -0
  109. data/.themes/classic/source/archives/index.html +20 -0
  110. data/.themes/classic/source/assets/jwplayer/glow/controlbar/background.png +0 -0
  111. data/.themes/classic/source/assets/jwplayer/glow/controlbar/blankButton.png +0 -0
  112. data/.themes/classic/source/assets/jwplayer/glow/controlbar/divider.png +0 -0
  113. data/.themes/classic/source/assets/jwplayer/glow/controlbar/fullscreenButton.png +0 -0
  114. data/.themes/classic/source/assets/jwplayer/glow/controlbar/fullscreenButtonOver.png +0 -0
  115. data/.themes/classic/source/assets/jwplayer/glow/controlbar/muteButton.png +0 -0
  116. data/.themes/classic/source/assets/jwplayer/glow/controlbar/muteButtonOver.png +0 -0
  117. data/.themes/classic/source/assets/jwplayer/glow/controlbar/normalscreenButton.png +0 -0
  118. data/.themes/classic/source/assets/jwplayer/glow/controlbar/normalscreenButtonOver.png +0 -0
  119. data/.themes/classic/source/assets/jwplayer/glow/controlbar/pauseButton.png +0 -0
  120. data/.themes/classic/source/assets/jwplayer/glow/controlbar/pauseButtonOver.png +0 -0
  121. data/.themes/classic/source/assets/jwplayer/glow/controlbar/playButton.png +0 -0
  122. data/.themes/classic/source/assets/jwplayer/glow/controlbar/playButtonOver.png +0 -0
  123. data/.themes/classic/source/assets/jwplayer/glow/controlbar/timeSliderBuffer.png +0 -0
  124. data/.themes/classic/source/assets/jwplayer/glow/controlbar/timeSliderCapLeft.png +0 -0
  125. data/.themes/classic/source/assets/jwplayer/glow/controlbar/timeSliderCapRight.png +0 -0
  126. data/.themes/classic/source/assets/jwplayer/glow/controlbar/timeSliderProgress.png +0 -0
  127. data/.themes/classic/source/assets/jwplayer/glow/controlbar/timeSliderRail.png +0 -0
  128. data/.themes/classic/source/assets/jwplayer/glow/controlbar/unmuteButton.png +0 -0
  129. data/.themes/classic/source/assets/jwplayer/glow/controlbar/unmuteButtonOver.png +0 -0
  130. data/.themes/classic/source/assets/jwplayer/glow/display/background.png +0 -0
  131. data/.themes/classic/source/assets/jwplayer/glow/display/bufferIcon.png +0 -0
  132. data/.themes/classic/source/assets/jwplayer/glow/display/muteIcon.png +0 -0
  133. data/.themes/classic/source/assets/jwplayer/glow/display/playIcon.png +0 -0
  134. data/.themes/classic/source/assets/jwplayer/glow/dock/button.png +0 -0
  135. data/.themes/classic/source/assets/jwplayer/glow/glow.xml +115 -0
  136. data/.themes/classic/source/assets/jwplayer/glow/playlist/item.png +0 -0
  137. data/.themes/classic/source/assets/jwplayer/glow/playlist/itemOver.png +0 -0
  138. data/.themes/classic/source/assets/jwplayer/glow/playlist/sliderCapBottom.png +0 -0
  139. data/.themes/classic/source/assets/jwplayer/glow/playlist/sliderCapTop.png +0 -0
  140. data/.themes/classic/source/assets/jwplayer/glow/playlist/sliderRail.png +0 -0
  141. data/.themes/classic/source/assets/jwplayer/glow/playlist/sliderThumb.png +0 -0
  142. data/.themes/classic/source/assets/jwplayer/glow/sharing/embedIcon.png +0 -0
  143. data/.themes/classic/source/assets/jwplayer/glow/sharing/embedScreen.png +0 -0
  144. data/.themes/classic/source/assets/jwplayer/glow/sharing/shareIcon.png +0 -0
  145. data/.themes/classic/source/assets/jwplayer/glow/sharing/shareScreen.png +0 -0
  146. data/.themes/classic/source/assets/jwplayer/player.swf +0 -0
  147. data/.themes/classic/source/atom.xml +23 -0
  148. data/.themes/classic/source/images/bird_32_gray.png +0 -0
  149. data/.themes/classic/source/images/bird_32_gray_fail.png +0 -0
  150. data/.themes/classic/source/images/code_bg.png +0 -0
  151. data/.themes/classic/source/images/dotted-border.png +0 -0
  152. data/.themes/classic/source/images/email.png +0 -0
  153. data/.themes/classic/source/images/icon/facebook.png +0 -0
  154. data/.themes/classic/source/images/icon/github.png +0 -0
  155. data/.themes/classic/source/images/icon/googleplus.png +0 -0
  156. data/.themes/classic/source/images/icon/twitter-bird.png +0 -0
  157. data/.themes/classic/source/images/icon/twitter.png +0 -0
  158. data/.themes/classic/source/images/line-tile.png +0 -0
  159. data/.themes/classic/source/images/noise.png +0 -0
  160. data/.themes/classic/source/images/rss.png +0 -0
  161. data/.themes/classic/source/images/search.png +0 -0
  162. data/.themes/classic/source/index.html +30 -0
  163. data/.themes/classic/source/javascripts/jquery.min.js +5 -0
  164. data/.themes/classic/source/octopress-favicon.png +0 -0
  165. data/.themes/classic/source/robots.txt +7 -0
  166. data/.travis.yml +6 -0
  167. data/CHANGELOG.markdown +46 -0
  168. data/CONTRIBUTING.markdown +17 -0
  169. data/Gemfile +2 -0
  170. data/README.markdown +37 -0
  171. data/Rakefile +76 -0
  172. data/bin/octopress +66 -0
  173. data/lib/console +17 -0
  174. data/lib/guard/jekyll.rb +33 -0
  175. data/lib/octopress.rb +89 -0
  176. data/lib/octopress/command.rb +9 -0
  177. data/lib/octopress/commands.rb +14 -0
  178. data/lib/octopress/commands/build.rb +17 -0
  179. data/lib/octopress/commands/build_javascripts.rb +11 -0
  180. data/lib/octopress/commands/build_jekyll.rb +25 -0
  181. data/lib/octopress/commands/build_stylesheets.rb +13 -0
  182. data/lib/octopress/commands/install.rb +45 -0
  183. data/lib/octopress/commands/new.rb +21 -0
  184. data/lib/octopress/commands/scaffold.rb +101 -0
  185. data/lib/octopress/commands/serve.rb +25 -0
  186. data/lib/octopress/configuration.rb +231 -0
  187. data/lib/octopress/core_ext.rb +44 -0
  188. data/lib/octopress/dependency_installer.rb +287 -0
  189. data/lib/octopress/errors.rb +3 -0
  190. data/lib/octopress/filters/content.rb +66 -0
  191. data/lib/octopress/filters/date.rb +46 -0
  192. data/lib/octopress/filters/post.rb +175 -0
  193. data/lib/octopress/filters/url.rb +34 -0
  194. data/lib/octopress/formatters.rb +9 -0
  195. data/lib/octopress/formatters/base_formatter.rb +17 -0
  196. data/lib/octopress/formatters/simple_formatter.rb +9 -0
  197. data/lib/octopress/formatters/verbose_formatter.rb +9 -0
  198. data/lib/octopress/generators/category_generator.rb +196 -0
  199. data/lib/octopress/generators/sitemap_generator.rb +308 -0
  200. data/lib/octopress/guardfile +43 -0
  201. data/lib/octopress/helpers/titlecase.rb +37 -0
  202. data/lib/octopress/ink.rb +12 -0
  203. data/lib/octopress/inquirable_string.rb +12 -0
  204. data/lib/octopress/installer.rb +92 -0
  205. data/lib/octopress/js_asset_manager.rb +98 -0
  206. data/lib/octopress/liquid_helpers/conditional.rb +36 -0
  207. data/lib/octopress/liquid_helpers/config.rb +58 -0
  208. data/lib/octopress/liquid_helpers/include.rb +33 -0
  209. data/lib/octopress/liquid_helpers/url.rb +29 -0
  210. data/lib/octopress/liquid_helpers/vars.rb +30 -0
  211. data/lib/octopress/plugin.rb +33 -0
  212. data/lib/octopress/rake.rb +16 -0
  213. data/lib/octopress/scaffold/.gitignore +18 -0
  214. data/lib/octopress/scaffold/site/Gemfile +3 -0
  215. data/lib/octopress/scaffold/site/config/compass.rb +27 -0
  216. data/lib/octopress/scaffold/site/config/rack.rb +25 -0
  217. data/lib/octopress/scaffold/site/config/site.yml +0 -0
  218. data/lib/octopress/scaffold/site/javascripts/lib/ios-rotate-scaling-fix.js +19 -0
  219. data/lib/octopress/scaffold/site/javascripts/lib/jquery-1.9.1.js +9598 -0
  220. data/lib/octopress/scaffold/site/javascripts/lib/jquery.cookie.js +93 -0
  221. data/lib/octopress/scaffold/site/stylesheets/_config.scss +1 -0
  222. data/lib/octopress/scaffold/site/stylesheets/_style.scss +1 -0
  223. data/lib/octopress/scaffold/site/stylesheets/site.scss +16 -0
  224. data/lib/octopress/tags/assign.rb +34 -0
  225. data/lib/octopress/tags/capture.rb +31 -0
  226. data/lib/octopress/tags/config-tag.rb +23 -0
  227. data/lib/octopress/tags/include.rb +63 -0
  228. data/lib/octopress/tags/js-assets.rb +23 -0
  229. data/lib/octopress/tags/puts.rb +39 -0
  230. data/lib/octopress/tags/render-partial.rb +89 -0
  231. data/lib/octopress/tags/return.rb +21 -0
  232. data/lib/octopress/version.rb +3 -0
  233. data/lib/rake/clean.rake +8 -0
  234. data/lib/rake/clobber.rake +5 -0
  235. data/lib/rake/console.rake +5 -0
  236. data/lib/rake/deploy.rake +4 -0
  237. data/lib/rake/gen_deploy.rake +2 -0
  238. data/lib/rake/generate.rake +4 -0
  239. data/lib/rake/generate_only.rake +14 -0
  240. data/lib/rake/hygiene.rake +29 -0
  241. data/lib/rake/install.rake +8 -0
  242. data/lib/rake/integrate.rake +4 -0
  243. data/lib/rake/isolate.rake +13 -0
  244. data/lib/rake/list_drafts.rake +7 -0
  245. data/lib/rake/new.rake +7 -0
  246. data/lib/rake/new_page.rake +49 -0
  247. data/lib/rake/new_post.rake +32 -0
  248. data/lib/rake/nuke.rake +4 -0
  249. data/lib/rake/preview.rake +4 -0
  250. data/lib/rake/push.rake +37 -0
  251. data/lib/rake/rsync.rake +20 -0
  252. data/lib/rake/set_root_dir.rake +35 -0
  253. data/lib/rake/setup_github_pages.rake +115 -0
  254. data/lib/rake/watch.rake +11 -0
  255. data/lib/scaffold/Rakefile +142 -0
  256. data/lib/scaffold/plugin-name.gemspec +43 -0
  257. data/lib/spec/fixtures/env/defaults/classic.yml +2 -0
  258. data/lib/spec/fixtures/no_override/defaults/classic.yml +11 -0
  259. data/lib/spec/fixtures/override/defaults/classic.yml +11 -0
  260. data/lib/spec/fixtures/override/site.yml +11 -0
  261. data/lib/spec/octopress/configuration_spec.rb +67 -0
  262. data/lib/spec/octopress/dependency_installer_spec.rb +66 -0
  263. data/lib/spec/octopress/ink_spec.rb +10 -0
  264. data/lib/spec/octopress/octopress_spec.rb +97 -0
  265. data/lib/spec/spec_helper.rb +22 -0
  266. data/lib/spec/support/env.rb +36 -0
  267. data/lib/spec/support/simplecov.rb +52 -0
  268. data/octopress.gemspec +52 -0
  269. metadata +697 -0
@@ -0,0 +1,44 @@
1
+ class Hash
2
+ # Merges self with another hash, recursively.
3
+ #
4
+ # This code was lovingly stolen from some random gem:
5
+ # http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
6
+ #
7
+ # Thanks to whoever made it.
8
+ def deep_merge(hash)
9
+ target = dup
10
+ hash.keys.each do |key|
11
+ if hash[key].is_a? Hash and self[key].is_a? Hash
12
+ target[key] = target[key].deep_merge(hash[key])
13
+ next
14
+ end
15
+ target[key] = hash[key]
16
+ end
17
+
18
+ target
19
+ end
20
+
21
+ def to_symbol_keys
22
+ inject({}) do |memo, (k, v)|
23
+ if v.is_a? Hash
24
+ memo[k.to_sym] = v.to_symbol_keys
25
+ else
26
+ memo[k.to_sym] = v
27
+ end
28
+
29
+ memo
30
+ end
31
+ end
32
+
33
+ def to_string_keys
34
+ inject({}) do |memo, (k, v)|
35
+ if v.is_a? Hash
36
+ memo[k.to_s] = v.to_string_keys
37
+ else
38
+ memo[k.to_s] = v
39
+ end
40
+
41
+ memo
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,287 @@
1
+ require 'uri'
2
+ require 'open3'
3
+ require 'fileutils'
4
+
5
+ module Octopress
6
+ class DependencyInstaller
7
+
8
+ # Static: installs a list of plugins
9
+ #
10
+ # plugins - an Array of plugin names
11
+ #
12
+ # Returns nothing
13
+ def self.install_all(plugins)
14
+ if plugins.is_a?(String)
15
+ plugins = [plugins]
16
+ end
17
+ installer = DependencyInstaller.new
18
+ plugins.each do |plugin|
19
+ installer.install plugin
20
+ end
21
+ end
22
+
23
+ CACHE_DIR = File.join(Octopress.root, ".plugins")
24
+ USERNAME_REPO_REGEXP = /^([a-z0-9\-_]+)\/([a-z0-9\-_]+)$/
25
+ OCTOPRESS_REPO_REGEXP = /^[a-z0-9\-_]+$/
26
+ GIT_REPO_REGEXP = /^(git:\/\/|https:\/\/|git@)([a-z0-9.]+)(\/|:)([a-z0-9\-_]+)\/([a-z0-9\-_]+)\.git/
27
+
28
+ # Public: Create a new DependencyInstaller and initialize instance variables
29
+ #
30
+ # Returns nothing
31
+ def initialize(plugins = [])
32
+ @plugins = Set.new.merge(plugins)
33
+ end
34
+
35
+ # Public: constructs full git URL for a plugin
36
+ #
37
+ # plugin - the plugin name
38
+ #
39
+ # Returns full git URL for a plugin
40
+ def git_url(plugin)
41
+ if OCTOPRESS_REPO_REGEXP.match(plugin)
42
+ "git://github.com/octopress/#{plugin}.git"
43
+ elsif USERNAME_REPO_REGEXP.match(plugin)
44
+ "git://github.com/#{plugin}.git"
45
+ else
46
+ plugin
47
+ end
48
+ end
49
+
50
+ # Public: Gets the directory for local storage
51
+ #
52
+ # Returns the directory for the plugin
53
+ def namespace(plugin)
54
+ if manifest(plugin)["type"].to_s == "theme"
55
+ "theme"
56
+ else
57
+ manifest(plugin)["slug"]
58
+ end
59
+ end
60
+
61
+ # Public: builds full installation directory path for plugin
62
+ #
63
+ # plugin - the plugin name
64
+ #
65
+ # Returns the full path of the installation directory
66
+ def cache_dir(plugin)
67
+ FileUtils.mkdir_p(CACHE_DIR) unless File.exists?(CACHE_DIR)
68
+ File.join(CACHE_DIR, File.basename(plugin).gsub(/\.git$/, ''))
69
+ end
70
+
71
+ # Public: clones the remote repository to the plugin install directory
72
+ #
73
+ # plugin - the plugin name
74
+ #
75
+ # Returns the file path to where the plugin was installed
76
+ def clone(plugin)
77
+ if File.directory?(cache_dir(plugin))
78
+ Open3.popen3("cd #{cache_dir(plugin)} && git pull origin master") do |stdin, stdout, stderr, wait_thr|
79
+ exit_status = wait_thr.value
80
+ raise RuntimeError, "Error updating #{plugin}".red unless exit_status.exitstatus == 0
81
+ end
82
+ else
83
+ Open3.popen3("git clone #{git_url(plugin)} #{cache_dir(plugin)}") do |stdin, stdout, stderr, wait_thr|
84
+ exit_status = wait_thr.value
85
+ raise RuntimeError, "Error cloning #{plugin}".red unless exit_status.exitstatus == 0
86
+ end
87
+ end
88
+ cache_dir(plugin)
89
+ end
90
+
91
+ # Public: fetches the contents of the manifest file as a Hash
92
+ #
93
+ # plugin - the plugin name
94
+ #
95
+ # Returns a Hash of the contents of the manifest file
96
+ def manifest(plugin)
97
+ @manifests = {} if @manifests.nil?
98
+ if @manifests.has_key?(plugin)
99
+ @manifests[plugin]
100
+ else
101
+ @manifests[plugin] = YAML.load_file(File.join(cache_dir(plugin), "manifest.yml"))
102
+ end
103
+ end
104
+
105
+ # Public: build dependency tree for a plugin
106
+ #
107
+ # plugin - the plugin name
108
+ #
109
+ # Returns an array of plugin names that are dependencies of the one specified
110
+ def build_dependencies_tree(plugin)
111
+ unless @plugins.include?(plugin)
112
+ clone(plugin)
113
+ manifest_yml = manifest(plugin)
114
+ Octopress.logger.debug manifest_yml.to_s
115
+ return [plugin] if !manifest_yml.has_key?("dependencies") || manifest_yml["dependencies"].size == 0
116
+ manifest_yml["dependencies"].each do |dep|
117
+ build_dependencies_tree(dep)
118
+ end
119
+ else
120
+ Octopress.logger.warn "Already installed #{plugin}."
121
+ end
122
+ end
123
+
124
+ # Public: copy files from the plugin clone to the user's source directory
125
+ #
126
+ # plugin - the plugin name
127
+ #
128
+ # Returns an Array of file paths which were copied
129
+ def copy_files(plugin)
130
+ manifest_yml = manifest(plugin)
131
+ %w[javascripts stylesheets plugins config source includes].each do |type|
132
+ Octopress.logger.debug "Copying #{type} files for #{plugin}..."
133
+ send("copy_#{type}_files", plugin)
134
+ end
135
+ end
136
+
137
+ # Public: install a plugin and its dependencies
138
+ #
139
+ # plugin - the plugin name
140
+ #
141
+ # Returns the Array of all plugins installed so far
142
+ def install(plugin)
143
+ @plugins.merge(build_dependencies_tree(plugin))
144
+ @plugins.each do |plugin|
145
+ copy_files(plugin)
146
+ end
147
+
148
+ @plugins
149
+ end
150
+
151
+ private
152
+ # Private: Copy file to Octopress installation
153
+ #
154
+ # files - a list of files
155
+ # destination - the directory in which the files should be copied
156
+ #
157
+ # Returns nothing
158
+ def copy_file_list(files, destination)
159
+ if files.size > 0
160
+ FileUtils.mkdir_p(destination, verbose: false) unless File.directory?(destination)
161
+ if files.is_a?(String) && File.directory?(files)
162
+ Octopress.logger.debug "Copying #{files}/. to #{destination} ..."
163
+ FileUtils.cp_r "#{files}/.", destination, verbose: false
164
+ else
165
+ Octopress.logger.debug "Copying #{files.join(", ")} to #{destination} ..."
166
+ FileUtils.cp files, destination, verbose: false
167
+ end
168
+ end
169
+ end
170
+
171
+ # Private: Fetch list of files in a file recursively
172
+ #
173
+ # plugin - plugin name
174
+ # *subdirs - a
175
+ def globbed_filelist(plugin, *subdirs)
176
+ Dir.glob(File.join(cache_dir(plugin), *subdirs, "**", "*")).select do |filename|
177
+ File.file?(filename)
178
+ end
179
+ end
180
+
181
+ # Private: Copy source files to local Octopress installation
182
+ #
183
+ # plugin - plugin name
184
+ #
185
+ # Returns nothing
186
+ def copy_source_files(plugin)
187
+ source = File.join(cache_dir(plugin), "source")
188
+ destination = File.join(Octopress.root, Octopress.configuration[:source])
189
+ destination = File.join(destination, namespace(plugin)) if manifest(plugin)["type"] != "theme"
190
+ if File.directory?(source)
191
+ copy_file_list(source, destination)
192
+ end
193
+ end
194
+
195
+ # Private: Copy includes files to local Octopress installation
196
+ #
197
+ # plugin - plugin name
198
+ #
199
+ # Returns nothing
200
+ def copy_includes_files(plugin)
201
+ source = File.join(cache_dir(plugin), "includes")
202
+ destination = File.join(Octopress.root, Octopress.configuration[:source], "_includes", namespace(plugin))
203
+ if File.directory?(source)
204
+ copy_file_list(source, destination)
205
+ end
206
+ end
207
+
208
+ # Private: Copy javascript files to local Octopress installation
209
+ #
210
+ # plugin - plugin name
211
+ # files - the filenames of the stylesheet files for this plugin relative to
212
+ # the stylesheets dir in the plugin's install dir
213
+ #
214
+ # Returns nothing
215
+ def copy_config_files(plugin)
216
+ source = File.join(cache_dir(plugin), "configs")
217
+ destination = File.join(Octopress.root, "config", "defaults", namespace(plugin))
218
+ if File.directory?(source)
219
+ copy_file_list(source, destination)
220
+ end
221
+ end
222
+
223
+ def config_files(plugin)
224
+ globbed_filelist(plugin, "configs")
225
+ end
226
+
227
+ # Private: Copy javascript files to local Octopress installation
228
+ #
229
+ # plugin - plugin name
230
+ #
231
+ # Returns nothing
232
+ def copy_javascripts_files(plugin)
233
+ source = File.join(cache_dir(plugin), "javascripts", "lib")
234
+ destination = File.join(Octopress.root, "javascripts", "lib", namespace(plugin))
235
+ if File.directory?(source)
236
+ copy_file_list(source, destination)
237
+ end
238
+ source = File.join(cache_dir(plugin), "javascripts", "modules")
239
+ destination = File.join(Octopress.root, "javascripts", "modules", namespace(plugin))
240
+ if File.directory?(source)
241
+ copy_file_list(source, destination)
242
+ end
243
+ end
244
+
245
+ # Private: Copy javascript files to local Octopress installation
246
+ #
247
+ # plugin - plugin name
248
+ # files - the filenames of the stylesheet files for this plugin relative to
249
+ # the stylesheets dir in the plugin's install dir
250
+ #
251
+ # Returns nothing
252
+ def copy_stylesheets_files(plugin)
253
+ source = File.join(cache_dir(plugin), "stylesheets")
254
+ sass_dir = File.join(Octopress.root, "stylesheets")
255
+ namespace = namespace(plugin)
256
+
257
+ if namespace == 'theme'
258
+ destination = File.join(sass_dir, namespace(plugin))
259
+ else
260
+ destination = File.join(sass_dir, 'plugins', namespace(plugin))
261
+ end
262
+ if File.directory?(source)
263
+ copy_file_list(source, destination)
264
+ end
265
+ end
266
+
267
+ # Private: Copy javascript files to local Octopress installation
268
+ #
269
+ # plugin - plugin name
270
+ # files - the filenames of the Jekyll plugin files for this plugin relative
271
+ # to the plugin dir in the plugin's install dir
272
+ #
273
+ # Returns nothing
274
+ def copy_plugins_files(plugin)
275
+ source = File.join(cache_dir(plugin), "plugins")
276
+ install_dir = Octopress.configuration[:plugins].is_a?(Array) ? Octopress.configuration[:plugins].last : Octopress.configuration[:plugins]
277
+ destination = File.join(Octopress.root, install_dir, namespace(plugin))
278
+ if File.directory?(source)
279
+ copy_file_list(source, destination)
280
+ end
281
+ end
282
+
283
+ def plugin_files(plugin)
284
+ globbed_filelist(plugin, "plugins")
285
+ end
286
+ end
287
+ end
@@ -0,0 +1,3 @@
1
+ module Octopress
2
+ class SiteNotFoundError < ArgumentError; end
3
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path("../helpers/titlecase.rb", File.dirname(__FILE__))
4
+ module Octopress
5
+ module ContentFilters
6
+
7
+ # Escapes CDATA sections in post content
8
+
9
+ def cdata_escape(input)
10
+ input.gsub(/<!\[CDATA\[/, '&lt;![CDATA[').gsub(/\]\]>/, ']]&gt;')
11
+ end
12
+
13
+ # Used on the blog index to split posts on the <!--more--> marker
14
+
15
+ def excerpt(input)
16
+ if input.index(/<!--\s*more\s*-->/i)
17
+ input.split(/<!--\s*more\s*-->/i)[0]
18
+ else
19
+ input
20
+ end
21
+ end
22
+
23
+ # Checks for excerpts (helpful for template conditionals)
24
+
25
+ def has_excerpt(input)
26
+ input =~ /<!--\s*more\s*-->/i ? true : false
27
+ end
28
+
29
+ # Summary is used on the Archive pages to return the first block of content from a post.
30
+
31
+ def summary(input)
32
+ if input.index(/\n\n/)
33
+ input.split(/\n\n/)[0]
34
+ else
35
+ input
36
+ end
37
+ end
38
+
39
+ # Improved version of Liquid's truncate:
40
+ # - Doesn't cut in the middle of a word.
41
+ # - Uses typographically correct ellipsis (…) insted of '...'
42
+
43
+ def truncate(input, length)
44
+ if input.length > length && input[0..(length-1)] =~ /(.+)\b.+$/im
45
+ $1.strip + ' &hellip;'
46
+ else
47
+ input
48
+ end
49
+ end
50
+
51
+ # Improved version of Liquid's truncatewords:
52
+ # - Uses typographically correct ellipsis (…) insted of '...'
53
+
54
+ def truncatewords(input, length)
55
+ truncate = input.split(' ')
56
+ if truncate.length > length
57
+ truncate[0..length-1].join(' ').strip + ' &hellip;'
58
+ else
59
+ input
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ Liquid::Template.register_filter Octopress::ContentFilters
66
+
@@ -0,0 +1,46 @@
1
+ module Octopress
2
+ module Date
3
+ # Returns a datetime if the input is a string
4
+ def datetime(date)
5
+ if date.class == String
6
+ date = Time.parse(date)
7
+ end
8
+ date
9
+ end
10
+
11
+ # Returns an ordidinal date eg July 22 2007 -> July 22nd 2007
12
+ def ordinalize(date)
13
+ date = datetime(date)
14
+ "#{date.strftime('%b')} #{ordinal(date.strftime('%e').to_i)}, #{date.strftime('%Y')}"
15
+ end
16
+
17
+ # Returns an ordinal number. 13 -> 13th, 21 -> 21st etc.
18
+ def ordinal(number)
19
+ if (11..13).include?(number.to_i % 100)
20
+ "#{number}<span>th</span>"
21
+ else
22
+ case number.to_i % 10
23
+ when 1; "#{number}<span>st</span>"
24
+ when 2; "#{number}<span>nd</span>"
25
+ when 3; "#{number}<span>rd</span>"
26
+ else "#{number}<span>th</span>"
27
+ end
28
+ end
29
+ end
30
+
31
+ # Formats date either as ordinal or by given date format
32
+ # Adds %o as ordinal representation of the day
33
+ def format_date(date, format)
34
+ date = datetime(date)
35
+ if format.nil? || format.empty? || format == "ordinal"
36
+ date_formatted = ordinalize(date)
37
+ else
38
+ date_formatted = date.strftime(format)
39
+ date_formatted.gsub!(/%o/, ordinal(date.strftime('%e').to_i))
40
+ end
41
+ date_formatted
42
+ end
43
+ end
44
+ end
45
+
46
+ Liquid::Template.register_filter Octopress::Date