pekky 0.2 → 0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -35,17 +35,14 @@
35
35
 
36
36
  TODO
37
37
  * Get specs up to speed
38
- * Add the option of naming pages
39
- * Support shared content
40
- * Add helpers for slurping up a collection of shared content i.e. news feed
41
- * Support alternate formats correctly
42
38
  * Compile stylesheets with less or sass
43
39
  * Compile javascripts with Coffee
44
40
 
45
41
 
46
42
  CAVEATS
47
43
  * Not actually finished soz
48
- * No Windows support. If someone wants to build it that’s cool, but I’m lazy.
44
+ * Windows support with cygwin only. If someone wants to fix this, that’s cool,
45
+ but I’m lazy.
49
46
  * Limited Mustache support. It won’t play with arbitrary contexts.
50
47
  * May potentially be slow
51
48
 
data/lib/pekky/builder.rb CHANGED
@@ -1,20 +1,13 @@
1
1
  module Pekky
2
2
  module Builder
3
3
  def self.build
4
- Context.flush!
5
4
  check_for_output_dir
6
5
  copy_static_assets
7
-
8
- @pages = []
9
- # This has to be done in three loops so we can collect the meta data and
10
- # content for each page first, assemble them into a tree, then render.
11
- #
12
- # This ensures that every page will have complete access to the entire
13
- # site and it's content as it is being rendered, calling helpers etc.
14
- pages = SiteConfig.page_configs.collect {|p| p.prepare}
15
- pages.flatten!
16
- Tree.add(pages)
17
- pages.each {|p| p.render}
6
+
7
+ Pekky::Content.flush!
8
+
9
+ Tree.add(Config.page_configs)
10
+ Config.page_configs.each {|p| p.render}
18
11
  end
19
12
 
20
13
  def self.build!
@@ -23,17 +16,17 @@ module Pekky
23
16
  end
24
17
 
25
18
  def self.clear_output_dir
26
- system("rm -rf '#{SiteConfig[:output_dir]}/*'") if File.exists?(SiteConfig[:output_dir])
19
+ system("rm -rf '#{Config[:output_dir]}/*'") if File.exists?(Config[:output_dir])
27
20
  end
28
21
 
29
- def self.check_for_output_dir
30
- FileUtils.mkdir(SiteConfig[:output_dir]) unless File.exists?(SiteConfig[:output_dir])
22
+ def self.check_for_output_dir
23
+ FileUtils.mkdir(Config[:output_dir]) unless File.exists?(Config[:output_dir])
31
24
  end
32
25
 
33
26
  def self.directory(path)
34
- unless File.directory?(File.join(SiteConfig[:output_dir], path))
27
+ unless File.directory?(File.join(Config[:output_dir], path))
35
28
  parts = path.split("/")
36
- fragment = SiteConfig[:output_dir].clone
29
+ fragment = Config[:output_dir].clone
37
30
  while parts.length > 0
38
31
  fragment = File.join(fragment, parts.shift)
39
32
  FileUtils.mkdir(fragment) unless File.directory?(fragment)
@@ -42,13 +35,13 @@ module Pekky
42
35
  end
43
36
 
44
37
  def self.copy_static_assets
45
- system("cp -fR '#{SiteConfig[:public_dir]}/.' '#{SiteConfig[:output_dir]}/.'")
38
+ system("cp -fR '#{Config[:public_dir]}/.' '#{Config[:output_dir]}/.'")
46
39
  end
47
40
 
48
41
  def self.generate(destination)
49
42
  destination ||= Dir.pwd
50
43
  FileUtils.mkdir(destination) unless File.exists?(destination)
51
- dirs = %w(content views public public/stylesheets public/javascripts public/images)
44
+ dirs = %w(content views views/layouts views/partials public public/stylesheets public/javascripts public/images)
52
45
  dirs.each do |d|
53
46
  FileUtils.mkdir(File.join(destination, d))
54
47
  end
@@ -0,0 +1,84 @@
1
+ module Pekky
2
+ module Config
3
+ @default_config = {
4
+ :content_dir => '/content',
5
+ :view_dir => '/views',
6
+ :layouts_dir => '/views/layouts',
7
+ :partials_dir => '/views/partials',
8
+ :public_dir => '/public',
9
+ :output_dir => '/output',
10
+ :javascripts_path => '/javascripts',
11
+ :stylesheets_path => '/stylesheets',
12
+ :images_path => '/images',
13
+ :templating => 'haml',
14
+ :css_processor => 'sass'
15
+ }
16
+
17
+ @config = {}
18
+ @loaded = false
19
+
20
+ def self.load(p)
21
+ unless @loaded
22
+ @config = @default_config.merge(@config)
23
+ @config[:root] = p
24
+ @config.each do |k, v|
25
+ @config[k] = File.join(p, v) if k.to_s.match(/_dir$/)
26
+ end
27
+ @loaded = true
28
+ end
29
+ end
30
+
31
+ @page_configs = []
32
+ @routes = {}
33
+
34
+ def self.page_configs
35
+ @page_configs
36
+ end
37
+
38
+ def self.[](name)
39
+ @config[name]
40
+ end
41
+
42
+ def self.[]=(option, val)
43
+ set(option, val)
44
+ end
45
+
46
+ private
47
+
48
+ def self.set(option, val)
49
+ if option.to_s.match(/_dir$/)
50
+ @config[option] = File.join(self[:root], val)
51
+ else
52
+ @config[option] = val
53
+ end
54
+ end
55
+
56
+ def self.page(name, path, content = nil, opts = {})
57
+ @page_configs << if content.is_a? Hash
58
+ Page.new(name, path, content, opts)
59
+ else
60
+ Page.new(name, path, Content.get(content), opts)
61
+ end
62
+ end
63
+
64
+ def self.route(name, path)
65
+ placeholders = path.scan(/:(\S+)/).flatten!
66
+ @routes[name.to_sym] = {:path => path, :placeholders => placeholders}
67
+ end
68
+
69
+ def self.pages(name, path, contents, opts = {})
70
+ route(name, path)
71
+ placeholders = path.scan(/:(\S+)/).flatten!
72
+ Content.get(contents).each do |c|
73
+ page_path = path.dup
74
+ page_name = name.to_s
75
+ placeholders.each do |p|
76
+ page_path.sub!(':' + p, c[p])
77
+ page_name += ('_' + c[p])
78
+ end
79
+
80
+ @page_configs << Page.new(page_name, page_path, c, opts.dup)
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/pekky/context.rb CHANGED
@@ -1,72 +1,70 @@
1
1
  module Pekky
2
+ # For every page instance in the site there is a corresponding context
3
+ # instance. The context is used when rendering the layout and views,
4
+ # encapsulating the page content and providing the built-in helpers.
5
+ #
6
+ # It also hosts any helpers provided in the helpers.rb file.
2
7
  class Context
8
+ # Some attribute writers for storing information in contexts attached to
9
+ # layouts. This is because the layout needs to have access to the rendered
10
+ # view in order to inject it into itself.
3
11
  attr_writer :view_output, :is_layout
4
12
 
5
- @shared = {}
6
-
7
- def self.flush!
8
- @shared.clear
9
- end
10
-
11
- def self.get(name, sort)
12
- @shared[name] ||= begin
13
- path = File.join(SiteConfig[:content_dir], name)
14
- if File.directory?(path)
15
- collection = Dir[path + '/*.yml'].inject([]) do |a, y|
16
- a << YAML.load_file(y)
17
- a
18
- end
19
- collection.sort! {|a, b| a[sort] <=> b[sort]} if sort
20
- collection
21
- else
22
- YAML.load_file(path + ".yml")
23
- end
24
- end
25
- end
26
-
13
+ # Initialize stores the reference to the page instance so that it can
14
+ # expose it to the view when rendering.
27
15
  def initialize(page)
28
16
  @page = page
29
17
  @is_layout = false
30
18
  end
31
19
 
32
- def get(name, sort = nil)
33
- self.class.get(name, sort)
34
- end
35
-
20
+ # A shortcut to the site configuration. This is here to allow users to
21
+ # store and access common, re-used details like the site title.
36
22
  def config
37
- SiteConfig
23
+ Config
38
24
  end
39
25
 
40
- def text(markup, val)
41
- case markup
42
- when :markdown then markdown(val)
43
- when :textile then markdown(textile)
44
- else val
45
- end
26
+ # A shortcut to the Formatters module. Users call methods on the module,
27
+ # which then calls the relevant formatter.
28
+ #
29
+ # format.textile(content[:body])
30
+ #
31
+ # Formatters accept a format like textile or haml and transform it into
32
+ # HTML markup.
33
+ def format
34
+ Format::Formatters
46
35
  end
47
36
 
48
- def markdown(val)
49
- unless Kernel.const_defined? :Markdown
50
- require 'rdiscount'
51
- end
52
-
53
- Markdown.new(val, :smart).to_html
37
+ # Shortcut to the filters module. Filters accept HTML markup and manipulate
38
+ # it in some way. For example, extracting an modifying links. They're called
39
+ # in the same way as the formatters.
40
+ #
41
+ # filter.links(markup)
42
+ #
43
+ def filter
44
+ Format::Filters
54
45
  end
55
46
 
56
- def textile(val)
57
- unless Kernel.const_defined? :RedCloth
58
- require 'RedCloth'
59
- end
60
-
61
- RedCloth.new(val).to_html
47
+ # Makes a call to Content#get and returns the content specified by the path
48
+ # argument. An argument of a directory name will return an array of content
49
+ # objects. The path to a single YAML file will return just the one object.
50
+ def get(path)
51
+ Content.get(path)
62
52
  end
63
-
53
+
54
+ # Renders the specified partial. The partial should only have it's name
55
+ # specified, not it's entire extension i.e. no '.html.haml'
56
+ #
57
+ # partial('profiles/full')
58
+ #
64
59
  def partial(path)
65
- file_name = "#{path}.html.#{SiteConfig[:templating]}"
66
- path = File.join(SiteConfig[:partials_dir], file_name)
60
+ file_name = "#{path}.html.#{Config[:templating]}"
61
+ path = File.join(Config[:partials_dir], file_name)
67
62
  Tilt.new(path).render(self)
68
63
  end
69
64
 
65
+ # A helper for injecting views into layouts. This method should be called
66
+ # at least once inside a layout. If you try calling it inside a view it will
67
+ # output a warning.
70
68
  def view
71
69
  if @is_layout
72
70
  @view_output
@@ -75,29 +73,52 @@ module Pekky
75
73
  end
76
74
  end
77
75
 
76
+ # Generates a link to a stylesheet. At it's most basic you only need to
77
+ # specify the name, but you can also optionally specify the media, name etc.
78
+ #
79
+ # stylesheet('print', :media => 'print')
80
+ #
78
81
  def stylesheet(name, opts = {})
79
82
  opts['media'] ||= 'screen'
80
83
  opts['rel'] ||= 'stylesheet'
81
84
  opts['type'] = 'text/css'
82
- opts['href'] = "#{qualify_path("#{SiteConfig[:stylesheets_path]}/#{name}")}.css"
85
+ opts['href'] = "#{Format::Util.qualify_path("#{Config[:stylesheets_path]}/#{name}")}.css"
83
86
 
84
87
  self_closing_tag('link', opts)
85
88
  end
86
89
 
90
+ # Generates a javascript tag.
87
91
  def javascript(name)
88
- tag('script', '', :src => "#{qualify_path("#{SiteConfig[:javascripts_path]}/#{name}")}.js", :type => 'text/javascript')
92
+ tag('script', '', :src => "#{Format::Util.qualify_path("#{Config[:javascripts_path]}/#{name}")}.js", :type => 'text/javascript')
89
93
  end
90
94
 
95
+ # Generates an image tag. As a bare minimum, only the name is required, but
96
+ # you can optionally provide additional attributes.
97
+ #
98
+ # image('pix.jpg', :alt => 'Wicked Cool')
99
+ #
91
100
  def image(path, opts = {})
92
- opts['src'] = qualify_path("#{SiteConfig[:images_path]}/#{path}")
101
+ opts['src'] = Format::Util.qualify_path("#{Config[:images_path]}/#{path}")
93
102
  self_closing_tag('img', opts)
94
103
  end
95
-
104
+
105
+ # Creates an anchor tag with the specified URL. It will also accept
106
+ # additional options for the anchor attributes. If you pass in a link with
107
+ # the 'pekky://' protocol, the string will be used as a name look up for an
108
+ # internal page and the URL will be replaced with a real path to the page.
109
+ #
110
+ # link('ZOMG', 'pekky://news_archive') #=> '<a href="/news/archive">ZOMG</a>'
111
+ #
96
112
  def link(text, url, opts = {})
97
- opts['href'] = qualify_path(url)
113
+ if url.index("pekky://") == 0
114
+ url = Format::Util.look_up_page(url)
115
+ end
116
+ opts['href'] = Format::Util.qualify_path(url)
98
117
  tag('a', text, opts)
99
118
  end
100
119
 
120
+ # Generates a content tag of the specified type. The child can either be
121
+ # text or HTML markup.
101
122
  def tag(type, child, opts = nil)
102
123
  if opts
103
124
  "<#{type} #{attrs(opts)}>#{child}</#{type}>"
@@ -106,14 +127,16 @@ module Pekky
106
127
  end
107
128
  end
108
129
 
130
+ # Generates a self closing tag of the specified type.
109
131
  def self_closing_tag(type, opts = nil)
110
132
  if opts
111
133
  "<#{type} #{attrs(opts)}/>"
112
134
  else
113
- "<#{type}>#{contents}/>"
135
+ "<#{type}/>"
114
136
  end
115
137
  end
116
138
 
139
+ # A utility method for converting a hash into a string of attributes.
117
140
  def attrs(opts)
118
141
  out = opts.inject([]) do |a, o|
119
142
  a << "#{o[0]}=\"#{o[1]}\""
@@ -123,54 +146,62 @@ module Pekky
123
146
  out.join(" ").chomp
124
147
  end
125
148
 
126
- def qualify_path(path)
127
- if !path.match(/^http/) and Pekky.exporting? and SiteConfig[:path_prefix]
128
- SiteConfig[:path_prefix] + path
129
- else
130
- path
131
- end
132
- end
133
-
149
+ # A convenience method which returns the top-level pages in the site. It
150
+ # excludes any what have been set as hidden.
134
151
  def nav
135
152
  Pekky.tree.pages.reject {|p| p.hidden? }
136
153
  end
137
154
 
155
+ # Returns the page with the specified name. This name is set in the site.rb
156
+ # or is derived from a sanitised version of the page's path.
138
157
  def page(name)
139
158
  Pekky.tree[name]
140
159
  end
141
160
 
161
+ # Returns the tree of all pages in the site. You can recurse through the
162
+ # entire tree by accessing the #children method on each page.
142
163
  def pages
143
164
  Pekky.tree.pages
144
165
  end
145
166
 
167
+ # The content assigned to the current page.
146
168
  def content
147
169
  @page.content
148
170
  end
149
171
 
172
+ # The path to the current page.
150
173
  def path
151
- qualify_path(@page.path)
174
+ Format::Util.qualify_path(@page.path)
152
175
  end
153
176
 
177
+ # The children of the current page.
154
178
  def children
155
179
  @page.children
156
180
  end
157
181
 
182
+ # The pages which sit above this page in the hierarchy i.e. parent,
183
+ # grant-parent etc.
158
184
  def ancestors
159
185
  collect_ancestors(@page)
160
186
  end
161
187
 
188
+ # The current page's parent.
162
189
  def parent
163
190
  @page.parent
164
191
  end
165
192
 
193
+ # Returns a boolean specifying if this page is the child of another.
166
194
  def child?
167
195
  @page.child?
168
196
  end
169
197
 
198
+ # Returns a boolean specifying if this page is hidden.
170
199
  def hidden?
171
200
  @page.hidden?
172
201
  end
173
202
 
203
+ # A helper method used to recursively collect the ancestors of the current
204
+ # page. It should never be called directly.
174
205
  def collect_ancestors(page, ancestors = [])
175
206
  if page.parent
176
207
  collect_ancestors(page.parent, ancestors)
data/lib/pekky/pages.rb CHANGED
@@ -1,76 +1,90 @@
1
1
  module Pekky
2
- class PageConfig
3
- def initialize(path, content, opts = {})
4
- @path = path
5
- @content = content
6
- @opts = opts
7
- end
8
-
9
- def prepare
10
- Page.new(@path, @content, @opts)
11
- end
12
- end
13
-
2
+ # The page class encapsulates everything needed to render the actual content
3
+ # to disk -- the destination path, content and templates. It also contains
4
+ # the meta-data for a page -- parents, children, name etc.
14
5
  class Page
15
- attr_reader :path, :children, :content, :opts, :file_name, :name
6
+ # Various attribute accessors for storing all the values we reuse across
7
+ # the different methods.
8
+ attr_reader :path, :directory, :children, :content, :opts, :file_name, :name
9
+
10
+ # This accessor will be used to store a reference to the parent page --
11
+ # if there is one. The parent page will be updated when the tree gets
12
+ # built. See the Builder class for more info.
16
13
  attr_accessor :parent
17
14
 
18
- def initialize(path, content, opts)
19
- @path = path
20
- @opts = opts
21
-
22
- # Calculate a name for the page
23
- @name = if opts[:name]
24
- opts.delete(:name).to_sym
25
- elsif path == '/'
26
- :root
15
+ # The Page class is initialized with the path, the content -- either a
16
+ # Content instance or a hash -- and a hash of options. It then determines
17
+ # the name of the output file and it's path -- pages without extensions
18
+ # default to 'index.html'. It also determines the format if specified.
19
+ def initialize(name, path, content, opts)
20
+ if content.is_a?(Pekky::Content)
21
+ @content = content
27
22
  else
28
-
29
- path.match(/^\/(\S+)/)[1].gsub(/[\/\-]/, '_').to_sym
23
+ opts = content
30
24
  end
25
+
26
+ @path = path
27
+ @opts = opts
28
+ @children = []
29
+ @opts[:name] = name
31
30
 
32
- @content = if content.is_a? String
33
- content_path = File.join(SiteConfig[:content_dir], "#{content}.yml")
34
- YAML.load_file(content_path)
31
+ if match = @path.match(/^([\S+]?\/)(\S+)\.(\S+)$/)
32
+ @directory = match[1]
33
+ @format = match[3]
34
+ @file_name = "#{match[2]}.#{@format}"
35
35
  else
36
- content
36
+ @directory = path
37
+ @format = 'html'
38
+ @file_name = "index.html"
37
39
  end
38
-
39
- @file_name = "index.#{opts[:ext] || 'html'}"
40
-
41
- @view = view(:view, opts)
42
- @layout = view(:layout, opts)
43
-
44
- @children = []
45
40
  end
46
41
 
42
+ # Compares one page instance with another. It does this by comparing the
43
+ # name -- which will be unique.
47
44
  def ==(other)
48
- path == other.path
45
+ name == other.name
49
46
  end
50
47
 
48
+ # Checks to see if the page is hidden i.e. it doesn't appear in the main
49
+ # navigation. The user can specify this when declaring a page in the
50
+ # site.rb
51
51
  def hidden?
52
52
  !!opts[:hidden]
53
53
  end
54
54
 
55
+ # Is this page a child or does it sit at the top level of the site? It just
56
+ # checks to see if there is only one leading slash. Cheaty, but it works ;)
55
57
  def child?
56
- @path.index("/") > 0
58
+ @path.count("/") == 1
57
59
  end
58
60
 
61
+ # The business part of the page. It renders the page and outputs it to
62
+ # disk. Firstly it asks the Builder to ensure the target directory is on
63
+ # disk. Then it sets up the context -- encapsulating the content -- and the
64
+ # view and layout. Finally it renders the page and writes it to disk.
59
65
  def render
60
- Builder.directory(@path)
66
+ Builder.directory(@directory)
61
67
 
68
+ @content.reload if @content
62
69
  context = Context.new(self)
63
- view_output = @view.render(Context.new(self))
64
- context.view_output = view_output
65
- context.is_layout = true
70
+ view_output = view(:view, @opts).render(context)
66
71
 
67
- File.open(File.join(SiteConfig[:output_dir], @path, @file_name), 'w') do |f|
68
- f.write(@layout.render(context))
72
+ File.open(File.join(Config[:output_dir], @directory, @file_name), 'w') do |f|
73
+ if @opts[:layout] == false
74
+ f.write(view_output)
75
+ else
76
+ layout = view(:layout, opts)
77
+ context.view_output = view_output
78
+ context.is_layout = true
79
+ f.write(layout.render(context))
80
+ end
69
81
  end
70
82
  end
71
83
 
72
84
  private
73
85
 
86
+ # A helper for creating the instances of Tilt for rendering the templates.
87
+ # It handles both the view and the layout.
74
88
  def view(type, opts)
75
89
  if type == :view
76
90
  name = opts[:view] ||= 'default'
@@ -80,43 +94,22 @@ module Pekky
80
94
  dir = :layouts_dir
81
95
  end
82
96
 
83
- file_name = "#{name}.#{opts[:ext] || 'html'}.#{SiteConfig[:templating]}"
84
- path = File.join(SiteConfig[dir], file_name)
97
+ file_name = "#{name}.#{@format}.#{opts[:templating] || Config[:templating]}"
98
+ path = File.join(Config[dir], file_name)
85
99
  Tilt.new(path)
86
100
  end
87
- end
88
-
89
- class GeneratorConfig
90
- def initialize(path, &blk)
101
+ end # Page
102
+
103
+ # The directory class is used to act as a parent for pages which don't have
104
+ # an actual direct parent i.e. /posts/* don't have a corresponding
105
+ # /posts/index.html
106
+ class Directory
107
+ def initialize(path)
91
108
  @path = path
92
- @blk = blk
93
- @pages = []
94
- matches = path.match(/:([a-zA-Z0-9_]+)/)
95
- @path_params = matches[1..matches.length]
96
- end
97
-
98
- def prepare
99
- instance_eval(&@blk)
100
- @pages
101
- end
102
-
103
- def render(template, opts = {})
104
- content = opts[:content] || {}
105
-
106
- opts[:view] = template
107
-
108
- path = @path.dup
109
- @path_params.each do |p|
110
- path.gsub!(/:#{p}/, opts[p.to_sym].to_s)
111
- end
112
-
113
- @pages << Page.new(path, content, opts)
114
109
  end
115
-
116
- private
117
-
118
- def get(name, sort = nil)
119
- Context.get(name, sort)
110
+
111
+ def render
120
112
  end
121
- end
122
- end
113
+ end # Directory
114
+ end # Pekky
115
+
data/lib/pekky/server.rb CHANGED
@@ -1,22 +1,28 @@
1
1
  module Pekky
2
2
  module Server
3
3
  def self.start(port)
4
- require 'rack'
5
4
  Pekky.load
6
5
  app = Rack::Builder.app {
7
- use Rack::Static, :urls => %w(/stylesheets /javascripts /images), :root => Pekky::SiteConfig[:output_dir]
6
+ use Rack::Static, :urls => %w(/stylesheets /javascripts /images), :root => Pekky::Config[:output_dir]
8
7
  run Pekky::Server
9
8
  }
10
- Rack::Handler.default.run(app, :Port => port || 3000)
9
+ Rack::Server.new(:app => app, :Port => port || 3000).start
11
10
  end
12
11
 
13
- def self.call(env)
12
+ def self.call(env)
14
13
  Pekky.build
15
14
  path = env['PATH_INFO']
16
- file = File.join(SiteConfig[:output_dir], path, 'index.html')
15
+ if path.match(/\.(\w+)$/)
16
+ file = File.join(Config[:output_dir], path)
17
+ type = Rack::Mime.mime_type(File.extname(path))
18
+ else
19
+ file = File.join(Config[:output_dir], path, "index.html")
20
+ type = "text/html"
21
+ end
22
+
17
23
  if File.exists?(file)
18
24
  output = File.open(file).read
19
- [200, {"Content-Type" => "text/html"}, [output]]
25
+ [200, {"Content-Type" => type}, [output]]
20
26
  else
21
27
  [200, {"Content-Type" => "text/html"}, "Oh, file is not found; Pekky cries for you."]
22
28
  end
data/lib/pekky/tree.rb CHANGED
@@ -3,6 +3,12 @@ module Pekky
3
3
  @pages = []
4
4
  @map = {}
5
5
 
6
+ class PageMissingError < PekkyError
7
+ def initialize(page)
8
+ @message = "The page ''#{page}' has not been defined. Check your site.rb"
9
+ end
10
+ end
11
+
6
12
  def self.[](name)
7
13
  @map[name]
8
14
  end
data/lib/pekky.rb CHANGED
@@ -1,8 +1,18 @@
1
- # [Tilt]: http://github.com/rtomayko/tilt is used to hanndle the template
1
+ # [Tilt]:http://github.com/rtomayko/tilt is used to hanndle the template
2
2
  # rendering. Pekky assumes that you have the relevant template libraries
3
3
  # installed.
4
+ require 'rubygems'
4
5
  require 'tilt'
5
6
 
7
+ # [Nokogiri]:http://nokogiri.org is required for both parsing output and
8
+ # updating links and also for the tests -- checking that the correct markup is
9
+ # output.
10
+ require 'nokogiri'
11
+
12
+ # Rack is used to run the server. It'll use the default server — generally
13
+ # webbrick.
14
+ require 'rack'
15
+
6
16
  # We need file utils for some of the generation steps, mainly adding and
7
17
  # deleting directories.
8
18
  require 'fileutils'
@@ -10,24 +20,35 @@ require 'fileutils'
10
20
  # The actual content is stored in YAML files, so we need to require the lib.
11
21
  require 'yaml'
12
22
 
13
- # Require all the bits of Pekky. Without these, it is nothing. True friends!
14
- dir = File.expand_path(File.dirname(__FILE__))
15
- require dir + '/pekky/site_config'
16
- require dir + '/pekky/pages'
17
- require dir + '/pekky/tree'
18
- require dir + '/pekky/context'
19
- require dir + '/pekky/builder'
20
- require dir + '/pekky/server'
21
- require dir + '/pekky/console'
22
-
23
23
  # # Pekky!
24
24
  # The main module, which contains all the various kick-off methods. The majority
25
25
  # of the actual logic is defined in the other source files. This module just
26
26
  # serves as a container and shortcut.
27
27
  module Pekky
28
- # The first release, dedicated to everyone's favourite washed-up super-star
29
- VERSION = '0.1'
30
- VERSION_NAME = "Not Rocket Fuel, But Love"
28
+ # The third release, dedicated to stunt-men everywhere.
29
+ VERSION = '0.3'
30
+ VERSION_NAME = "Shit-scared"
31
+
32
+ # A base class for all the errors in Pekky. We’re using custom errors so that
33
+ # we can filter out errors concerning configuration in one place, while still
34
+ # letting other errors filter through like normal. In other words, using a
35
+ # rescue block won't be an impediment to development.
36
+ class PekkyError < StandardError
37
+ attr_reader :message, :title
38
+ end
39
+
40
+ # Require all the bits of Pekky. Without these, it is nothing. True friends!
41
+ # This is done after the declaration of PekkyError to stop things blowing up.
42
+ dir = File.expand_path(File.dirname(__FILE__))
43
+ require dir + '/pekky/config'
44
+ require dir + '/pekky/pages'
45
+ require dir + '/pekky/content'
46
+ require dir + '/pekky/tree'
47
+ require dir + '/pekky/format'
48
+ require dir + '/pekky/context'
49
+ require dir + '/pekky/builder'
50
+ require dir + '/pekky/server'
51
+ require dir + '/pekky/console'
31
52
 
32
53
  # Returns the tree module. The tree module represents the sites pages and
33
54
  # contents arranged into a tree.
@@ -53,15 +74,16 @@ module Pekky
53
74
  # Requires the site file and if defined the helpers file. #load can be called
54
75
  # with an optional root. This is generally not necessary and is mainly used
55
76
  # when testing.
56
- def self.load(root = Dir.pwd)
57
- SiteConfig.set_root(root)
58
- require 'site'
59
- require 'helpers' if File.exists?('./helpers.rb')
77
+ def self.load(root = Dir.pwd)
78
+ Config.load(root)
79
+ require File.join(root, 'site')
80
+ helpers_path = File.join(root, 'helpers.rb')
81
+ require helpers_path if File.exists?(helpers_path)
60
82
  end
61
83
 
62
84
  # Used by the site.rb file to define all the options in the site.
63
85
  def self.site(&blk)
64
- SiteConfig.class_eval(&blk)
86
+ Config.class_eval(&blk)
65
87
  end
66
88
 
67
89
  # Used bu the helpers.rb file to define additional helpers.
metadata CHANGED
@@ -1,45 +1,58 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: pekky
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- version: "0.2"
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.4'
5
+ prerelease:
9
6
  platform: ruby
10
- authors:
7
+ authors:
11
8
  - Luke Matthew Sutton
12
9
  autorequire:
13
10
  bindir: bin
14
11
  cert_chain: []
15
-
16
- date: 2010-05-09 00:00:00 +09:30
17
- default_executable:
18
- dependencies:
19
- - !ruby/object:Gem::Dependency
12
+ date: 2011-11-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
20
15
  name: tilt
16
+ requirement: &70364329519300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
21
23
  prerelease: false
22
- requirement: &id001 !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- segments:
27
- - 0
28
- version: "0"
24
+ version_requirements: *70364329519300
25
+ - !ruby/object:Gem::Dependency
26
+ name: nokogiri
27
+ requirement: &70364329518840 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
29
33
  type: :runtime
30
- version_requirements: *id001
34
+ prerelease: false
35
+ version_requirements: *70364329518840
36
+ - !ruby/object:Gem::Dependency
37
+ name: rack
38
+ requirement: &70364329518420 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70364329518420
31
47
  description: A friendly static site builder
32
48
  email: me@lukematthewsutton.com
33
- executables:
49
+ executables:
34
50
  - pekky
35
51
  extensions: []
36
-
37
52
  extra_rdoc_files: []
38
-
39
- files:
53
+ files:
40
54
  - LICENSE
41
55
  - README
42
- - Thorfile
43
56
  - bin/pekky
44
57
  - lib/pekky.rb
45
58
  - lib/pekky/builder.rb
@@ -47,39 +60,35 @@ files:
47
60
  - lib/pekky/context.rb
48
61
  - lib/pekky/pages.rb
49
62
  - lib/pekky/server.rb
50
- - lib/pekky/site_config.rb
63
+ - lib/pekky/config.rb
51
64
  - lib/pekky/tree.rb
52
65
  - lib/pekky/templates/site.rb
53
66
  - lib/pekky/templates/helpers.rb
54
- has_rdoc: true
55
67
  homepage: http://lukematthewsutton.com/pekky
56
68
  licenses: []
57
-
58
69
  post_install_message:
59
70
  rdoc_options: []
60
-
61
- require_paths:
71
+ require_paths:
62
72
  - lib
63
- required_ruby_version: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
- version: "0"
70
- required_rubygems_version: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- segments:
75
- - 0
76
- version: "0"
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
77
85
  requirements: []
78
-
79
86
  rubyforge_project:
80
- rubygems_version: 1.3.6
87
+ rubygems_version: 1.8.10
81
88
  signing_key:
82
89
  specification_version: 2
83
- summary: "Pekky\xE2\x80\x99s main strengths come from the fact that it chooses explicitness over magic, that it\xE2\x80\x99s defaults are configurable and that it doesn\xE2\x80\x99t assume all content is derived from files on disk. For example Pekky can generate pages from databases, CSV files or web API calls."
90
+ summary: Pekky’s main strengths come from the fact that it chooses explicitness over
91
+ magic, that it’s defaults are configurable and that it doesn’t assume all content
92
+ is derived from files on disk. For example Pekky can generate pages from databases,
93
+ CSV files or web API calls.
84
94
  test_files: []
85
-
data/Thorfile DELETED
@@ -1,39 +0,0 @@
1
- class App < Thor
2
- desc "docs", "generate Docco documentation"
3
- def docs
4
- if File.exists?('docs')
5
- system('rm -rf doc/*')
6
- else
7
- system('mkdir docs')
8
- end
9
- system('rocco lib/pekky.rb -o docs')
10
- system('rocco lib/pekky/*.rb -o docs')
11
- end
12
-
13
- desc "gem", "build the gemfile"
14
- def gem
15
- system("gem build pekky.gemspec")
16
- end
17
-
18
- desc "install", "build the gem and install it"
19
- def install
20
- gem
21
- f = Dir["pekky-*.gem"][0]
22
- system("gem install #{f}")
23
- end
24
- end
25
-
26
- class Spec < Thor
27
- desc "all", "runs all of the specs for Pekky"
28
- def all
29
- path = File.expand_path(File.dirname(__FILE__)) + '/'
30
- Dir["spec/*_spec.rb"].each do |s|
31
- require path + s
32
- end
33
- end
34
-
35
- desc "single SPEC_PREFIX", "runs the specified spec file"
36
- def single(prefix)
37
- require "spec/#{prefix}_spec"
38
- end
39
- end
@@ -1,60 +0,0 @@
1
- module Pekky
2
- module SiteConfig
3
- @config = {
4
- :content_dir => '/content',
5
- :view_dir => '/views',
6
- :layouts_dir => '/views/layouts',
7
- :partials_dir => '/views/partials',
8
- :public_dir => '/public',
9
- :output_dir => '/output',
10
- :javascripts_path => '/javascripts',
11
- :stylesheets_path => '/stylesheets',
12
- :images_path => '/images',
13
- :templating => 'haml',
14
- :css_processor => 'sass'
15
- }
16
-
17
- def self.set_root(p)
18
- @config[:root] = p
19
- @config.each do |k, v|
20
- if k.to_s.match(/_dir$/)
21
- self[k] = File.join(p, v)
22
- end
23
- end
24
- end
25
-
26
- @page_configs = []
27
-
28
- def self.page_configs
29
- @page_configs
30
- end
31
-
32
- def self.[](name)
33
- @config[name]
34
- end
35
-
36
- def self.[]=(name, val)
37
- @config[name] = val
38
- end
39
-
40
- def self.set(option, val)
41
- if option.to_s.match(/_dir$/)
42
- @config[option] = File.join(self[:root], val)
43
- else
44
- @config[option] = val
45
- end
46
- end
47
-
48
- def self.page(path, content, opts = {})
49
- @page_configs << PageConfig.new(path, content, opts)
50
- end
51
-
52
- def self.generate(path, &blk)
53
- @page_configs << GeneratorConfig.new(path, &blk)
54
- end
55
-
56
- def self.get(name, sort = nil)
57
- Context.get(name, sort)
58
- end
59
- end
60
- end