nanoc-toolbox 0.0.7 → 0.1.0
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/CHANGELOG.md +13 -2
- data/Gemfile +3 -0
- data/Gemfile.lock +36 -13
- data/Guardfile +9 -0
- data/README.md +22 -5
- data/lib/nanoc/toolbox/filters/add_sections.rb +2 -2
- data/lib/nanoc/toolbox/filters/html_tidy.rb +5 -5
- data/lib/nanoc/toolbox/filters/js_minify.rb +2 -2
- data/lib/nanoc/toolbox/filters.rb +2 -1
- data/lib/nanoc/toolbox/helpers/blogging_extra.rb +105 -0
- data/lib/nanoc/toolbox/helpers/disqus.rb +47 -0
- data/lib/nanoc/toolbox/helpers/google_analytics.rb +7 -5
- data/lib/nanoc/toolbox/helpers/gravatar.rb +2 -2
- data/lib/nanoc/toolbox/helpers/html_tag.rb +13 -8
- data/lib/nanoc/toolbox/helpers/navigation.rb +61 -67
- data/lib/nanoc/toolbox/helpers/tagging_extra.rb +135 -0
- data/lib/nanoc/toolbox/helpers.rb +4 -1
- data/lib/nanoc/toolbox/version.rb +2 -2
- data/nanoc-toolbox.gemspec +15 -14
- data/spec/filters/add_sections_spec.rb +7 -29
- data/spec/filters/js_minify_spec.rb +14 -0
- data/spec/helpers/blogging_extra_spec.rb +134 -0
- data/spec/helpers/disqus_spec.rb +47 -0
- data/spec/helpers/google_analytics_spec.rb +27 -7
- data/spec/helpers/gravatar_spec.rb +25 -25
- data/spec/helpers/html_tag_spec.rb +8 -1
- data/spec/helpers/navigation_spec.rb +110 -49
- data/spec/helpers/tagging_extra_spec.rb +155 -0
- data/spec/spec_helper.rb +5 -1
- metadata +109 -119
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'nanoc/toolbox/helpers/html_tag'
|
2
2
|
|
3
|
-
module Nanoc::Toolbox::Helpers
|
3
|
+
module Nanoc::Toolbox::Helpers
|
4
4
|
# NANOC Helper for the Navigation related stuff.
|
5
5
|
#
|
6
6
|
# This module contains functions for generating navigation menus for your
|
@@ -8,7 +8,7 @@ module Nanoc::Toolbox::Helpers
|
|
8
8
|
#
|
9
9
|
# @author Anouar ADLANI <anouar@adlani.com>
|
10
10
|
module Navigation
|
11
|
-
include
|
11
|
+
include Nanoc::Helpers::LinkTo
|
12
12
|
include Nanoc::Toolbox::Helpers::HtmlTag
|
13
13
|
|
14
14
|
# Generate a navigation menu for a given item.
|
@@ -34,39 +34,38 @@ module Nanoc::Toolbox::Helpers
|
|
34
34
|
render_menu(sections, options)
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
37
|
# Generate a Table of Content for a given item. The toc will be generated
|
39
38
|
# form the item content. The parsing is done with Nokogiri through XPath.
|
40
39
|
#
|
41
|
-
# @param [
|
40
|
+
# @param [Nanoc::ItemRep] item_rep - the representation of desired item
|
42
41
|
# @param [Hash] options - The Optional parameters
|
43
42
|
# @option options (see #render_menu)
|
44
43
|
# @option options [String] :path ('div[@class="section"]') Generic XPath for the sections
|
45
|
-
#
|
44
|
+
#
|
46
45
|
# @return [String] The output ready to be displayed by the caller
|
47
46
|
#
|
48
47
|
# @see http://nokogiri.org/
|
49
48
|
def toc_for(item_rep, options={})
|
50
49
|
require 'nokogiri'
|
50
|
+
item_rep = item_rep.rep_named(:default) if item_rep.is_a? Nanoc::Item
|
51
51
|
|
52
|
-
# Parse options or set to default values
|
53
52
|
options[:path] ||= 'div[@class="section"]'
|
54
53
|
|
55
54
|
# Retreive the parsed content and init nokogiri
|
56
55
|
compiled_content = item_rep.instance_eval { @content[:pre] }
|
57
56
|
doc = Nokogiri::HTML(compiled_content)
|
58
57
|
doc_root = doc.xpath('/html/body').first
|
58
|
+
return "" if doc_root.nil?
|
59
59
|
|
60
60
|
# Find all sections, and render them
|
61
61
|
sections = find_toc_sections(doc_root, options[:path])
|
62
|
-
render_menu(sections, options)
|
62
|
+
render_menu(sections, options) || ""
|
63
63
|
end
|
64
64
|
|
65
|
-
|
66
65
|
# Generate a Breadcrumb for a given item. The breadcrumbs, is starting with
|
67
66
|
# the root item and ending with the item itself.
|
68
67
|
#
|
69
|
-
# Requires the Helper:
|
68
|
+
# Requires the Helper: Nanoc::Helpers::Breadcrumbs
|
70
69
|
#
|
71
70
|
# @param [String] identifier - the identifier string of element
|
72
71
|
# @param [Hash] options - The Optional parameters
|
@@ -74,12 +73,11 @@ module Nanoc::Toolbox::Helpers
|
|
74
73
|
#
|
75
74
|
# @return [String] The output ready to be displayed by the caller
|
76
75
|
#
|
77
|
-
# @see
|
76
|
+
# @see Nanoc::Helpers::Breadcrumbs#breadcrumbs_for_identifier
|
78
77
|
def breadcrumb_for(identifier, options={})
|
79
|
-
|
80
|
-
# Parse options or set to default values
|
81
78
|
options[:collection_tag] ||= 'ul'
|
82
|
-
|
79
|
+
options[:collection_class] ||= 'breadcrumb'
|
80
|
+
|
83
81
|
# Retreive the breadcrumbs trail and format them
|
84
82
|
sections = find_breadcrumbs_trail(identifier)
|
85
83
|
render_menu(sections, options)
|
@@ -118,24 +116,22 @@ module Nanoc::Toolbox::Helpers
|
|
118
116
|
#
|
119
117
|
# @return [String] The output ready to be displayed by the caller
|
120
118
|
def render_menu(items, options={})
|
121
|
-
|
122
|
-
# Parse options or set to default values
|
123
119
|
options[:depth] ||= 3
|
124
120
|
options[:collection_tag] ||= 'ol'
|
121
|
+
options[:collection_class] ||= 'menu'
|
125
122
|
options[:item_tag] ||= 'li'
|
126
123
|
options[:title_tag] ||= 'h2'
|
127
124
|
options[:title] ||= nil
|
128
|
-
|
125
|
+
|
129
126
|
# Parse the title and remove it from the options
|
130
127
|
title = options[:title] ? content_tag(options[:title_tag], options[:title]) : ''
|
131
|
-
options.delete(:title_tag)
|
132
|
-
options.delete(:title)
|
133
|
-
|
128
|
+
options.delete(:title_tag)
|
129
|
+
options.delete(:title)
|
130
|
+
|
134
131
|
# Decrease the depth level
|
135
132
|
options[:depth] -= 1
|
136
133
|
|
137
134
|
rendered_menu = items.map do |item|
|
138
|
-
|
139
135
|
# Render only if there is depth left
|
140
136
|
if options[:depth].to_i > 0 && item[:subsections]
|
141
137
|
output = render_menu(item[:subsections], options)
|
@@ -146,60 +142,58 @@ module Nanoc::Toolbox::Helpers
|
|
146
142
|
|
147
143
|
end.join()
|
148
144
|
|
149
|
-
|
150
|
-
title + content_tag(options[:collection_tag], rendered_menu) unless rendered_menu.strip.empty?
|
145
|
+
title + content_tag(options[:collection_tag], rendered_menu, :class => options[:collection_class]) unless rendered_menu.strip.empty?
|
151
146
|
end
|
152
147
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
173
|
-
{ :title => sub_title, :link => '#' + sub_id, :subsections => subsections }
|
148
|
+
private
|
149
|
+
|
150
|
+
# Recursive method that extract from an XPath pattern the document structure
|
151
|
+
# and return the "permalinks" to each sections in an Array of Hash that
|
152
|
+
# could be used by the rendering method. The structure is deducted by the
|
153
|
+
# H1-6 header within the html element defined by the XPATH
|
154
|
+
def find_toc_sections(section, section_xpath, title_level=1)
|
155
|
+
return {} unless section.xpath(section_xpath)
|
156
|
+
|
157
|
+
# For each section found call the find_toc_sections on it with an
|
158
|
+
# increased header level (ex: h1 => h2) and then generate the hash res
|
159
|
+
sections = section.xpath(section_xpath).map do |subsection|
|
160
|
+
header = subsection.css("h1, h2, h3, h4, h5, h6").first
|
161
|
+
sub_id = subsection['id']
|
162
|
+
sub_title = header ? header.inner_html : 'untitled'
|
163
|
+
subsections = {}
|
164
|
+
|
165
|
+
if subsection.xpath("#{section_xpath}") && title_level <= 6
|
166
|
+
subsections = find_toc_sections(subsection, "#{section_xpath}", title_level+1)
|
174
167
|
end
|
168
|
+
{ :title => sub_title, :link => '#' + sub_id, :subsections => subsections }
|
175
169
|
end
|
170
|
+
end
|
176
171
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
# filter the elements to contain only the kind requested
|
184
|
-
children = options[:kind] ? root.children.select { |item| item[:kind] == options[:kind] } : root.children
|
185
|
-
|
186
|
-
# For each child call the find_item_tree on it and then generate the hash
|
187
|
-
sections = children.map do |child|
|
188
|
-
subsections = find_item_tree(child)
|
189
|
-
|
190
|
-
{ :title => (child[:title] || child.identifier),
|
191
|
-
:link => relative_path_to(child),
|
192
|
-
:subsections => subsections }
|
193
|
-
end
|
194
|
-
end
|
172
|
+
# Recursive method that extract from an XPath pattern the document structure
|
173
|
+
# and return the "permalinks" in a Array of Hash that could be used by the
|
174
|
+
# rendering method
|
175
|
+
def find_item_tree(root, options={})
|
176
|
+
return nil unless root.children
|
195
177
|
|
178
|
+
# filter the elements to contain only the kind requested
|
179
|
+
children = options[:kind] ? root.children.select { |item| item[:kind] == options[:kind] } : root.children
|
196
180
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
181
|
+
# For each child call the find_item_tree on it and then generate the hash
|
182
|
+
sections = children.map do |child|
|
183
|
+
subsections = find_item_tree(child)
|
184
|
+
|
185
|
+
{ :title => (child[:title] || child.identifier),
|
186
|
+
:link => relative_path_to(child),
|
187
|
+
:subsections => subsections }
|
203
188
|
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def find_breadcrumbs_trail(root)
|
192
|
+
sections = breadcrumbs_for_identifier(root).map do |child|
|
193
|
+
{ :title => (child[:short_title] || child[:title] || child.identifier),
|
194
|
+
:link => relative_path_to(child),
|
195
|
+
:subsections => nil }
|
196
|
+
end
|
197
|
+
end
|
204
198
|
end
|
205
199
|
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Nanoc::Toolbox::Helpers
|
2
|
+
|
3
|
+
# NANOC Helper for added tagging functions
|
4
|
+
#
|
5
|
+
# This module contains functions for ...
|
6
|
+
#
|
7
|
+
# @see http://groups.google.com/group/nanoc/browse_thread/thread/caefcab791fd3c4b
|
8
|
+
module TaggingExtra
|
9
|
+
include Nanoc::Helpers::Blogging
|
10
|
+
|
11
|
+
# Returns all the tags present in a collection of items. The tags are
|
12
|
+
# only present once in the returned value. When called whithout
|
13
|
+
# parameters, all the site items are considered.
|
14
|
+
#
|
15
|
+
# @param [Array<Nanoc::Item>] items
|
16
|
+
# @return [Array<String>] An array of tags
|
17
|
+
def tag_set(items=nil)
|
18
|
+
items ||= @items
|
19
|
+
items.map { |i| i[:tags] }.flatten.uniq.delete_if{|t| t.nil?}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return true if an item has a specified tag
|
23
|
+
#
|
24
|
+
# @param [Nanoc::Item] item
|
25
|
+
# @param [String] tag
|
26
|
+
# @return [Boolean] true if the item contains the specified tag
|
27
|
+
def has_tag?(item, tag)
|
28
|
+
return false if item[:tags].nil?
|
29
|
+
item[:tags].include? tag
|
30
|
+
end
|
31
|
+
|
32
|
+
# Finds all the items having a specified tag. By default the method search
|
33
|
+
# in all the site items. Alternatively, an item collection can be passed as
|
34
|
+
# second (optional) parameter, to restrict the search in the collection.
|
35
|
+
#
|
36
|
+
# @param [Array<Nanoc::Item>] items
|
37
|
+
# @param [String] tag
|
38
|
+
# @param [Nanoc::Item] item
|
39
|
+
def items_with_tag(tag, items=nil)
|
40
|
+
items = sorted_articles if items.nil?
|
41
|
+
items.select { |item| has_tag?( item, tag ) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Count the tags in a given collection of items. By default, the method
|
45
|
+
# counts tags in all the site items. The result is an hash such as:
|
46
|
+
# { tag => count }.
|
47
|
+
#
|
48
|
+
# @param [Array<Nanoc::Item>] items
|
49
|
+
# @return [Hash] Hash indexed by tag name with the occurences as value
|
50
|
+
def count_tags(items=nil)
|
51
|
+
items ||= @items
|
52
|
+
tags = items.map { |i| i[:tags] }.flatten.delete_if{|t| t.nil?}
|
53
|
+
tags.inject(Hash.new(0)) {|h,i| h[i] += 1; h }
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sort the tags of an item collection (defaults to all site items) in 'n'
|
57
|
+
# classes of rank. The rank 0 corresponds to the most frequent tags.
|
58
|
+
# The rank 'n-1' to the least frequents. The result is a hash such as:
|
59
|
+
# { tag => rank }
|
60
|
+
#
|
61
|
+
# @param [Integer] n number of rank
|
62
|
+
# @param [Array<Nanoc::Item>] items
|
63
|
+
def rank_tags(n, items=nil)
|
64
|
+
raise ArgumentError, 'the number of ranks should be > 1' if n < 2
|
65
|
+
|
66
|
+
items = @items if items.nil?
|
67
|
+
count = count_tags( items )
|
68
|
+
min, max = count.values.minmax
|
69
|
+
|
70
|
+
ranker = lambda { |num| n - 1 - (num - min) / (max - min) }
|
71
|
+
|
72
|
+
Hash[count.map {|tag,value| [tag, ranker.call(value) ] }]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns an Array of links to tags in the item, optionally omits the
|
76
|
+
# given tags from the selection
|
77
|
+
#
|
78
|
+
# @param [Item] item the item from which to extract tags
|
79
|
+
# @param [Array<String>] omit_tags tags that should be excluded
|
80
|
+
# @param [Item] options the options for the links to be created
|
81
|
+
# @option options [String] :tag_pattern ("%%tag%%") The pattern to be replace by the tag name
|
82
|
+
# @option options [String] :title ("options[:tag_pattern]") The text that will be in the link
|
83
|
+
# @option options [String] :file_extension (".html") The file extension
|
84
|
+
# @option options [String] :url_format ("/tags/:tag_pattern:file_extension") The path pattern
|
85
|
+
#
|
86
|
+
# @return [Array<String>] An array of html links
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# omited = ['strange_tag']
|
90
|
+
# options = { :tag_pattern => "%%TAGNAME%%",
|
91
|
+
# :title => "articles tagged with %%TAGNAME%%",
|
92
|
+
# :url_format => "/tags/tag_%%TAGNAME%%.html"}
|
93
|
+
# tag_links_for(item, omited, options) # => ['<a href="/tags/tag_a.html">articles tagged with a</a>', '<a href="/tags/tag_b.html">articles tagged with b</a>']
|
94
|
+
def tag_links_for(item, omit_tags=[], options={})
|
95
|
+
tags = []
|
96
|
+
return tags unless item[:tags]
|
97
|
+
|
98
|
+
options[:tag_pattern] ||= "%%tag%%"
|
99
|
+
options[:title] ||= options[:tag_pattern]
|
100
|
+
options[:file_extension] ||= ".html"
|
101
|
+
options[:url_format] ||= "/tags/#{options[:tag_pattern]}#{options[:file_extension]}"
|
102
|
+
|
103
|
+
tags = item[:tags] - omit_tags
|
104
|
+
|
105
|
+
tags.map! do |tag|
|
106
|
+
title = options[:title].gsub(options[:tag_pattern], tag.downcase)
|
107
|
+
url = options[:url_format].gsub(options[:tag_pattern], tag.downcase)
|
108
|
+
content_tag('a', title, {:href => url})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creates in-memory tag pages from tags of the passed items or form all items
|
113
|
+
#
|
114
|
+
# @param [Array<Item>] item the item from which to extract tags
|
115
|
+
# @param [Item] options the options for the item to be created
|
116
|
+
# @option options [String] :tag_pattern ("%%tag%%") The pattern to be replace by the tag name
|
117
|
+
# @option options [String] :title ("options[:tag_pattern]") The text that will be in the link
|
118
|
+
# @option options [String] :identifier ("/tags/option[:tag_pattern]") The item identifer
|
119
|
+
# @option options [String] :template ("tag") The template/layout to use to render the tag
|
120
|
+
def create_tag_pages(items=nil, options={})
|
121
|
+
options[:tag_pattern] ||= "%%tag%%"
|
122
|
+
options[:title] ||= options[:tag_pattern]
|
123
|
+
options[:identifier] ||= "/tags/#{options[:tag_pattern]}/"
|
124
|
+
options[:template] ||= "tag"
|
125
|
+
|
126
|
+
tag_set(items).each do |tagname|
|
127
|
+
raw_content = "<%= render('#{options[:template]}', :tag => '#{tagname}') %>"
|
128
|
+
attributes = { :title => options[:title].gsub(options[:tag_pattern], tagname) }
|
129
|
+
identifier = options[:identifier].gsub(options[:tag_pattern], tagname)
|
130
|
+
|
131
|
+
@items << Nanoc::Item.new(raw_content, attributes, identifier, :binary => false)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'nanoc/toolbox/helpers/navigation'
|
2
2
|
require 'nanoc/toolbox/helpers/gravatar'
|
3
3
|
require 'nanoc/toolbox/helpers/html_tag'
|
4
|
+
require 'nanoc/toolbox/helpers/disqus'
|
5
|
+
require 'nanoc/toolbox/helpers/blogging_extra'
|
6
|
+
require 'nanoc/toolbox/helpers/tagging_extra'
|
4
7
|
require 'nanoc/toolbox/helpers/google_analytics'
|
5
8
|
|
6
9
|
# This module will regroup all the helpers for nanoc
|
7
10
|
module Nanoc::Toolbox::Helpers
|
8
11
|
|
9
|
-
end
|
12
|
+
end
|
data/nanoc-toolbox.gemspec
CHANGED
@@ -2,25 +2,26 @@
|
|
2
2
|
require File.expand_path("../lib/nanoc/toolbox/version", __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
|
-
s.name
|
6
|
-
s.version
|
7
|
-
s.platform
|
8
|
-
s.authors
|
9
|
-
s.email
|
10
|
-
s.homepage
|
11
|
-
s.summary
|
12
|
-
s.description
|
5
|
+
s.name = "nanoc-toolbox"
|
6
|
+
s.version = Nanoc::Toolbox::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Anouar ADLANI"]
|
9
|
+
s.email = ["anouar@adlani.com"]
|
10
|
+
s.homepage = "http://aadlani.github.com/nanoc-toolbox/"
|
11
|
+
s.summary = "A collection of helper and filters for nanoc"
|
12
|
+
s.description = "The nanoc-toolbox is a collection of filters and helpers for the static site generator tool nanoc"
|
13
13
|
s.rdoc_options = ["--main", "README.rdoc"]
|
14
14
|
|
15
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
15
16
|
s.required_rubygems_version = ">= 1.3.6"
|
16
17
|
|
17
|
-
s.add_dependency "nanoc",
|
18
|
-
s.add_dependency "nokogiri", "
|
19
|
-
s.add_dependency "jsmin",
|
18
|
+
s.add_dependency "nanoc", "~> 3.4"
|
19
|
+
s.add_dependency "nokogiri", "~> 1.4"
|
20
|
+
s.add_dependency "jsmin", "~> 1.0"
|
20
21
|
|
21
|
-
s.add_development_dependency "bundler", "
|
22
|
-
s.add_development_dependency "rspec",
|
23
|
-
s.add_development_dependency "rake"
|
22
|
+
s.add_development_dependency "bundler", "~> 1.1"
|
23
|
+
s.add_development_dependency "rspec", "~> 2.4"
|
24
|
+
s.add_development_dependency "rake", "~> 0.9"
|
24
25
|
|
25
26
|
s.files = `git ls-files`.split("\n")
|
26
27
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
@@ -1,31 +1,4 @@
|
|
1
|
-
# <div>
|
2
|
-
# <h1>Title</h1>
|
3
|
-
#
|
4
|
-
# <h2>Sub title1</h2>
|
5
|
-
# <p>Lorem Ipsum</p>
|
6
|
-
#
|
7
|
-
# <h3>Sub Sub Title1</h3>
|
8
|
-
# <p>Lorem Ipsum</p>
|
9
|
-
#
|
10
|
-
# <h3>Sub Sub Title2</h3>
|
11
|
-
# <p>Lorem Ipsum</p>
|
12
|
-
#
|
13
|
-
# <h3>Sub Sub Title3</h3>
|
14
|
-
# <p>Lorem Ipsum</p>
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# <h2>Sub title2</h2>
|
18
|
-
# <p>Lorem Ipsum</p>
|
19
|
-
#
|
20
|
-
# <h2>Sub title3</h2>
|
21
|
-
# <p>Lorem Ipsum</p>
|
22
|
-
#
|
23
|
-
# <h2>Sub title4</h2>
|
24
|
-
# <p>Lorem Ipsum</p>
|
25
|
-
# </div>
|
26
|
-
|
27
1
|
require "spec_helper"
|
28
|
-
require "nokogiri"
|
29
2
|
|
30
3
|
describe Nanoc::Toolbox::Filters::AddSections do
|
31
4
|
before(:each) do
|
@@ -33,6 +6,11 @@ describe Nanoc::Toolbox::Filters::AddSections do
|
|
33
6
|
end
|
34
7
|
|
35
8
|
describe ".run" do
|
36
|
-
|
9
|
+
it "minifies javascript" do
|
10
|
+
content = "<h1>A Title<h1/><h2>A Second Title<h2/>"
|
11
|
+
result = @filter.run(content)
|
12
|
+
result.should_not eq content
|
13
|
+
result.should =~ /"section"/
|
14
|
+
end
|
37
15
|
end
|
38
|
-
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Nanoc::Toolbox::Filters::JsMinify do
|
4
|
+
before(:each) do
|
5
|
+
@filter = described_class.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".run" do
|
9
|
+
it "minifies javascript" do
|
10
|
+
content = "alert('Hello World!'); /*Print Hello world*/\n"
|
11
|
+
@filter.run(content).should_not eq content
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class BloggingExtraDummyClass
|
4
|
+
include Nanoc::Toolbox::Helpers::BloggingExtra
|
5
|
+
def initialize
|
6
|
+
@config = {}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Nanoc::Toolbox::Helpers::BloggingExtra do
|
11
|
+
|
12
|
+
subject { BloggingExtraDummyClass.new }
|
13
|
+
|
14
|
+
it { should respond_to(:add_post_attributes) }
|
15
|
+
it { should respond_to(:act_as_post) }
|
16
|
+
it { should respond_to(:slug_for) }
|
17
|
+
it { should respond_to(:recent_posts) }
|
18
|
+
it { should respond_to(:posts_by_date) }
|
19
|
+
|
20
|
+
describe ".slug_for" do
|
21
|
+
it "returns the slug set in the item if it's existing" do
|
22
|
+
item = { :slug => "abc-def-geh.html" }
|
23
|
+
subject.slug_for(item).should == "abc-def-geh.html"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "generate the slug based on the item filename, by striping spaces" do
|
27
|
+
item = { :filename => "abc def geh.html" }
|
28
|
+
subject.slug_for(item).should == "abc-def-geh"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe ".add_post_attributes" do
|
33
|
+
it "defines the items as posts when located in the defined folders" do
|
34
|
+
articles = [
|
35
|
+
Nanoc::Item.new("", { :extension => ".md", :created_at => "01/12/2012 22:14" }, "test-of-post2"),
|
36
|
+
Nanoc::Item.new("", { :filename => "_posts/test-of-post2", :extension => ".md", :created_at => "01/12/2012 22:14" }, "test-of-post2"),
|
37
|
+
Nanoc::Item.new("", { :filename => "_articles/test-of-post3", :extension => ".md", :created_at => "01/12/2010 22:13" }, "test-of-post3"),
|
38
|
+
Nanoc::Item.new("", { :filename => "test-of-post6", :extension => ".md", :created_at => "01/12/2008 22:10" }, "test-of-post6")]
|
39
|
+
|
40
|
+
subject.stub(:items).and_return(articles)
|
41
|
+
subject.should_receive(:act_as_post).with(an_instance_of(Nanoc::Item)).twice
|
42
|
+
subject.add_post_attributes
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe ".act_as_post" do
|
47
|
+
before do
|
48
|
+
@item = { :filename => "2011-02-12-test-of-post", :extension => ".md", :created_at => "01/12/2011 22:15" }
|
49
|
+
subject.act_as_post(@item)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "forces the item kind to article" do
|
53
|
+
@item[:kind].should == 'article'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "handles the date from the filename" do
|
57
|
+
@item[:created_at].should == Time.local(2011, 02, 12)
|
58
|
+
@item[:year].should == "2011"
|
59
|
+
@item[:month].should == "02"
|
60
|
+
@item[:day].should == "12"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "do something when no date set in the filename" do
|
64
|
+
@item[:year].to_i.should == @item[:created_at].year
|
65
|
+
@item[:month].to_i.should == @item[:created_at].month
|
66
|
+
@item[:day].to_i.should == @item[:created_at].day
|
67
|
+
end
|
68
|
+
|
69
|
+
it "generates a slug from the filename" do
|
70
|
+
@item[:slug].should == "test-of-post"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "enables by default the comments" do
|
74
|
+
@item[:comments].should be_true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".recent_posts" do
|
79
|
+
before do
|
80
|
+
@last_articles = [
|
81
|
+
Nanoc::Item.new("", { :filename => "test-of-post1", :extension => ".md", :created_at => "01/12/2008 22:15" }, "test-of-post1"),
|
82
|
+
Nanoc::Item.new("", { :filename => "test-of-post2", :extension => ".md", :created_at => "01/12/2012 22:14" }, "test-of-post2"),
|
83
|
+
Nanoc::Item.new("", { :filename => "test-of-post3", :extension => ".md", :created_at => "01/12/2010 22:13" }, "test-of-post3"),
|
84
|
+
Nanoc::Item.new("", { :filename => "test-of-post4", :extension => ".md", :created_at => "01/12/2010 22:12" }, "test-of-post4"),
|
85
|
+
Nanoc::Item.new("", { :filename => "test-of-post5", :extension => ".md", :created_at => "01/11/2010 22:11" }, "test-of-post5"),
|
86
|
+
Nanoc::Item.new("", { :filename => "test-of-post6", :extension => ".md", :created_at => "01/12/2013 22:10" }, "test-of-post6")]
|
87
|
+
|
88
|
+
subject.stub(:sorted_articles).and_return(@last_articles)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "returns the requested recent posts" do
|
92
|
+
posts = subject.recent_posts(3)
|
93
|
+
posts.length.should eq 3
|
94
|
+
posts.should_not include(@last_articles.last)
|
95
|
+
posts.should include(@last_articles.first)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns the existing posts when requesting more than" do
|
99
|
+
posts = subject.recent_posts(13)
|
100
|
+
posts.length.should eq @last_articles.length
|
101
|
+
posts.should eq(@last_articles)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "excludes the current item when requested" do
|
105
|
+
posts = subject.recent_posts(6, @last_articles.last)
|
106
|
+
posts.should_not include(@last_articles.last)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe ".posts_by_date" do
|
111
|
+
before do
|
112
|
+
@last_articles = []
|
113
|
+
articles = [
|
114
|
+
Nanoc::Item.new("", { :filename => "test-of-post1", :extension => ".md", :created_at => "01/12/2013 22:15" }, "test-of-post1"),
|
115
|
+
Nanoc::Item.new("", { :filename => "test-of-post2", :extension => ".md", :created_at => "01/12/2012 22:14" }, "test-of-post2"),
|
116
|
+
Nanoc::Item.new("", { :filename => "test-of-post3", :extension => ".md", :created_at => "01/12/2010 22:13" }, "test-of-post3"),
|
117
|
+
Nanoc::Item.new("", { :filename => "test-of-post4", :extension => ".md", :created_at => "01/12/2010 22:12" }, "test-of-post4"),
|
118
|
+
Nanoc::Item.new("", { :filename => "test-of-post5", :extension => ".md", :created_at => "01/02/2010 22:11" }, "test-of-post5"),
|
119
|
+
Nanoc::Item.new("", { :filename => "test-of-post6", :extension => ".md", :created_at => "01/12/2008 22:10" }, "test-of-post6")]
|
120
|
+
|
121
|
+
articles.each do |article|
|
122
|
+
@last_articles << subject.act_as_post(article)
|
123
|
+
end
|
124
|
+
subject.stub(:sorted_articles).and_return(@last_articles)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "returns the article grouped by years and months" do
|
128
|
+
grouped_article = subject.posts_by_date
|
129
|
+
grouped_article.keys.should eq @last_articles.map {|i| i[:year]}.uniq
|
130
|
+
grouped_article[2010][12].should eq @last_articles[2..3]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class DummyDisqusClass
|
4
|
+
include Nanoc::Toolbox::Helpers::Disqus
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Nanoc::Toolbox::Helpers::Disqus do
|
8
|
+
subject { DummyDisqusClass.new }
|
9
|
+
|
10
|
+
it { should respond_to :disqus_id_for }
|
11
|
+
it { should respond_to :disqus_js_snippet }
|
12
|
+
it { should respond_to :disqus_nojs_snippet }
|
13
|
+
|
14
|
+
describe ".disqus_id_for" do
|
15
|
+
it "calls slug_for to generate the id" do
|
16
|
+
subject.should_receive(:slug_for).once.and_return('hello-world')
|
17
|
+
subject.disqus_id_for({}).should eq 'hello_world'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "prepends the disqus prefix id if passed in the options" do
|
21
|
+
subject.should_receive(:slug_for).once.and_return('hello-world')
|
22
|
+
subject.disqus_id_for({}, {:disqus_id_prefix => 'my_website_'}).should eq 'my_website_hello_world'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".disqus_js_snippet" do
|
27
|
+
it "returns the JS snippet" do
|
28
|
+
subject.disqus_js_snippet.should =~/<script type="text\/javascript">/
|
29
|
+
end
|
30
|
+
|
31
|
+
it "declares prefixed variables passed in options" do
|
32
|
+
menu = subject.disqus_js_snippet({:name => "Anouar", :lastname => 'ADLANI'})
|
33
|
+
menu.should =~/var disqus_name = 'Anouar';/
|
34
|
+
menu.should =~/var disqus_lastname = 'ADLANI';/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".disqus_nojs_snippet" do
|
39
|
+
it "returns the default noscript snippet" do
|
40
|
+
subject.disqus_nojs_snippet.should eq "<noscript>Please enable JavaScript to view the <a href=\"http://disqus.com/?ref_noscript\">comments powered by Disqus.</a></noscript>"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "render the specified message" do
|
44
|
+
subject.disqus_nojs_snippet("No message").should eq "<noscript>No message</noscript>"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|