tumblargh 0.2.0 → 0.2.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +2 -14
- data/Gemfile.lock +18 -20
- data/Rakefile +0 -20
- data/examples/{confg.ru → config.ru} +0 -0
- data/lib/tumblargh.rb +1 -0
- data/lib/tumblargh/grammar.rb +235 -55
- data/lib/tumblargh/grammar.treetop +14 -2
- data/lib/tumblargh/node/block.rb +6 -4
- data/lib/tumblargh/node/block_start.rb +15 -3
- data/lib/tumblargh/parser.rb +5 -9
- data/lib/tumblargh/renderer.rb +2 -2
- data/lib/tumblargh/renderer/base.rb +7 -5
- data/lib/tumblargh/renderer/blocks.rb +3 -3
- data/lib/tumblargh/renderer/blocks/base.rb +2 -2
- data/lib/tumblargh/renderer/document.rb +4 -11
- data/lib/tumblargh/version.rb +3 -0
- data/spec/fixtures/themes/tumblr-boilerplate.html +168 -0
- data/spec/parser_spec.rb +89 -50
- data/tumblargh.gemspec +19 -118
- metadata +73 -66
- data/VERSION +0 -1
@@ -12,11 +12,23 @@ grammar Tumblr
|
|
12
12
|
end
|
13
13
|
|
14
14
|
rule block_start
|
15
|
-
'{block:'
|
15
|
+
'{block:' block_name space? block_arguments? '}' space? <Tumblargh::Node::BlockStart>
|
16
16
|
end
|
17
17
|
|
18
18
|
rule block_end
|
19
|
-
'{/block:'
|
19
|
+
'{/block:' block_name '}' space? <Tumblargh::Node::BlockEnd>
|
20
|
+
end
|
21
|
+
|
22
|
+
rule block_name
|
23
|
+
[^\s}:;]+
|
24
|
+
end
|
25
|
+
|
26
|
+
rule block_arguments
|
27
|
+
block_argument+
|
28
|
+
end
|
29
|
+
|
30
|
+
rule block_argument
|
31
|
+
(([a-zA-Z0-9]+) '=' '"' ([a-zA-Z0-9]+) '"') space?
|
20
32
|
end
|
21
33
|
|
22
34
|
rule tag
|
data/lib/tumblargh/node/block.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Tumblargh
|
2
2
|
module Node
|
3
|
-
|
4
3
|
class Block < Root
|
5
4
|
|
6
5
|
def name
|
@@ -8,8 +7,12 @@ module Tumblargh
|
|
8
7
|
elements.first.name
|
9
8
|
end
|
10
9
|
|
10
|
+
def options
|
11
|
+
elements.first.options
|
12
|
+
end
|
13
|
+
|
11
14
|
def to_tree
|
12
|
-
ary = [type, name]
|
15
|
+
ary = [type, name, options]
|
13
16
|
|
14
17
|
# Second node is a Treetop SyntaxNode which holds
|
15
18
|
# the rest of the block contents. Extra parse node
|
@@ -22,10 +25,9 @@ module Tumblargh
|
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
25
|
-
|
28
|
+
ary
|
26
29
|
end
|
27
30
|
|
28
31
|
end
|
29
|
-
|
30
32
|
end
|
31
33
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Tumblargh
|
2
2
|
module Node
|
3
|
-
|
4
3
|
class BlockStart < Base
|
5
4
|
|
6
5
|
def name
|
@@ -8,15 +7,28 @@ module Tumblargh
|
|
8
7
|
"#{str[0].upcase}#{str[1..str.size]}"
|
9
8
|
end
|
10
9
|
|
10
|
+
def options
|
11
|
+
arguments = elements[3]
|
12
|
+
return {} if arguments.nil? || arguments.elements.nil?
|
13
|
+
|
14
|
+
arguments.elements.inject({}) do |memo, node|
|
15
|
+
nodes = node.elements.first.elements
|
16
|
+
k = nodes[0].text_value
|
17
|
+
v = nodes[3].text_value
|
18
|
+
|
19
|
+
memo[k] = v
|
20
|
+
memo
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
11
24
|
def matching_end
|
12
25
|
"{/block:#{name}}"
|
13
26
|
end
|
14
27
|
|
15
28
|
def to_tree
|
16
|
-
return [type, name]
|
29
|
+
return [type, name, options]
|
17
30
|
end
|
18
31
|
|
19
32
|
end
|
20
|
-
|
21
33
|
end
|
22
34
|
end
|
data/lib/tumblargh/parser.rb
CHANGED
@@ -3,6 +3,8 @@ require 'open-uri'
|
|
3
3
|
require 'nokogiri'
|
4
4
|
|
5
5
|
module Tumblargh
|
6
|
+
class ParserError < StandardError
|
7
|
+
end
|
6
8
|
|
7
9
|
class Parser
|
8
10
|
grammar_file = File.join(File.dirname(__FILE__), 'grammar')
|
@@ -56,10 +58,8 @@ module Tumblargh
|
|
56
58
|
def parse
|
57
59
|
@structure = @@parser.parse(html)
|
58
60
|
|
59
|
-
if
|
60
|
-
|
61
|
-
puts "#{@@parser.failure_line}:#{@@parser.failure_column}"
|
62
|
-
raise ParserError, "Parse error at offset: #{@@parser.index}"
|
61
|
+
if @structure.nil?
|
62
|
+
raise ParserError, @@parser.failure_reason
|
63
63
|
end
|
64
64
|
|
65
65
|
@tree = @structure.to_tree
|
@@ -77,7 +77,7 @@ module Tumblargh
|
|
77
77
|
|
78
78
|
default = case type
|
79
79
|
when "if"
|
80
|
-
default == "1"
|
80
|
+
default == "1"
|
81
81
|
else
|
82
82
|
default
|
83
83
|
end
|
@@ -89,8 +89,4 @@ module Tumblargh
|
|
89
89
|
opts
|
90
90
|
end
|
91
91
|
end
|
92
|
-
|
93
|
-
class ParserError < StandardError
|
94
|
-
end
|
95
|
-
|
96
92
|
end
|
data/lib/tumblargh/renderer.rb
CHANGED
@@ -9,7 +9,7 @@ require 'tumblargh/renderer/tag'
|
|
9
9
|
module Tumblargh
|
10
10
|
module Renderer
|
11
11
|
|
12
|
-
def self.factory(node, context)
|
12
|
+
def self.factory(node, context, options = {})
|
13
13
|
args = []
|
14
14
|
base = node.first.to_s
|
15
15
|
|
@@ -35,7 +35,7 @@ module Tumblargh
|
|
35
35
|
klass_name = "Tumblargh::Renderer::#{base}"
|
36
36
|
klass = klass_name.constantize
|
37
37
|
|
38
|
-
klass.new(node, context, *args)
|
38
|
+
klass.new(node, context, options, *args)
|
39
39
|
end
|
40
40
|
|
41
41
|
end
|
@@ -1,15 +1,14 @@
|
|
1
1
|
module Tumblargh
|
2
2
|
module Renderer
|
3
|
-
|
4
3
|
class Base
|
5
4
|
|
6
5
|
class << self
|
7
6
|
|
8
7
|
# Define a simple tag on the block.
|
9
|
-
# Name being tag name, and optionally the attibute/method to call
|
8
|
+
# Name being tag name, and optionally the attibute/method to call
|
10
9
|
# on the context. If the second argument is left off, it'll just use the tag name.
|
11
10
|
def contextual_tag(name, attribute=nil)
|
12
|
-
class_eval do
|
11
|
+
class_eval do
|
13
12
|
define_method name do
|
14
13
|
context.send(attribute || name)
|
15
14
|
end
|
@@ -18,12 +17,15 @@ module Tumblargh
|
|
18
17
|
|
19
18
|
end
|
20
19
|
|
21
|
-
attr_reader :node
|
20
|
+
attr_reader :node, :options
|
22
21
|
attr_accessor :context
|
23
22
|
|
24
|
-
|
23
|
+
alias_method :config, :options # Backwards compatibility with old Document rendere
|
24
|
+
|
25
|
+
def initialize(node, context, options = {})
|
25
26
|
@node = node
|
26
27
|
@context = context
|
28
|
+
@options = options.with_indifferent_access
|
27
29
|
end
|
28
30
|
|
29
31
|
def context_post
|
@@ -91,9 +91,9 @@ module Tumblargh
|
|
91
91
|
class Boolean < Base
|
92
92
|
attr_reader :variable
|
93
93
|
|
94
|
-
def initialize(node, context, *args)
|
94
|
+
def initialize(node, context, options = {}, *args)
|
95
95
|
@variable = args[0]
|
96
|
-
super(node, context)
|
96
|
+
super(node, context, options)
|
97
97
|
end
|
98
98
|
|
99
99
|
def should_render?
|
@@ -120,7 +120,7 @@ module Tumblargh
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
# Identical to {PostTitle}, but will automatically generate a summary
|
123
|
+
# Identical to {PostTitle}, but will automatically generate a summary
|
124
124
|
# if a title doesn't exist.
|
125
125
|
class PostSummary < PostTitle
|
126
126
|
def post_summary
|
@@ -22,10 +22,10 @@ module Tumblargh
|
|
22
22
|
def render
|
23
23
|
return '' unless should_render?
|
24
24
|
|
25
|
-
|
25
|
+
_, type, options, *nodes = node
|
26
26
|
|
27
27
|
res = nodes.map do |n|
|
28
|
-
Renderer.factory(n, self).render
|
28
|
+
Renderer.factory(n, self, options).render
|
29
29
|
end
|
30
30
|
|
31
31
|
" #{res.join('')} "
|
@@ -1,18 +1,10 @@
|
|
1
|
-
|
1
|
+
module Tumblargh
|
2
2
|
module Renderer
|
3
|
-
|
4
3
|
class Document < Base
|
5
4
|
|
6
|
-
attr_accessor :config
|
7
|
-
|
8
|
-
def initialize(node, context, config)
|
9
|
-
@config = config.with_indifferent_access
|
10
|
-
super(node, context)
|
11
|
-
end
|
12
|
-
|
13
5
|
# Are we rendering a permalink page?
|
14
6
|
def permalink?
|
15
|
-
|
7
|
+
options[:permalink] == true
|
16
8
|
end
|
17
9
|
|
18
10
|
# TAGS ----------
|
@@ -21,6 +13,7 @@
|
|
21
13
|
|
22
14
|
def meta_description
|
23
15
|
strip_html(description)
|
16
|
+
strip_html(description)
|
24
17
|
end
|
25
18
|
|
26
19
|
def favicon
|
@@ -32,7 +25,7 @@
|
|
32
25
|
"#{context.url}rss"
|
33
26
|
end
|
34
27
|
|
35
|
-
# Appearance options
|
28
|
+
# Appearance options
|
36
29
|
# http://www.tumblr.com/docs/en/custom_themes#appearance-options
|
37
30
|
def color(key)
|
38
31
|
custom_value_for_type :color, key
|
@@ -0,0 +1,168 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="{block:English}en{/block:English}{block:French}fr{/block:French}{block:German}de{/block:German}{block:Japanese}ja{/block:Japanese}{block:Italian}it{/block:Italian}{block:Spanish}es{/block:Spanish}{block:Polish}pl{/block:Polish}">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
6
|
+
<meta name="viewport" content="width=device-width">
|
7
|
+
<title>{Title}{block:PostSummary} — {PostSummary}{/block:PostSummary}</title>
|
8
|
+
{block:Description}<meta name="description" content="{MetaDescription}">{/block:Description}
|
9
|
+
|
10
|
+
<link rel="apple-touch-icon" href="{PortraitURL-128}">
|
11
|
+
<link rel="shortcut icon" href="{Favicon}">
|
12
|
+
<link rel="alternate" type="application/rss+xml" href="{RSS}">
|
13
|
+
<!--Normalize 2.1.0 CSS-->
|
14
|
+
<link rel="stylesheet" href="http://static.tumblr.com/cqczc5x/kYdmihjuj/normalize.css" type="text/css" media="all">
|
15
|
+
<style type="text/css">
|
16
|
+
|
17
|
+
img, video, object, embed {
|
18
|
+
max-width: 100%;
|
19
|
+
height: auto !important;
|
20
|
+
}
|
21
|
+
|
22
|
+
.clearfix {zoom:1;}
|
23
|
+
.clearfix:before, .clearfix:after {
|
24
|
+
content: "\0020";
|
25
|
+
display: block;
|
26
|
+
height: 0;
|
27
|
+
overflow: hidden; }
|
28
|
+
.clearfix:after {clear: both;}
|
29
|
+
|
30
|
+
/*Tumblr inherited */
|
31
|
+
iframe#tumblr_controls {}
|
32
|
+
.search_query {}
|
33
|
+
.read_more_container a {}
|
34
|
+
|
35
|
+
</style>
|
36
|
+
<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
|
37
|
+
</head>
|
38
|
+
<body>
|
39
|
+
<header id="header">
|
40
|
+
<h1 id="logo"><a href="/">{Title}</a></h1>
|
41
|
+
{block:Description}<div class="description">{Description}</div>{/block:Description}
|
42
|
+
<ul id="nav">
|
43
|
+
{block:HasPages}{block:Pages}<li><a href="{URL}">{Label}</a></li>{/block:Pages}{/block:HasPages}
|
44
|
+
<li><a href="/archive">{lang:Archive}</a></li>
|
45
|
+
{block:AskEnabled}<li><a href="/ask">{AskLabel}</a></li>{/block:AskEnabled}
|
46
|
+
</ul>
|
47
|
+
<form id="search" action="/search" method="get">
|
48
|
+
<input type="text" placeholder="{lang:Search}" name="q" value="{SearchQuery}">
|
49
|
+
<input type="submit" value="{lang:Search}">
|
50
|
+
</form>
|
51
|
+
</header>
|
52
|
+
<section class="content">
|
53
|
+
{block:SearchPage}
|
54
|
+
<div class="result">
|
55
|
+
<p>{lang:Found SearchResultCount results for SearchQuery 2}</p>
|
56
|
+
{block:NoSearchResults}<p>{lang:No results for SearchQuery 2}</p>{/block:NoSearchResults}
|
57
|
+
</div>
|
58
|
+
{/block:SearchPage}
|
59
|
+
{block:TagPage}<div class="result"><p>{lang:TagResultCount posts tagged Tag 3}</p></div>{/block:TagPage}
|
60
|
+
|
61
|
+
{block:Posts}
|
62
|
+
<article class="post {TagsAsClasses}">
|
63
|
+
{block:Date}
|
64
|
+
{block:NewDayDate}<p>{DayOfWeek}, {Month} {DayOfMonth}, {Year}</p>{/block:NewDayDate}
|
65
|
+
{block:SameDayDate}<p>{DayOfWeek}, {Month} {DayOfMonth}, {Year}</p>{/block:SameDayDate}
|
66
|
+
{/block:Date}
|
67
|
+
{block:Text}
|
68
|
+
<div class="text">
|
69
|
+
{block:Title}<h3>{Title}</h3>{/block:Title}
|
70
|
+
{Body}
|
71
|
+
</div>
|
72
|
+
{/block:Text}
|
73
|
+
{block:Quote}
|
74
|
+
<div class="quote">
|
75
|
+
<blockquote class="words {Length}">“{Quote}”</blockquote>
|
76
|
+
{block:Source}<p class="source">— {Source}</p>{/block:Source}
|
77
|
+
</div>
|
78
|
+
{/block:Quote}
|
79
|
+
{block:Link}
|
80
|
+
<div class="link">
|
81
|
+
<h3><a href="{URL}" {Target}>{Name}</a></h3>
|
82
|
+
{block:Description}<div class="caption">{Description}</div>{/block:Description}
|
83
|
+
</div>
|
84
|
+
{/block:Link}
|
85
|
+
{block:Video}
|
86
|
+
<div class="video">
|
87
|
+
{Video-500}
|
88
|
+
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
|
89
|
+
</div>
|
90
|
+
{/block:Video}
|
91
|
+
{block:Audio}
|
92
|
+
<div class="audio">
|
93
|
+
{block:AlbumArt}<img src="{AlbumArtURL}" alt="">{/block:AlbumArt}
|
94
|
+
{AudioPlayerBlack}
|
95
|
+
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
|
96
|
+
</div>
|
97
|
+
{/block:Audio}
|
98
|
+
{block:Photo}
|
99
|
+
<div class="photo">
|
100
|
+
{LinkOpenTag}<img src="{PhotoURL-HighRes}" alt="{PhotoAlt}"/>{LinkCloseTag}
|
101
|
+
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
|
102
|
+
</div>
|
103
|
+
{/block:Photo}
|
104
|
+
{block:Photoset}
|
105
|
+
<div class="photoset">
|
106
|
+
{block:Photos}
|
107
|
+
<img src="{PhotoURL-HighRes}" alt="{PhotoAlt}"/>
|
108
|
+
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
|
109
|
+
{/block:Photos}
|
110
|
+
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
|
111
|
+
</div>
|
112
|
+
{/block:Photoset}
|
113
|
+
|
114
|
+
{block:Panorama}
|
115
|
+
<div class="panorama">
|
116
|
+
{LinkOpenTag}<img src="{PhotoURL-Panorama}" alt="{PhotoAlt}" />{LinkCloseTag}
|
117
|
+
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
|
118
|
+
</div>
|
119
|
+
{/block:Panorama}
|
120
|
+
|
121
|
+
{block:Chat}
|
122
|
+
<div class="chat">
|
123
|
+
{block:Title}<h3>{Title}</h3>{/block:Title}
|
124
|
+
<ul class="conversation">
|
125
|
+
{block:Lines}
|
126
|
+
<li class="line {Alt}">
|
127
|
+
{block:Label}<span class="person">{Label}</span>{/block:Label}
|
128
|
+
<span class="person-said">{Line}</span>
|
129
|
+
</li>
|
130
|
+
{/block:Lines}
|
131
|
+
</ul>
|
132
|
+
</div>
|
133
|
+
{/block:Chat}
|
134
|
+
{block:Answer}
|
135
|
+
<div class="answer">
|
136
|
+
<img src="{AskerPortraitURL-40}">
|
137
|
+
{Asker}
|
138
|
+
{Question}
|
139
|
+
{Answer}
|
140
|
+
</div>
|
141
|
+
{/block:Answer}
|
142
|
+
{block:IndexPage}<p><a href="{Permalink}" class="permalink">{lang:Permalink}</a></p>{/block:IndexPage}
|
143
|
+
</article>
|
144
|
+
{/block:Posts}
|
145
|
+
|
146
|
+
{block:PermalinkPagination}
|
147
|
+
<div class="pagination">
|
148
|
+
{block:PreviousPost}<a class="prev"href="{PreviousPost}">{lang:Previous post}</a>{/block:PreviousPost}
|
149
|
+
{block:NextPost}<a class="next" href="{NextPost}">{lang:Next post}</a>{/block:NextPost}
|
150
|
+
</div>
|
151
|
+
{/block:PermalinkPagination}
|
152
|
+
|
153
|
+
{block:Pagination}
|
154
|
+
<div class="pagination">
|
155
|
+
{block:PreviousPage}<a class="prev" href="{PreviousPage}">{lang:Previous}</a>{/block:PreviousPage}
|
156
|
+
|
157
|
+
{block:JumpPagination length="5"}
|
158
|
+
{block:CurrentPage}<span class="current-page">{PageNumber}</span>{/block:CurrentPage}
|
159
|
+
{block:JumpPage}<a class="jump-page" href="{URL}">{PageNumber}</a>{/block:JumpPage}
|
160
|
+
{/block:JumpPagination}
|
161
|
+
|
162
|
+
{block:NextPage}<a class="next" href="{NextPage}">{lang:Next}</a>{/block:NextPage}
|
163
|
+
</div>
|
164
|
+
{/block:Pagination}
|
165
|
+
|
166
|
+
</section><!--close content-->
|
167
|
+
</body>
|
168
|
+
</html>
|
data/spec/parser_spec.rb
CHANGED
@@ -1,52 +1,40 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
|
4
4
|
describe Tumblargh::Parser do
|
5
|
-
|
6
|
-
before do
|
7
|
-
@parser = Tumblargh::Parser.new
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should exist" do
|
11
|
-
defined?(Tumblargh::Parser).should be_true
|
12
|
-
end
|
5
|
+
subject { Tumblargh::Parser.new }
|
13
6
|
|
14
7
|
describe "given invalid input" do
|
15
|
-
|
16
8
|
it "should throw an error if there is an unclosed block" do
|
17
|
-
|
9
|
+
subject.html = <<-eos
|
18
10
|
{block:Text}
|
19
11
|
{block:Title}<h1>{Title}</h1>{block:Title}
|
20
12
|
<p>{Body}</p>
|
21
13
|
{/block:text}
|
22
14
|
eos
|
23
15
|
|
24
|
-
lambda {
|
16
|
+
lambda { subject.tree }.should raise_error Tumblargh::ParserError
|
25
17
|
end
|
26
|
-
|
27
18
|
end
|
28
19
|
|
29
20
|
describe "given something that kinda looks like a tag but isn't" do
|
30
|
-
|
31
21
|
before do
|
32
|
-
|
22
|
+
subject.html = "<div>{CustomCSS</div>"
|
33
23
|
end
|
34
24
|
|
35
25
|
it "should NOT throw an error if there is a malformed tag" do
|
36
|
-
lambda {
|
26
|
+
lambda { subject.tree }.should_not raise_error Tumblargh::ParserError
|
37
27
|
end
|
38
28
|
|
39
29
|
it "should generate the following tree" do
|
40
|
-
|
30
|
+
subject.tree.should == [[:Literal, "<div>"], [:Literal, "{"], [:Literal, "CustomCSS</div>"]]
|
41
31
|
end
|
42
|
-
|
43
32
|
end
|
44
33
|
|
45
34
|
describe "when given a bunch of css" do
|
46
|
-
|
47
35
|
before do
|
48
36
|
@input = <<-eos
|
49
|
-
.container{*zoom:1;margin:auto;width:960px;max-width:100%;position:relative}.container:after{content:"";display:table;clear:both}.dot-sprite,#clients .nav .dots li,#clients .nav .dots li.active,#fullscreen_nav .nav .dots li,#fullscreen_nav .nav .dots li.active{background:url(
|
37
|
+
.container{*zoom:1;margin:auto;width:960px;max-width:100%;position:relative}.container:after{content:"";display:table;clear:both}.dot-sprite,#clients .nav .dots li,#clients .nav .dots li.active,#fullscreen_nav .nav .dots li,#fullscreen_nav .nav .dots li.active{background:url("../images/dot-sa49b299bc4.png") no-repeat}body.index{min-width:1000px}body.fullscreen{overflow-x:hidden}#clients{height:461px;overflow:visible;background:#fff url("../images/homepage-clients-bg.png") repeat-x 0 0px}#clients .frame{width:958px;height:448px;margin:0 auto;position:relative;-moz-border-radius:7px;-webkit-border-radius:7px;-o-border-radius:7px;-ms-border-radius:7px;-khtml-border-radius:7px;border-radius:7px;-moz-box-shadow:#000 0px 1px 2px;-webkit-box-shadow:#000 0px 1px 2px;-o-box-shadow:#000 0px 1px 2px;box-shadow:#000 0px 1px 2px;background:#262626}
|
50
38
|
|
51
39
|
#title a{
|
52
40
|
text-decoration:none;
|
@@ -70,24 +58,21 @@ describe Tumblargh::Parser do
|
|
70
58
|
#title b.right {right:-36px;}
|
71
59
|
eos
|
72
60
|
|
73
|
-
|
61
|
+
subject.html = @input
|
74
62
|
end
|
75
63
|
|
76
64
|
it "should NOT throw an error" do
|
77
|
-
lambda {
|
65
|
+
lambda { subject.tree }.should_not raise_error Tumblargh::ParserError
|
78
66
|
end
|
79
67
|
|
80
68
|
it "its output should match its input" do
|
81
|
-
|
69
|
+
subject.to_s.should eql @input
|
82
70
|
end
|
83
|
-
|
84
71
|
end
|
85
72
|
|
86
|
-
|
87
73
|
describe "given a simple partial" do
|
88
|
-
|
89
74
|
before do
|
90
|
-
|
75
|
+
subject.html = <<-eos
|
91
76
|
{block:Text}
|
92
77
|
{block:Title}<h1>{Title}</h1>{/block:Title}
|
93
78
|
<p>{Body}</p>
|
@@ -96,48 +81,46 @@ describe Tumblargh::Parser do
|
|
96
81
|
end
|
97
82
|
|
98
83
|
it "should not contain any custom appearance options" do
|
99
|
-
|
84
|
+
subject.options.empty?.should be_true
|
100
85
|
end
|
101
86
|
|
102
87
|
it "should contain the following tree" do
|
103
88
|
expected = [
|
104
89
|
[:Literal, " "],
|
105
|
-
[:Block, "Text",
|
106
|
-
[:Block, "Title",
|
107
|
-
[:Literal, "<h1>"],
|
108
|
-
[:Tag, "Title"],
|
90
|
+
[:Block, "Text", {},
|
91
|
+
[:Block, "Title", {},
|
92
|
+
[:Literal, "<h1>"],
|
93
|
+
[:Tag, "Title"],
|
109
94
|
[:Literal, "</h1>"]
|
110
|
-
],
|
111
|
-
[:Literal, "<p>"],
|
112
|
-
[:Tag, "Body"],
|
95
|
+
],
|
96
|
+
[:Literal, "<p>"],
|
97
|
+
[:Tag, "Body"],
|
113
98
|
[:Literal, "</p>\n "]
|
114
99
|
]
|
115
100
|
]
|
116
101
|
|
117
102
|
# Yes, Array.== Array is a deep value based comparison
|
118
|
-
|
103
|
+
subject.tree.should == expected
|
119
104
|
end
|
120
|
-
|
121
105
|
end
|
122
106
|
|
123
107
|
describe "given jake's solstice theme" do
|
124
|
-
|
125
108
|
before do
|
126
|
-
|
109
|
+
subject.html = open(File.join(FIXTURE_PATH, "themes", "solstice.html")).read
|
127
110
|
end
|
128
|
-
|
111
|
+
|
129
112
|
it "should contain the correct appearance options" do
|
130
|
-
|
113
|
+
subject.options.should == {
|
131
114
|
"image" => {
|
132
115
|
"background" => ""
|
133
|
-
},
|
116
|
+
},
|
134
117
|
"if" => {
|
135
118
|
"showpeopleifollow" => true,
|
136
|
-
"showmyportraitphoto" => true,
|
137
|
-
"showvialinkswithrebloggedposts" => true,
|
138
|
-
"useclassicpaging" => false,
|
119
|
+
"showmyportraitphoto" => true,
|
120
|
+
"showvialinkswithrebloggedposts" => true,
|
121
|
+
"useclassicpaging" => false,
|
139
122
|
"hidedisquscommentcountifzero" => false
|
140
|
-
},
|
123
|
+
},
|
141
124
|
"text" => {
|
142
125
|
"disqusshortname" => "",
|
143
126
|
"googleanalyticsid" => ""
|
@@ -145,15 +128,71 @@ describe Tumblargh::Parser do
|
|
145
128
|
}
|
146
129
|
end
|
147
130
|
|
148
|
-
it "should contain exacty one
|
149
|
-
|
150
|
-
matches = nodes.select do |n|
|
131
|
+
it "should contain exacty one Posts block" do
|
132
|
+
matches = subject.tree.select do |n|
|
151
133
|
n[0] == :Block && n[1] == "Posts"
|
152
134
|
end
|
153
135
|
|
154
136
|
matches.size.should eql 1
|
155
137
|
end
|
156
|
-
|
157
138
|
end
|
158
139
|
|
140
|
+
describe "block arguments" do
|
141
|
+
context "with a single argument" do
|
142
|
+
before do
|
143
|
+
subject.html = <<-eos
|
144
|
+
{block:JumpPagination length="5"}
|
145
|
+
{block:CurrentPage}<span class="current-page">{PageNumber}</span>{/block:CurrentPage}
|
146
|
+
{/block:JumpPagination}
|
147
|
+
eos
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should contain the following tree" do
|
151
|
+
expected = [
|
152
|
+
[:Literal, " "],
|
153
|
+
[:Block, "JumpPagination", { "length" => "5" },
|
154
|
+
[:Block, "CurrentPage", {},
|
155
|
+
[:Literal, "<span class=\"current-page\">"],
|
156
|
+
[:Tag, "PageNumber"],
|
157
|
+
[:Literal, "</span>"]
|
158
|
+
]
|
159
|
+
]
|
160
|
+
]
|
161
|
+
|
162
|
+
subject.tree.should == expected
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "with multiple arguments" do
|
167
|
+
before do
|
168
|
+
subject.html = <<-eos
|
169
|
+
{block:Something length="5" offset="2" foo="bar"}{/block:Something}
|
170
|
+
eos
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should contain the following tree" do
|
174
|
+
expected = [
|
175
|
+
[:Literal, " "],
|
176
|
+
[:Block, "Something", { "length" => "5", "offset" => "2", "foo" => "bar" }]
|
177
|
+
]
|
178
|
+
|
179
|
+
subject.tree.should == expected
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "tumblr-boilerplate" do
|
185
|
+
before do
|
186
|
+
# https://github.com/davesantos/tumblr-boilerplate/master/tumblr.html
|
187
|
+
subject.html = open(File.join(FIXTURE_PATH, "themes", "tumblr-boilerplate.html")).read
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should contain exacty one Posts block" do
|
191
|
+
matches = subject.tree.select do |n|
|
192
|
+
n[0] == :Block && n[1] == "Posts"
|
193
|
+
end
|
194
|
+
|
195
|
+
matches.size.should eql 1
|
196
|
+
end
|
197
|
+
end
|
159
198
|
end
|