zzot-semi-static 0.0.2 → 0.0.3

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.
@@ -0,0 +1,63 @@
1
+ = Semi Static
2
+
3
+ Semi Static is yet another static site generator. I've been playing around
4
+ with similar systems off and on for years, but it's
5
+ Jekyll[http://github.com/mojombo/jekyll] that finally convinced me to build
6
+ (and finish) one for myself. The main idea that I take from Jekyll is using
7
+ Git[http://git-scm.com/] as the database. The idea from Jekyll that I'm not
8
+ adopting is avoiding Ruby[http://ruby-lang.org/] code evaluation at all
9
+ costs -- I'm not letting other people feed documents into it (as
10
+ GitHub[http://github.com/] Pages[http://pages.github.com] does), so I don't
11
+ need to protect myself from them.
12
+
13
+ At some point Semi Static had a sister project, Semi Live, that would generate
14
+ the site dynamically (probably via Rails[http://rubyonrails.org/]). I stopped
15
+ working on it not long after I first started, so don't expect to see it on my
16
+ projects[http://github.com/zzot] page.
17
+
18
+ == Features
19
+
20
+ * Layouts can be Haml[http://haml.hamptoncatlin.com/] or
21
+ ERB[http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/] -- but not
22
+ Liquid[http://www.liquidmarkup.org/].
23
+ * Stylesheets can be Sass[http://haml.hamptoncatlin.com/] or raw CSS.
24
+ * Pages and posts can be Maruku[http://maruku.rubyforge.org/] or raw HTML.
25
+ * Code highlighting by Pygments[http://pygments.org/].
26
+
27
+ == Installation
28
+
29
+ The easiest way to install Semi-Static is via RubyGems[http://www.rubygems.org/]:
30
+
31
+ $ sudo gem install zzot-semi-static -s http://gems.github.com/
32
+
33
+ Semi-Static requires the `Haml` and `Maruku` gems and the `Pygments`
34
+ library to be installed.
35
+
36
+ == Usage
37
+
38
+ $ semi source-path [output-path]
39
+
40
+ == License
41
+
42
+ (The MIT License)
43
+
44
+ Copyright (c) 2009 Josh Dady
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining
47
+ a copy of this software and associated documentation files (the
48
+ 'Software'), to deal in the Software without restriction, including
49
+ without limitation the rights to use, copy, modify, merge, publish,
50
+ distribute, sublicense, and/or sell copies of the Software, and to
51
+ permit persons to whom the Software is furnished to do so, subject to
52
+ the following conditions:
53
+
54
+ The above copyright notice and this permission notice shall be
55
+ included in all copies or substantial portions of the Software.
56
+
57
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
58
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
59
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
60
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
61
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
62
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
63
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 0
3
- :patch: 2
4
2
  :major: 0
3
+ :minor: 0
4
+ :patch: 3
@@ -1,6 +1,7 @@
1
1
  # Core requirements
2
2
  require 'erb'
3
3
  require 'tempfile'
4
+ require 'time'
4
5
  require 'yaml'
5
6
 
6
7
  # Gem requirements
@@ -25,6 +26,72 @@ require 'semi-static/post'
25
26
  require 'semi-static/snippet'
26
27
  require 'semi-static/posts'
27
28
  require 'semi-static/index'
28
- require 'semi-static/categories'
29
+ require 'semi-static/tags'
29
30
  require 'semi-static/statistics'
30
31
  require 'semi-static/site'
32
+
33
+ ##
34
+ # Semi Static is yet another static site generator. I've been playing around
35
+ # with similar systems off and on for years, but it's
36
+ # Jekyll[http://github.com/mojombo/jekyll] that finally convinced me to build
37
+ # (and finish) one for myself. The main idea that I take from Jekyll is using
38
+ # Git[http://git-scm.com/] as the database. The idea from Jekyll that I'm not
39
+ # adopting is avoiding Ruby[http://ruby-lang.org/] code evaluation at all
40
+ # costs -- I'm not letting other people feed documents into it (as
41
+ # GitHub[http://github.com/] Pages[http://pages.github.com] does), so I don't
42
+ # need to protect myself from them.
43
+ #
44
+ # At some point Semi Static had a sister project, Semi Live, that would generate
45
+ # the site dynamically (probably via Rails[http://rubyonrails.org/]). I stopped
46
+ # working on it not long after I first started, so don't expect to see it on my
47
+ # projects[http://github.com/zzot] page.
48
+ #
49
+ # == Features
50
+ #
51
+ # * Layouts can be Haml[http://haml.hamptoncatlin.com/] or
52
+ # ERB[http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/] -- but not
53
+ # Liquid[http://www.liquidmarkup.org/].
54
+ # * Stylesheets can be Sass[http://haml.hamptoncatlin.com/] or raw CSS.
55
+ # * Pages and posts can be Maruku[http://maruku.rubyforge.org/] or raw HTML.
56
+ # * Code highlighting by Pygments[http://pygments.org/].
57
+ #
58
+ # == Installation
59
+ #
60
+ # The easiest way to install Semi-Static is via RubyGems[http://www.rubygems.org/]:
61
+ #
62
+ # $ sudo gem install zzot-semi-static -s http://gems.github.com/
63
+ #
64
+ # Semi-Static requires the `Haml` and `Maruku` gems and the `Pygments`
65
+ # library to be installed.
66
+ #
67
+ # == Usage
68
+ #
69
+ # $ semi source-path [output-path]
70
+ #
71
+ # == License
72
+ #
73
+ # (The MIT License)
74
+ #
75
+ # Copyright (c) 2009 Josh Dady
76
+ #
77
+ # Permission is hereby granted, free of charge, to any person obtaining
78
+ # a copy of this software and associated documentation files (the
79
+ # 'Software'), to deal in the Software without restriction, including
80
+ # without limitation the rights to use, copy, modify, merge, publish,
81
+ # distribute, sublicense, and/or sell copies of the Software, and to
82
+ # permit persons to whom the Software is furnished to do so, subject to
83
+ # the following conditions:
84
+ #
85
+ # The above copyright notice and this permission notice shall be
86
+ # included in all copies or substantial portions of the Software.
87
+ #
88
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
89
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
90
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
91
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
92
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
93
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
94
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
95
+
96
+ module SemiStatic
97
+ end
@@ -1,8 +1,7 @@
1
1
  module SemiStatic
2
- # Base represents a single source file and its associated metadata.
3
- # Base loads the source file, and strips and parses any metadata set
4
- # in the file's header. It stores an absolute path to the file so we
5
- # can refer to it later.
2
+ # Base is a single source file and its associated metadata. Base loads
3
+ # itself from the source file and strips off and parses the metadata in
4
+ # the file's header.
6
5
  class Base
7
6
  ##
8
7
  # The associated Site object
@@ -1,8 +1,10 @@
1
1
  module SemiStatic
2
+ ##
3
+ # Support conversion of the source file into another format.
2
4
  module Convertable
3
5
  include ERB::Util
4
6
 
5
- def load
7
+ def load #:nodoc:
6
8
  @content = nil
7
9
  if layout
8
10
  layout.load
@@ -10,6 +12,8 @@ module SemiStatic
10
12
  super
11
13
  end
12
14
 
15
+ ##
16
+ # Format the source file.
13
17
  def content(options={})
14
18
  return @content unless @content.nil?
15
19
 
@@ -25,7 +29,9 @@ module SemiStatic
25
29
  when '.haml'
26
30
  Haml::Engine.new(self.source_content, :filename => source_path).render(binding)
27
31
  when '.erb'
28
- ERB.new(self.source_content, nil, '-').result(binding)
32
+ erb = ERB.new self.source_content, nil, '-'
33
+ erb.filename = source_path
34
+ erb.result(binding)
29
35
  when '.html'
30
36
  self.source_content
31
37
  else
@@ -34,13 +40,13 @@ module SemiStatic
34
40
  end
35
41
  end
36
42
 
37
- def layout_name
43
+ def layout_name #:nodoc:
38
44
  unless source_metadata.nil? || !source_metadata.include?(:layout)
39
45
  source_metadata[:layout].to_sym
40
46
  end
41
47
  end
42
48
 
43
- def layout
49
+ def layout #:nodoc:
44
50
  if layout_name.nil?
45
51
  return nil
46
52
  else
@@ -48,6 +54,9 @@ module SemiStatic
48
54
  end
49
55
  end
50
56
 
57
+ ##
58
+ # Add the layout used (if any) to the list of files used to determine
59
+ # the objects modification time.
51
60
  def source_mtime
52
61
  mtime = super
53
62
  if layout && layout.source_mtime > mtime
@@ -56,6 +65,8 @@ module SemiStatic
56
65
  return mtime
57
66
  end
58
67
 
68
+ ##
69
+ # Wrap the formatted source file in the Layout (if any).
59
70
  def render(options={})
60
71
  content = self.content(options)
61
72
  if layout
@@ -65,6 +76,8 @@ module SemiStatic
65
76
  return content
66
77
  end
67
78
 
79
+ ##
80
+ # Helper method used to insert a Snippet into the formatted output.
68
81
  def snippet(name)
69
82
  name = name.to_s
70
83
  site.snippets[name].render :page => self
@@ -73,7 +86,7 @@ module SemiStatic
73
86
  # This method is adapted from Haml::Buffer#parse_object_ref -- it's
74
87
  # used to make it easier for Haml and ERB layouts to generate the
75
88
  # same output so I can use the same test output for both.
76
- def object_ref(object)
89
+ def object_ref(object) #:nodoc:
77
90
  return '' if object.nil?
78
91
  name = underscore(object.class)
79
92
  id = "#{name}_#{object.id || 'new'}"
@@ -83,7 +96,7 @@ module SemiStatic
83
96
  # Changes a word from camel case to underscores. Based on the method
84
97
  # of the same name in Rails' Inflector, but copied here so it'll run
85
98
  # properly without Rails.
86
- def underscore(camel_cased_word)
99
+ def underscore(camel_cased_word) #:nodoc:
87
100
  camel_cased_word.to_s.gsub(/::/, '_').
88
101
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
89
102
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
@@ -1,9 +1,27 @@
1
1
  module SemiStatic
2
+ ##
3
+ # Index is used to generate several site index pages that don't have a
4
+ # fixed path (i.e., the yearly index pages) from a single source file.
5
+ # It can have a Layout and use any number of Snippets. Index's modification
6
+ # time is the most recent of itself, its layout, and any Snippets used.
7
+ # Indices are also considered out-of-date if any posts in the index's range
8
+ # are changed.
2
9
  class Index < Base
3
10
  include Convertable
4
11
 
5
- attr_accessor :posts, :context
12
+ ##
13
+ # Posts in range for the Index's current path.
14
+ attr_accessor :posts
6
15
 
16
+ ##
17
+ # The Index's current context (usually a Date).
18
+ attr_accessor :context
19
+
20
+ ##
21
+ # Initializes a new Index
22
+ #
23
+ # +site+:: The Site object we belong to
24
+ # +path+:: The relative path to the source file
7
25
  def initialize(site, path)
8
26
  super
9
27
  @metadata = [ :layout ]
@@ -1,9 +1,18 @@
1
1
  module SemiStatic
2
+ ##
3
+ # Layout embeds the formatted output of a Convertable within a large document.
2
4
  class Layout < Base
3
5
  include Convertable
4
6
 
7
+ ##
8
+ # The Layout's name
5
9
  attr_reader :name
6
10
 
11
+ ##
12
+ # Initialize a new Layout
13
+ #
14
+ # +site+: The Site we belong to.
15
+ # +path+: The path to the source file.
7
16
  def initialize(site, path)
8
17
  super
9
18
  @metadata = [ :layout ]
@@ -10,10 +10,6 @@ module SemiStatic
10
10
  # The Post's name
11
11
  attr_reader :name
12
12
 
13
- ##
14
- # The Post's Category
15
- attr_reader :category
16
-
17
13
  ##
18
14
  # The Post's Tags
19
15
  attr_reader :tags
@@ -57,9 +53,6 @@ module SemiStatic
57
53
 
58
54
  @name = File.basename(source_path, source_ext)
59
55
 
60
- @category = site.categories[source_metadata[:category]]
61
- @category << self
62
-
63
56
  @tags = []
64
57
  unless source_metadata[:tags].nil?
65
58
  for tag in source_metadata[:tags]
@@ -92,20 +85,6 @@ module SemiStatic
92
85
  return "#{uri}"
93
86
  end
94
87
 
95
- # def comments_link
96
- # "#{uri}#comments"
97
- # end
98
- #
99
- # def comment_count
100
- # 0
101
- # end
102
-
103
- ##
104
- # Formatted date the Post was published (i.e., "March 15, 2009")
105
- def date
106
- created.strftime '%B %e, %Y'
107
- end
108
-
109
88
  ##
110
89
  # Year the Post was published as a String (i.e., "2009")
111
90
  def year
@@ -1,7 +1,27 @@
1
1
  module SemiStatic
2
+ ##
3
+ # Collection of Posts for the current site.
2
4
  class Posts
3
- attr_reader :site, :posts, :names, :indices
5
+ ##
6
+ # The Site object we belong to.
7
+ attr_reader :site
4
8
 
9
+ ##
10
+ # The raw list of posts.
11
+ attr_reader :posts
12
+
13
+ ##
14
+ # Posts indexed by name.
15
+ attr_reader :names
16
+
17
+ ##
18
+ # Indices that correspond to the Posts.
19
+ attr_reader :indices
20
+
21
+ ##
22
+ # Initializes a new Posts
23
+ #
24
+ # +site+: The Site we belong to.
5
25
  def initialize(site)
6
26
  @site = site
7
27
  @posts = []
@@ -9,8 +29,14 @@ module SemiStatic
9
29
  @indices = Set.new
10
30
  end
11
31
 
32
+ ##
33
+ # The format of the Date portion of a post's filename.
12
34
  NAME_RE = /^([0-9]{4})-([0-9]{2})-([0-9]{2})-(.*)/
13
35
 
36
+ ##
37
+ # Parse the given file as a Post and add it to the list.
38
+ #
39
+ # +source_path+: Path to the source file
14
40
  def <<(source_path)
15
41
  unless File.file?(source_path)
16
42
  $stderr.puts "[#{source_path}]"
@@ -28,6 +54,10 @@ module SemiStatic
28
54
  end
29
55
  end
30
56
 
57
+ ##
58
+ # Truncate the list of Posts to the given number (to speed up testing).
59
+ #
60
+ # +count+: The number of posts to keep.
31
61
  def chop!(count)
32
62
  raise ArgumentError unless count > 0
33
63
  posts = self.posts.first(count)
@@ -43,10 +73,16 @@ module SemiStatic
43
73
  end
44
74
  end
45
75
 
76
+ ##
77
+ # Number of posts.
46
78
  def length
47
79
  self.posts.length
48
80
  end
49
81
 
82
+ ##
83
+ # Fetch the least recent posts.
84
+ #
85
+ # +n+: Number of Posts to return.
50
86
  def first(n=nil)
51
87
  if n.nil?
52
88
  self.posts.first
@@ -55,6 +91,10 @@ module SemiStatic
55
91
  end
56
92
  end
57
93
 
94
+ ##
95
+ # Fetch the most recent posts.
96
+ #
97
+ # +n+: Number of Posts to return.
58
98
  def last(n=nil)
59
99
  if n.nil?
60
100
  self.posts.last
@@ -63,6 +103,8 @@ module SemiStatic
63
103
  end
64
104
  end
65
105
 
106
+ ##
107
+ # Fetch the Posts for the given Date range.
66
108
  def from(year, month=nil, day=nil)
67
109
  if year.is_a?(String) && month.nil? && day.nil?
68
110
  date = year.split('/', 3)
@@ -95,15 +137,21 @@ module SemiStatic
95
137
  return result
96
138
  end
97
139
 
140
+ ##
141
+ # Get the post with the given name.
98
142
  def [](name)
99
143
  return self.names[name]
100
144
  end
101
145
 
102
- def each(&block)
146
+ ##
147
+ # Iterate over all posts.
148
+ def each(&block) # :yields: Post
103
149
  self.posts.each(&block)
104
150
  end
105
151
 
106
- def each_index(&block)
152
+ ##
153
+ # Iterate over all indices.
154
+ def each_index(&block) # :yields: String
107
155
  indices.each(&block)
108
156
  end
109
157
  end