zzot-semi-static 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +63 -0
- data/VERSION.yml +2 -2
- data/lib/semi-static.rb +68 -1
- data/lib/semi-static/base.rb +3 -4
- data/lib/semi-static/convertable.rb +19 -6
- data/lib/semi-static/index.rb +19 -1
- data/lib/semi-static/layout.rb +9 -0
- data/lib/semi-static/post.rb +0 -21
- data/lib/semi-static/posts.rb +51 -3
- data/lib/semi-static/pygmentize.rb +11 -4
- data/lib/semi-static/site.rb +72 -7
- data/lib/semi-static/snippet.rb +7 -0
- data/lib/semi-static/statistics.rb +13 -0
- data/lib/semi-static/tags.rb +121 -0
- data/test/ref/test_layout/default_layout.html +43 -1
- data/test/ref/test_layout/post_layout.html +42 -0
- data/test/ref/test_page/about.html +42 -0
- data/test/ref/test_page/colophon.html +42 -0
- data/test/ref/test_post/impressions.html +48 -0
- data/test/ref/test_post/lighting-up.html +48 -0
- data/test/ref/test_post/the-working-mans-typeface.html +92 -45
- data/test/source/layouts/default.haml +4 -1
- data/test/source/layouts/post.erb +7 -3
- data/test/source/posts/2005-03-27-a-bash-script-to-mess-with-the-containing-terminalapp-window.markdown +2 -1
- data/test/source/posts/2008-11-24-lighting-up.markdown +0 -1
- data/test/source/posts/2008-11-26-impressions.md +0 -1
- data/test/source/posts/2008-12-04-the-working-mans-typeface.html +1 -1
- data/test/source/snippets/tags-widget.haml +6 -0
- data/test/test_layout.rb +2 -1
- data/test/test_post.rb +17 -14
- metadata +5 -4
- data/README.markdown +0 -84
- data/lib/semi-static/categories.rb +0 -74
@@ -1,11 +1,18 @@
|
|
1
1
|
module SemiStatic
|
2
2
|
module Pygmentize
|
3
|
+
##
|
4
|
+
# Format of a valid lexer name
|
3
5
|
LEXER_FORMAT = /^[a-z]+$/i
|
4
6
|
|
5
|
-
def pygmentize(code, lang)
|
7
|
+
def pygmentize(code, lang) #:nodoc:
|
6
8
|
Pygmentize.pygmentize code, lang
|
7
9
|
end
|
8
|
-
|
10
|
+
|
11
|
+
##
|
12
|
+
# Highlight the given code with the given lexer.
|
13
|
+
#
|
14
|
+
# +code+: The code to highlight.
|
15
|
+
# +lang+: The lexer to use.
|
9
16
|
def self.pygmentize(code, lang)
|
10
17
|
unless lang =~ LEXER_FORMAT
|
11
18
|
raise ArgumentError, "invalid lexer: #{lang}"
|
@@ -23,10 +30,10 @@ module SemiStatic
|
|
23
30
|
end
|
24
31
|
|
25
32
|
@@enabled = false
|
26
|
-
def self.enabled
|
33
|
+
def self.enabled #:nodoc:
|
27
34
|
@@enabled
|
28
35
|
end
|
29
|
-
def self.enabled=(value)
|
36
|
+
def self.enabled=(value) #:nodoc:
|
30
37
|
@@enabled = value
|
31
38
|
end
|
32
39
|
end
|
data/lib/semi-static/site.rb
CHANGED
@@ -1,14 +1,75 @@
|
|
1
1
|
module SemiStatic
|
2
2
|
class Site
|
3
|
-
|
3
|
+
##
|
4
|
+
# Clean the output directory before generating the site.
|
5
|
+
attr_accessor :clean_first
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
##
|
8
|
+
# Only generate a file if its source files are newer than its output file.
|
9
|
+
attr_accessor :check_mtime
|
10
|
+
|
11
|
+
##
|
12
|
+
# Only process a few posts, to speed up template editing.
|
13
|
+
attr_accessor :quick_mode
|
14
|
+
|
15
|
+
##
|
16
|
+
# Show conversion stats after outputting the site.
|
17
|
+
attr_accessor :show_statistics
|
18
|
+
|
19
|
+
##
|
20
|
+
# List of every Layout in the site.
|
21
|
+
attr_reader :layouts
|
22
|
+
|
23
|
+
##
|
24
|
+
# List of every Page in the site.
|
25
|
+
attr_reader :pages
|
26
|
+
|
27
|
+
##
|
28
|
+
# List of every Post in the site.
|
29
|
+
attr_reader :posts
|
30
|
+
|
31
|
+
##
|
32
|
+
# List of every Snippet in the site.
|
33
|
+
attr_reader :snippets
|
34
|
+
|
35
|
+
##
|
36
|
+
# List of every Stylesheet in the site.
|
37
|
+
attr_reader :stylesheets
|
9
38
|
|
39
|
+
##
|
40
|
+
# List of all Tags in the site.
|
41
|
+
attr_reader :tags
|
42
|
+
|
43
|
+
##
|
44
|
+
# Index used to generate the year indices in the output site.
|
45
|
+
attr_reader :year_index
|
46
|
+
|
47
|
+
##
|
48
|
+
# Index used to generate the month indices in the output site.
|
49
|
+
attr_reader :month_index
|
50
|
+
|
51
|
+
##
|
52
|
+
# Index used to generate the day indices in the output site.
|
53
|
+
attr_reader :day_index
|
54
|
+
|
55
|
+
##
|
56
|
+
# Site configuration.
|
57
|
+
attr_reader :metadata
|
58
|
+
|
59
|
+
##
|
60
|
+
# Statistics for the conversion process.
|
10
61
|
attr_reader :stats
|
11
62
|
|
63
|
+
##
|
64
|
+
# Site source directory.
|
65
|
+
attr_reader :source_dir
|
66
|
+
|
67
|
+
##
|
68
|
+
# Time the output was generated.
|
69
|
+
attr_reader :time
|
70
|
+
|
71
|
+
##
|
72
|
+
# Initializes a new Site with the given source directory.
|
12
73
|
def initialize(source_dir)
|
13
74
|
@clean_first = false
|
14
75
|
@first_pass = true
|
@@ -21,12 +82,17 @@ module SemiStatic
|
|
21
82
|
stats.record(:site, :load) { load }
|
22
83
|
end
|
23
84
|
|
85
|
+
##
|
86
|
+
# Creates a Site with the given source directory and yields it to the
|
87
|
+
# given block.
|
24
88
|
def self.open(source_dir)
|
25
89
|
raise ArugmentError, "block required" unless block_given?
|
26
90
|
site = SemiStatic::Site.new source_dir
|
27
91
|
yield site
|
28
92
|
end
|
29
93
|
|
94
|
+
##
|
95
|
+
# Write the Site to the given output directory.
|
30
96
|
def output(path)
|
31
97
|
if @first_pass
|
32
98
|
@first_pass = false
|
@@ -186,8 +252,7 @@ module SemiStatic
|
|
186
252
|
|
187
253
|
def load_posts
|
188
254
|
@posts = Posts.new(self)
|
189
|
-
@
|
190
|
-
@tags = Categories.new
|
255
|
+
@tags = Tags.new :tag
|
191
256
|
with_source_files('posts', '*.{html,haml,erb,txt,md,markdown}') do |path|
|
192
257
|
posts << path
|
193
258
|
end
|
data/lib/semi-static/snippet.rb
CHANGED
@@ -2,8 +2,15 @@ module SemiStatic
|
|
2
2
|
class Snippet < Base
|
3
3
|
include Convertable
|
4
4
|
|
5
|
+
##
|
6
|
+
# Snippet Name
|
5
7
|
attr_reader :name
|
6
8
|
|
9
|
+
##
|
10
|
+
# Initialize a new Snippet.
|
11
|
+
#
|
12
|
+
# +site+: The Site we belong to.
|
13
|
+
# +path+: Path to the source file.
|
7
14
|
def initialize(site, path)
|
8
15
|
super
|
9
16
|
@name = File.basename(source_path, source_ext)
|
@@ -1,13 +1,24 @@
|
|
1
1
|
module SemiStatic
|
2
|
+
##
|
3
|
+
# Used to track statistics while generating the Site.
|
2
4
|
class Statistics
|
5
|
+
##
|
6
|
+
# Initialize a new Statistics object.
|
3
7
|
def initialize
|
4
8
|
self.reset
|
5
9
|
end
|
6
10
|
|
11
|
+
##
|
12
|
+
# Clears all recorded data.
|
7
13
|
def reset
|
8
14
|
@data = Hash.new { |hash,key| hash[key] = Hash.new }
|
9
15
|
end
|
10
16
|
|
17
|
+
##
|
18
|
+
# Record the time it takes for the block to execute.
|
19
|
+
#
|
20
|
+
# +category+: The category of the action.
|
21
|
+
# +item+: The name of the action.
|
11
22
|
def record(category, item)
|
12
23
|
raise ArgumentError unless block_given?
|
13
24
|
before = Time.now
|
@@ -16,6 +27,8 @@ module SemiStatic
|
|
16
27
|
return result
|
17
28
|
end
|
18
29
|
|
30
|
+
##
|
31
|
+
# Display the collected data to the user.
|
19
32
|
def display
|
20
33
|
# details = {}
|
21
34
|
@data.each do |category,items|
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module SemiStatic
|
2
|
+
##
|
3
|
+
# A group of posts in the site that have the same tag in
|
4
|
+
# their metadata.
|
5
|
+
class Tag < Array
|
6
|
+
##
|
7
|
+
# Display name (i.e., Semi Static)
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
##
|
11
|
+
# URL-ified name (i.e., semi-static)
|
12
|
+
attr_reader :slug
|
13
|
+
|
14
|
+
##
|
15
|
+
# URI for the tag's index page.
|
16
|
+
attr_reader :uri
|
17
|
+
|
18
|
+
##
|
19
|
+
# Initializes a new Tag
|
20
|
+
def initialize(owner, name)
|
21
|
+
super()
|
22
|
+
@name = name
|
23
|
+
@slug = Tags.slugize name
|
24
|
+
@uri = "#{owner.uri}#{slug}/"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# A list of all tag in the site.
|
30
|
+
class Tags < Hash
|
31
|
+
##
|
32
|
+
# The URI for the collection's index page.
|
33
|
+
attr_reader :uri
|
34
|
+
|
35
|
+
##
|
36
|
+
# Convert the given display name to a URL-ified one.
|
37
|
+
def self.slugize(name)
|
38
|
+
name.to_s.gsub(/ /, '-').downcase.to_sym
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Initializes a new collection with the given name
|
43
|
+
def initialize(slug)
|
44
|
+
super()
|
45
|
+
@slug = slug
|
46
|
+
@uri = "/#{slug}/"
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Find the tag with the given name.
|
51
|
+
#
|
52
|
+
# +name+: The Tag's name (either its dipslay name or URL-ified name).
|
53
|
+
def [](name)
|
54
|
+
slug = Tags.slugize name
|
55
|
+
tag = super(slug)
|
56
|
+
if tag.nil?
|
57
|
+
tag = Tag.new self, name
|
58
|
+
self[slug] = tag
|
59
|
+
end
|
60
|
+
return tag
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# List all tag' URL-ified names, sorted alphabetically.
|
65
|
+
def slugs
|
66
|
+
keys.sort { |l,r| l.to_s <=> r.to_s }
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# List all tag' display names, sorted alphabetically.
|
71
|
+
def names
|
72
|
+
values.collect { |c| c.name }.sort { |l,r| l.to_s <=> r.to_s }
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Use each tag's name as a path, and arrange them into tree.
|
77
|
+
def nested_values
|
78
|
+
result = Hash.new { |hash,key| hash[key] = Hash.new }
|
79
|
+
values.each do |item|
|
80
|
+
parent, child = item.slug.to_s.split '/'
|
81
|
+
if child.nil?
|
82
|
+
result[parent.to_sym][nil] = item
|
83
|
+
else
|
84
|
+
result[parent.to_sym][child.to_sym] = item
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
result.collect do |parent_slug,items|
|
89
|
+
parent = items.delete(nil)
|
90
|
+
children = items.values.sort { |l,r| l.name.casecmp r.name }
|
91
|
+
|
92
|
+
class << parent
|
93
|
+
attr_accessor :slug, :children
|
94
|
+
end
|
95
|
+
parent.children = children
|
96
|
+
parent
|
97
|
+
end.sort { |l,r| l.name.casecmp r.name }
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Iterate over all tags
|
102
|
+
#
|
103
|
+
# +order+ can be:
|
104
|
+
# +:name+: Sorted alphabetically by display name
|
105
|
+
# +:count+: Sorted by post count, largest to smallest
|
106
|
+
# +:tree+: Sorted alphabetically bo display name and arranged into a tree
|
107
|
+
def each(options={}, &block)
|
108
|
+
list = case options[:order]
|
109
|
+
when :name, nil
|
110
|
+
values.sort { |l,r| l.name.casecmp r.name }
|
111
|
+
when :count
|
112
|
+
values.sort { |l,r| r.count <=> l.count }
|
113
|
+
when :tree
|
114
|
+
nested_values
|
115
|
+
else
|
116
|
+
raise ArgumentError, "Unknown order: #{options[:order]}"
|
117
|
+
end
|
118
|
+
list.each(&block)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -23,7 +23,49 @@
|
|
23
23
|
</li>
|
24
24
|
</ul>
|
25
25
|
</div>
|
26
|
-
<div id='body'
|
26
|
+
<div id='body'>
|
27
|
+
<div class='column' id='content'><p>Hello World!</p></div>
|
28
|
+
<div class='column' id='sidebar'>
|
29
|
+
<div class='widget' id='tags'>
|
30
|
+
<h3 class='header'>Tags</h3>
|
31
|
+
<ul class='content'>
|
32
|
+
<li>
|
33
|
+
<a href='/tag/applescript/'>AppleScript (1)</a>
|
34
|
+
</li>
|
35
|
+
<li>
|
36
|
+
<a href='/tag/auto-show/'>Auto Show (1)</a>
|
37
|
+
</li>
|
38
|
+
<li>
|
39
|
+
<a href='/tag/catching-up/'>Catching Up (2)</a>
|
40
|
+
</li>
|
41
|
+
<li>
|
42
|
+
<a href='/tag/colbert-report/'>Colbert Report (1)</a>
|
43
|
+
</li>
|
44
|
+
<li>
|
45
|
+
<a href='/tag/comedy-central/'>Comedy Central (1)</a>
|
46
|
+
</li>
|
47
|
+
<li>
|
48
|
+
<a href='/tag/iphone/'>iPhone (1)</a>
|
49
|
+
</li>
|
50
|
+
<li>
|
51
|
+
<a href='/tag/raves/'>Raves (1)</a>
|
52
|
+
</li>
|
53
|
+
<li>
|
54
|
+
<a href='/tag/rss/'>RSS (2)</a>
|
55
|
+
</li>
|
56
|
+
<li>
|
57
|
+
<a href='/tag/travel/'>Travel (1)</a>
|
58
|
+
</li>
|
59
|
+
<li>
|
60
|
+
<a href='/tag/typography/'>Typography (1)</a>
|
61
|
+
</li>
|
62
|
+
<li>
|
63
|
+
<a href='/tag/work/'>Work (1)</a>
|
64
|
+
</li>
|
65
|
+
</ul>
|
66
|
+
</div>
|
67
|
+
</div>
|
68
|
+
</div>
|
27
69
|
<div id='footer'>
|
28
70
|
<p>
|
29
71
|
Copyright © 2003–2009 Josh Dady.
|
@@ -24,6 +24,7 @@
|
|
24
24
|
</ul>
|
25
25
|
</div>
|
26
26
|
<div id='body'>
|
27
|
+
<div class='column' id='content'>
|
27
28
|
<div class='test_layout_post' id='test_layout_post_314159'>
|
28
29
|
<div class='post-header'>
|
29
30
|
<h2 class='post-title'>
|
@@ -73,6 +74,47 @@
|
|
73
74
|
})();
|
74
75
|
//]]>
|
75
76
|
</script>
|
77
|
+
</div>
|
78
|
+
<div class='column' id='sidebar'>
|
79
|
+
<div class='widget' id='tags'>
|
80
|
+
<h3 class='header'>Tags</h3>
|
81
|
+
<ul class='content'>
|
82
|
+
<li>
|
83
|
+
<a href='/tag/applescript/'>AppleScript (1)</a>
|
84
|
+
</li>
|
85
|
+
<li>
|
86
|
+
<a href='/tag/auto-show/'>Auto Show (1)</a>
|
87
|
+
</li>
|
88
|
+
<li>
|
89
|
+
<a href='/tag/catching-up/'>Catching Up (2)</a>
|
90
|
+
</li>
|
91
|
+
<li>
|
92
|
+
<a href='/tag/colbert-report/'>Colbert Report (1)</a>
|
93
|
+
</li>
|
94
|
+
<li>
|
95
|
+
<a href='/tag/comedy-central/'>Comedy Central (1)</a>
|
96
|
+
</li>
|
97
|
+
<li>
|
98
|
+
<a href='/tag/iphone/'>iPhone (1)</a>
|
99
|
+
</li>
|
100
|
+
<li>
|
101
|
+
<a href='/tag/raves/'>Raves (1)</a>
|
102
|
+
</li>
|
103
|
+
<li>
|
104
|
+
<a href='/tag/rss/'>RSS (2)</a>
|
105
|
+
</li>
|
106
|
+
<li>
|
107
|
+
<a href='/tag/travel/'>Travel (1)</a>
|
108
|
+
</li>
|
109
|
+
<li>
|
110
|
+
<a href='/tag/typography/'>Typography (1)</a>
|
111
|
+
</li>
|
112
|
+
<li>
|
113
|
+
<a href='/tag/work/'>Work (1)</a>
|
114
|
+
</li>
|
115
|
+
</ul>
|
116
|
+
</div>
|
117
|
+
</div>
|
76
118
|
</div>
|
77
119
|
<div id='footer'>
|
78
120
|
<p>
|
@@ -24,6 +24,7 @@
|
|
24
24
|
</ul>
|
25
25
|
</div>
|
26
26
|
<div id='body'>
|
27
|
+
<div class='column' id='content'>
|
27
28
|
<h1 id='about_this_site'>About this site</h1>
|
28
29
|
|
29
30
|
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio.</p>
|
@@ -35,6 +36,47 @@
|
|
35
36
|
<p>Quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim.</p>
|
36
37
|
|
37
38
|
<p>Suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait.</p>
|
39
|
+
</div>
|
40
|
+
<div class='column' id='sidebar'>
|
41
|
+
<div class='widget' id='tags'>
|
42
|
+
<h3 class='header'>Tags</h3>
|
43
|
+
<ul class='content'>
|
44
|
+
<li>
|
45
|
+
<a href='/tag/applescript/'>AppleScript (1)</a>
|
46
|
+
</li>
|
47
|
+
<li>
|
48
|
+
<a href='/tag/auto-show/'>Auto Show (1)</a>
|
49
|
+
</li>
|
50
|
+
<li>
|
51
|
+
<a href='/tag/catching-up/'>Catching Up (2)</a>
|
52
|
+
</li>
|
53
|
+
<li>
|
54
|
+
<a href='/tag/colbert-report/'>Colbert Report (1)</a>
|
55
|
+
</li>
|
56
|
+
<li>
|
57
|
+
<a href='/tag/comedy-central/'>Comedy Central (1)</a>
|
58
|
+
</li>
|
59
|
+
<li>
|
60
|
+
<a href='/tag/iphone/'>iPhone (1)</a>
|
61
|
+
</li>
|
62
|
+
<li>
|
63
|
+
<a href='/tag/raves/'>Raves (1)</a>
|
64
|
+
</li>
|
65
|
+
<li>
|
66
|
+
<a href='/tag/rss/'>RSS (2)</a>
|
67
|
+
</li>
|
68
|
+
<li>
|
69
|
+
<a href='/tag/travel/'>Travel (1)</a>
|
70
|
+
</li>
|
71
|
+
<li>
|
72
|
+
<a href='/tag/typography/'>Typography (1)</a>
|
73
|
+
</li>
|
74
|
+
<li>
|
75
|
+
<a href='/tag/work/'>Work (1)</a>
|
76
|
+
</li>
|
77
|
+
</ul>
|
78
|
+
</div>
|
79
|
+
</div>
|
38
80
|
</div>
|
39
81
|
<div id='footer'>
|
40
82
|
<p>
|