1+ require "rubygems"
2+ require 'rake'
3+ require 'yaml'
4+ require 'time'
5+
6+ SOURCE = "."
7+ CONFIG = {
8+ 'version' => "0.3.0" ,
9+ 'themes' => File . join ( SOURCE , "_includes" , "themes" ) ,
10+ 'layouts' => File . join ( SOURCE , "_layouts" ) ,
11+ 'posts' => File . join ( SOURCE , "_posts" ) ,
12+ 'post_ext' => "md" ,
13+ 'theme_package_version' => "0.1.0"
14+ }
15+
16+ # Path configuration helper
17+ module JB
18+ class Path
19+ SOURCE = "."
20+ Paths = {
21+ :layouts => "_layouts" ,
22+ :themes => "_includes/themes" ,
23+ :theme_assets => "assets/themes" ,
24+ :theme_packages => "_theme_packages" ,
25+ :posts => "_posts"
26+ }
27+
28+ def self . base
29+ SOURCE
30+ end
31+
32+ # build a path relative to configured path settings.
33+ def self . build ( path , opts = { } )
34+ opts [ :root ] ||= SOURCE
35+ path = "#{ opts [ :root ] } /#{ Paths [ path . to_sym ] } /#{ opts [ :node ] } " . split ( "/" )
36+ path . compact!
37+ File . __send__ :join , path
38+ end
39+
40+ end #Path
41+ end #JB
42+
43+ # Usage: rake post title="A Title" [date="2012-02-09"] [tags=[tag1, tag2]]
44+ desc "Begin a new post in #{ CONFIG [ 'posts' ] } "
45+ task :post do
46+ abort ( "rake aborted: '#{ CONFIG [ 'posts' ] } ' directory not found." ) unless FileTest . directory? ( CONFIG [ 'posts' ] )
47+ title = ENV [ "title" ] || "new-post"
48+ tags = ENV [ "tags" ] || "[]"
49+ slug = title . downcase . strip . gsub ( ' ' , '-' ) . gsub ( /[^\w -]/ , '' )
50+ begin
51+ date = ( ENV [ 'date' ] ? Time . parse ( ENV [ 'date' ] ) : Time . now ) . strftime ( '%Y-%m-%d' )
52+ rescue => e
53+ puts "Error - date format must be YYYY-MM-DD, please check you typed it correctly!"
54+ exit -1
55+ end
56+ filename = File . join ( CONFIG [ 'posts' ] , "#{ date } -#{ slug } .#{ CONFIG [ 'post_ext' ] } " )
57+ if File . exist? ( filename )
58+ abort ( "rake aborted!" ) if ask ( "#{ filename } already exists. Do you want to overwrite?" , [ 'y' , 'n' ] ) == 'n'
59+ end
60+
61+ puts "Creating new post: #{ filename } "
62+ open ( filename , 'w' ) do |post |
63+ post . puts "---"
64+ post . puts "layout: post"
65+ post . puts "title: \" #{ title . gsub ( /-/ , ' ' ) } \" "
66+ post . puts "date: #{ date } 22:03:50"
67+ post . puts "---"
68+ post . puts ""
69+ end
70+ end # task :post
71+
72+ # Usage: rake page name="about.html"
73+ # You can also specify a sub-directory path.
74+ # If you don't specify a file extention we create an index.html at the path specified
75+ desc "Create a new page."
76+ task :page do
77+ name = ENV [ "name" ] || "new-page.md"
78+ filename = File . join ( SOURCE , "#{ name } " )
79+ filename = File . join ( filename , "index.html" ) if File . extname ( filename ) == ""
80+ title = File . basename ( filename , File . extname ( filename ) ) . gsub ( /[\W \_ ]/ , " " ) . gsub ( /\b \w / ) { $&. upcase }
81+ if File . exist? ( filename )
82+ abort ( "rake aborted!" ) if ask ( "#{ filename } already exists. Do you want to overwrite?" , [ 'y' , 'n' ] ) == 'n'
83+ end
84+
85+ mkdir_p File . dirname ( filename )
86+ puts "Creating new page: #{ filename } "
87+ open ( filename , 'w' ) do |post |
88+ post . puts "---"
89+ post . puts "layout: page"
90+ post . puts "title: \" #{ title } \" "
91+ post . puts 'description: ""'
92+ post . puts "---"
93+ post . puts "{% include JB/setup %}"
94+ end
95+ end # task :page
96+
97+ desc "Launch preview environment"
98+ task :preview do
99+ system "jekyll serve -w"
100+ end # task :preview
101+
102+ # Public: Alias - Maintains backwards compatability for theme switching.
103+ task :switch_theme => "theme:switch"
104+
105+ namespace :theme do
106+
107+ # Public: Switch from one theme to another for your blog.
108+ #
109+ # name - String, Required. name of the theme you want to switch to.
110+ # The theme must be installed into your JB framework.
111+ #
112+ # Examples
113+ #
114+ # rake theme:switch name="the-program"
115+ #
116+ # Returns Success/failure messages.
117+ desc "Switch between Jekyll-bootstrap themes."
118+ task :switch do
119+ theme_name = ENV [ "name" ] . to_s
120+ theme_path = File . join ( CONFIG [ 'themes' ] , theme_name )
121+ settings_file = File . join ( theme_path , "settings.yml" )
122+ non_layout_files = [ "settings.yml" ]
123+
124+ abort ( "rake aborted: name cannot be blank" ) if theme_name . empty?
125+ abort ( "rake aborted: '#{ theme_path } ' directory not found." ) unless FileTest . directory? ( theme_path )
126+ abort ( "rake aborted: '#{ CONFIG [ 'layouts' ] } ' directory not found." ) unless FileTest . directory? ( CONFIG [ 'layouts' ] )
127+
128+ Dir . glob ( "#{ theme_path } /*" ) do |filename |
129+ next if non_layout_files . include? ( File . basename ( filename ) . downcase )
130+ puts "Generating '#{ theme_name } ' layout: #{ File . basename ( filename ) } "
131+
132+ open ( File . join ( CONFIG [ 'layouts' ] , File . basename ( filename ) ) , 'w' ) do |page |
133+ if File . basename ( filename , ".html" ) . downcase == "default"
134+ page . puts "---"
135+ page . puts File . read ( settings_file ) if File . exist? ( settings_file )
136+ page . puts "---"
137+ else
138+ page . puts "---"
139+ page . puts "layout: default"
140+ page . puts "---"
141+ end
142+ page . puts "{% include JB/setup %}"
143+ page . puts "{% include themes/#{ theme_name } /#{ File . basename ( filename ) } %}"
144+ end
145+ end
146+
147+ puts "=> Theme successfully switched!"
148+ puts "=> Reload your web-page to check it out =)"
149+ end # task :switch
150+
151+ # Public: Install a theme using the theme packager.
152+ # Version 0.1.0 simple 1:1 file matching.
153+ #
154+ # git - String, Optional path to the git repository of the theme to be installed.
155+ # name - String, Optional name of the theme you want to install.
156+ # Passing name requires that the theme package already exist.
157+ #
158+ # Examples
159+ #
160+ # rake theme:install git="https://github.com/jekyllbootstrap/theme-twitter.git"
161+ # rake theme:install name="cool-theme"
162+ #
163+ # Returns Success/failure messages.
164+ desc "Install theme"
165+ task :install do
166+ if ENV [ "git" ]
167+ manifest = theme_from_git_url ( ENV [ "git" ] )
168+ name = manifest [ "name" ]
169+ else
170+ name = ENV [ "name" ] . to_s . downcase
171+ end
172+
173+ packaged_theme_path = JB ::Path . build ( :theme_packages , :node => name )
174+
175+ abort ( "rake aborted!
176+ => ERROR: 'name' cannot be blank" ) if name . empty?
177+ abort ( "rake aborted!
178+ => ERROR: '#{ packaged_theme_path } ' directory not found.
179+ => Installable themes can be added via git. You can find some here: http://github.com/jekyllbootstrap
180+ => To download+install run: `rake theme:install git='[PUBLIC-CLONE-URL]'`
181+ => example : rake theme:install git='git@github.com:jekyllbootstrap/theme-the-program.git'
182+ " ) unless FileTest . directory? ( packaged_theme_path )
183+
184+ manifest = verify_manifest ( packaged_theme_path )
185+
186+ # Get relative paths to packaged theme files
187+ # Exclude directories as they'll be recursively created. Exclude meta-data files.
188+ packaged_theme_files = [ ]
189+ FileUtils . cd ( packaged_theme_path ) {
190+ Dir . glob ( "**/*.*" ) { |f |
191+ next if ( FileTest . directory? ( f ) || f =~ /^(manifest|readme|packager)/i )
192+ packaged_theme_files << f
193+ }
194+ }
195+
196+ # Mirror each file into the framework making sure to prompt if already exists.
197+ packaged_theme_files . each do |filename |
198+ file_install_path = File . join ( JB ::Path . base , filename )
199+ if File . exist? file_install_path and ask ( "#{ file_install_path } already exists. Do you want to overwrite?" , [ 'y' , 'n' ] ) == 'n'
200+ next
201+ else
202+ mkdir_p File . dirname ( file_install_path )
203+ cp_r File . join ( packaged_theme_path , filename ) , file_install_path
204+ end
205+ end
206+
207+ puts "=> #{ name } theme has been installed!"
208+ puts "=> ---"
209+ if ask ( "=> Want to switch themes now?" , [ 'y' , 'n' ] ) == 'y'
210+ system ( "rake switch_theme name='#{ name } '" )
211+ end
212+ end
213+
214+ # Public: Package a theme using the theme packager.
215+ # The theme must be structured using valid JB API.
216+ # In other words packaging is essentially the reverse of installing.
217+ #
218+ # name - String, Required name of the theme you want to package.
219+ #
220+ # Examples
221+ #
222+ # rake theme:package name="twitter"
223+ #
224+ # Returns Success/failure messages.
225+ desc "Package theme"
226+ task :package do
227+ name = ENV [ "name" ] . to_s . downcase
228+ theme_path = JB ::Path . build ( :themes , :node => name )
229+ asset_path = JB ::Path . build ( :theme_assets , :node => name )
230+
231+ abort ( "rake aborted: name cannot be blank" ) if name . empty?
232+ abort ( "rake aborted: '#{ theme_path } ' directory not found." ) unless FileTest . directory? ( theme_path )
233+ abort ( "rake aborted: '#{ asset_path } ' directory not found." ) unless FileTest . directory? ( asset_path )
234+
235+ ## Mirror theme's template directory (_includes)
236+ packaged_theme_path = JB ::Path . build ( :themes , :root => JB ::Path . build ( :theme_packages , :node => name ) )
237+ mkdir_p packaged_theme_path
238+ cp_r theme_path , packaged_theme_path
239+
240+ ## Mirror theme's asset directory
241+ packaged_theme_assets_path = JB ::Path . build ( :theme_assets , :root => JB ::Path . build ( :theme_packages , :node => name ) )
242+ mkdir_p packaged_theme_assets_path
243+ cp_r asset_path , packaged_theme_assets_path
244+
245+ ## Log packager version
246+ packager = { "packager" => { "version" => CONFIG [ "theme_package_version" ] . to_s } }
247+ open ( JB ::Path . build ( :theme_packages , :node => "#{ name } /packager.yml" ) , "w" ) do |page |
248+ page . puts packager . to_yaml
249+ end
250+
251+ puts "=> '#{ name } ' theme is packaged and available at: #{ JB ::Path . build ( :theme_packages , :node => name ) } "
252+ end
253+
254+ end # end namespace :theme
255+
256+ # Internal: Download and process a theme from a git url.
257+ # Notice we don't know the name of the theme until we look it up in the manifest.
258+ # So we'll have to change the folder name once we get the name.
259+ #
260+ # url - String, Required url to git repository.
261+ #
262+ # Returns theme manifest hash
263+ def theme_from_git_url ( url )
264+ tmp_path = JB ::Path . build ( :theme_packages , :node => "_tmp" )
265+ abort ( "rake aborted: system call to git clone failed" ) if !system ( "git clone #{ url } #{ tmp_path } " )
266+ manifest = verify_manifest ( tmp_path )
267+ new_path = JB ::Path . build ( :theme_packages , :node => manifest [ "name" ] )
268+ if File . exist? ( new_path ) && ask ( "=> #{ new_path } theme package already exists. Override?" , [ 'y' , 'n' ] ) == 'n'
269+ remove_dir ( tmp_path )
270+ abort ( "rake aborted: '#{ manifest [ "name" ] } ' already exists as theme package." )
271+ end
272+
273+ remove_dir ( new_path ) if File . exist? ( new_path )
274+ mv ( tmp_path , new_path )
275+ manifest
276+ end
277+
278+ # Internal: Process theme package manifest file.
279+ #
280+ # theme_path - String, Required. File path to theme package.
281+ #
282+ # Returns theme manifest hash
283+ def verify_manifest ( theme_path )
284+ manifest_path = File . join ( theme_path , "manifest.yml" )
285+ manifest_file = File . open ( manifest_path )
286+ abort ( "rake aborted: repo must contain valid manifest.yml" ) unless File . exist? manifest_file
287+ manifest = YAML . load ( manifest_file )
288+ manifest_file . close
289+ manifest
290+ end
291+
292+ def ask ( message , valid_options )
293+ if valid_options
294+ answer = get_stdin ( "#{ message } #{ valid_options . to_s . gsub ( /"/ , '' ) . gsub ( /, / , '/' ) } " ) while !valid_options . include? ( answer )
295+ else
296+ answer = get_stdin ( message )
297+ end
298+ answer
299+ end
300+
301+ def get_stdin ( message )
302+ print message
303+ STDIN . gets . chomp
304+ end
305+
306+ #Load custom rake scripts
307+ Dir [ '_rake/*.rake' ] . each { |r | load r }
0 commit comments