qipowl 0.9.3 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,3 +6,17 @@ Feature: Mapper-Ruler-Bowler abstraction produces valid bowlers
6
6
  Given we use "html" bowler
7
7
  When the input string is ""
8
8
  Then bowler has all the method aliases
9
+
10
+ Scenario: Config params set properly
11
+ Given nothing
12
+ When we request param "bowlers"
13
+ Then param value ends with "/qipowl/config/bowlers"
14
+
15
+ Scenario: Additional map mergeg properly
16
+ Given we add additional bowler directory "spec"
17
+ And we use "html" bowler with additional map "html_additional_test"
18
+ When the input string is "This is ⌚striked⌚ out."
19
+ And the execute method is called on bowler
20
+ Then the result should equal to "<p>This is <del>striked</del> out.</p>"
21
+
22
+
@@ -46,11 +46,16 @@ Feature: All the possibilities of HTML parser
46
46
 
47
47
  Scenario: Block tag Λ
48
48
  Given we use "html" bowler
49
- When the input string is "Λ ruby @mapping[:block] = ≡bold≡ Λ"
49
+ When the input string is
50
+ """
51
+ Λ ruby
52
+ @mapping[:block] = ≡bold≡
53
+ Λ
54
+ """
50
55
  And the execute method is called on bowler
51
56
  Then the result should equal to
52
57
  """
53
-
58
+
54
59
  <pre class='ruby'>@mapping[:block] = ≡bold≡</pre>
55
60
  """
56
61
 
@@ -106,7 +111,7 @@ Feature: All the possibilities of HTML parser
106
111
  | "Wikipedia¹http://wikipedia.org" | "<p><a href='http://wikipedia.org'>Wikipedia</a></p>" |
107
112
  | "Wikipedia†Best knowledge base†" | "<p><abbr title='Best knowledge base'>Wikipedia</abbr></p>" |
108
113
  | "Inplace picture¹http://mudasobwa.ru/images/am.jpg goes here." | "<p><img class='inplace' alt='Inplace picture' src='http://mudasobwa.ru/images/am.jpg'/> goes here.</p>" |
109
- | "http://mudasobwa.ru/images/am.jpg Standalone picture" | " ␍ <figure> ␍ <img src='http://mudasobwa.ru/images/am.jpg'/> ␍ <figcaption> ␍ <p>Standalone picture</p> ␍ </figcaption> ␍ </figure> ␍ " |
114
+ | "http://mudasobwa.ru/images/am.jpg Standalone picture" | " ␍ <figure> ␍ <img src='http://mudasobwa.ru/images/am.jpg'/> ␍ <figcaption> ␍ <p>Standalone picture</p> ␍ </figcaption> ␍ </figure> ␍ " |
110
115
 
111
116
  Scenario Outline: Markdown atavisms ⇒ links
112
117
  Given we use "html" bowler
@@ -117,7 +122,7 @@ Feature: All the possibilities of HTML parser
117
122
  Examples:
118
123
  | input | output |
119
124
  | "Here ![Image](http://mudasobwa.ru/images/am.jpg) goes" | "<p>Here <img class='inplace' alt='Image' src='http://mudasobwa.ru/images/am.jpg'/> goes</p>" |
120
- | "![Figure](http://mudasobwa.ru/images/am.jpg)" | " ␍ <figure> ␍ <img src='http://mudasobwa.ru/images/am.jpg'/> ␍ <figcaption> ␍ <p>Figure</p> ␍ </figcaption> ␍ </figure> ␍ " |
125
+ | "![Figure](http://mudasobwa.ru/images/am.jpg)" | " ␍ <figure> ␍ <img src='http://mudasobwa.ru/images/am.jpg'/> ␍ <figcaption> ␍ <p>Figure</p> ␍ </figcaption> ␍ </figure> ␍ " |
121
126
  | "Here [Link](http://wikipedia.org/) goes" | "<p>Here <a href='http://wikipedia.org/'>Link</a> goes</p>" |
122
127
  | "Here *italic* goes" | "<p>Here <em>italic</em> goes</p>" |
123
128
  | "Here inplace*it*alic goes" | "<p>Here inplace<em>it</em>alic goes</p>" |
@@ -135,12 +140,12 @@ Feature: All the possibilities of HTML parser
135
140
 
136
141
  Examples:
137
142
  | input | output |
138
- | "List: • li1 • li2" | "<p>List:</p> <ul class='fancy'><li>li1 </li> <li>li2</li></ul>" |
139
- | "List: • li1  • nested 1  • nested 2 • li2" | "<p>List:</p> <ul class='fancy'><li>li1 </li> <ul class='fancy'><li>nested 1 </li> <li>nested 2 </li></ul> <li>li2</li></ul>" |
140
- | "Data: ▶ dt — dd ▶ dt — dd" | "<p>Data:</p> <dl> ␍ <dt>dt</dt> ␍ <dd>dd </dd> ␍ ␍ <dt>dt</dt> ␍ <dd>dd</dd> ␍ </dl>" |
143
+ | "List: • li1 • li2" | "<p>List:</p> <ul class='fancy'><li>li1</li> <li>li2</li></ul>" |
144
+ | "List: • li1  • nested 1  • nested 2 • li2" | "<p>List:</p> <ul class='fancy'><li>li1</li> <ul class='fancy'><li>nested 1</li> <li>nested 2</li></ul> <li>li2</li></ul>" |
145
+ | "Data: ▶ dt — dd ▶ dt — dd" | "<p>Data:</p> <dl> ␍ <dt>dt</dt> ␍ <dd>dd</dd> ␍ ␍ <dt>dt</dt> ␍ <dd>dd</dd> ␍ </dl>" |
141
146
  | "§1 Header" | "<h1>Header</h1>" |
142
147
  | "〉 Blockquote" | "<blockquote><p class='blockquote'>Blockquote</p></blockquote>" |
143
-
148
+
144
149
  Scenario Outline: Self tags
145
150
  Given we use "html" bowler
146
151
  When the input string is <input>
@@ -148,8 +153,12 @@ Feature: All the possibilities of HTML parser
148
153
  Then the result should equal to <output>
149
154
 
150
155
  Examples:
151
- | input | output |
152
- | "here qipowl goes" | "<p>here <strong>qipowl</strong> goes</p>" |
156
+ | input | output |
157
+ | "here qipowl goes" | "<p>here <strong><a href='http://qipowl.github.com'>qipowl</a></strong> goes</p>" |
158
+ | "here Qipowl goes" | "<p>here <strong><a href='http://Qipowl.github.com'>Qipowl</a></strong> goes</p>" |
159
+ | "here tag goes" | "<p>here <a href='/tags/tag'>tag</a> goes</p>" |
160
+ | "here tag2 goes" | "<p>here <b><a href='/tags/tag2'>tag2</a></b> goes</p>" |
161
+ | "here tag3 goes" | "<p>here <b><a href='/tags/tag3'>tag3</a></b> goes</p>" |
153
162
 
154
163
  Scenario: Address tag
155
164
  Given we use "html" bowler
@@ -162,7 +171,7 @@ Feature: All the possibilities of HTML parser
162
171
  When the input string is "List: × li1 line item × li2"
163
172
  And rule "×" is added to mapping as "li" in "regular" section with "ol" enclosure
164
173
  And the execute method is called on bowler
165
- Then the result should equal to "<p>List:</p> <ol><li>li1 line item </li> <li>li2</li></ol>"
174
+ Then the result should equal to "<p>List:</p> <ol><li>li1 line item</li> <li>li2</li></ol>"
166
175
 
167
176
  Scenario: Entity removal
168
177
  Given we use "html" bowler
@@ -178,19 +187,19 @@ Feature: All the possibilities of HTML parser
178
187
 
179
188
  Preamble: given
180
189
 
181
-
190
+
182
191
  〉 http://mudasobwa.ru/i/self.jpg With caption
183
192
  ‒ Wiki, http://wikipedia.ru
184
-
193
+
185
194
  Nice?
186
195
  """
187
196
  And the execute method is called on bowler
188
197
  Then the result should equal to
189
198
  """
190
-
191
-
199
+
200
+
192
201
  <blockquote><p class='blockquote'>http://mudasobwa.ru/i/self.jpg With caption
193
- <br/> <small><a href='http://wikipedia.ru'>Wiki</a></small> </p></blockquote>
202
+ <br/> <small><a href='http://wikipedia.ru'>Wiki</a></small></p></blockquote>
194
203
  <p>Nice?</p>
195
204
  """
196
205
 
@@ -201,13 +210,13 @@ Feature: All the possibilities of HTML parser
201
210
  ---
202
211
  This is a comment text
203
212
  ---
204
-
213
+
205
214
  Nice?
206
215
  """
207
216
  And the execute method is called on bowler
208
217
  Then the result should equal to
209
218
  """
210
-
219
+
211
220
  <p>Nice?</p>
212
221
  """
213
222
 
@@ -216,28 +225,28 @@ Feature: All the possibilities of HTML parser
216
225
  When the input string is
217
226
  """
218
227
  §2 Blockquotes
219
-
228
+
220
229
  〉 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere
221
230
  erat a ante.
222
231
     〉 Nested blockquote first line
223
232
   〉 Nested blockquote second line
224
233
  〉 Lorem ipsum para text 2.
225
-
234
+
226
235
  Some para text.
227
-
236
+
228
237
  〉 Intro 1.
229
238
   • list item ≡with bold≡ 1
230
-  • list item ≈emphasized≈
239
+  • list item ≈emphasized≈
231
240
    • nested list item 1
232
-   • nested list item 2
233
-
241
+   • nested list item 2
242
+
234
243
  〉 Blockquote standalone.
235
-
244
+
236
245
  〉 Intro 2.
237
-  • list item 2.1
246
+  • list item 2.1
238
247
   • list item 2.2
239
248
  〉 Continuing intro 2.
240
-
249
+
241
250
  Blockquote standalone.
242
251
  """
243
252
  And the execute method is called on bowler
@@ -245,3 +254,43 @@ Feature: All the possibilities of HTML parser
245
254
  And the result should match "</li> <ul class='fancy'><li>nested list item 1"
246
255
  And the result should match "<p>Blockquote standalone.</p>"
247
256
 
257
+ Scenario Outline: Postprocessing: spaces
258
+ Given we use "html" bowler
259
+ When the input string is <input>
260
+ And the execute method is called on bowler
261
+ Then the result should equal to <output>
262
+
263
+ Examples:
264
+ | input | output |
265
+ | "here «quote» goes" | "<p>here «quote» goes</p>" |
266
+ | "here « quote¹http://wikipedia.org » goes" | "<p>here «<a href='http://wikipedia.org'>quote</a>» goes</p>" |
267
+ | "This is λsystem.dllλ file." | "<p>This is <code>system.dll</code> file.</p>" |
268
+ | "This is ✓8:35✓ time." | "<p>This is <span class='notypo'>8:35</span> time.</p>" |
269
+
270
+ Scenario: Video embedded
271
+ Given we use "html" bowler
272
+ When the input string is
273
+ """
274
+ http://qipowl.herokuapp.com/images/owl.png
275
+
276
+ ☞ Video embedded:
277
+
278
+ http://www.youtube.com/watch?v=KFKxlYNfT_o
279
+ """
280
+ And the execute method is called on bowler
281
+ Then the result should equal to
282
+ """
283
+
284
+ <figure>
285
+ <img src='http://qipowl.herokuapp.com/images/owl.png'/>
286
+ <figcaption>
287
+ <p></p>
288
+ </figcaption>
289
+ </figure>
290
+
291
+ <p class='text-info'>Video embedded:</p>
292
+
293
+ <iframe class='youtube' width='560' height='315' src='http://www.youtube.com/embed/KFKxlYNfT_o'
294
+ frameborder='0' allowfullscreen></iframe>
295
+
296
+ """
@@ -1,10 +1,17 @@
1
1
  # encoding: utf-8
2
2
 
3
+ Given(/^nothing$/) do
4
+ end
5
+
3
6
  Given(/^we use "(.*?)" bowler$/) do |f|
4
7
  # @f = "config/bowlers/#{f}.yaml"
5
8
  @bowler = Qipowl::Ruler.new_bowler f
6
9
  end
7
10
 
11
+ Given(/^we use "(.*?)" bowler with additional map "(.*?)"$/) do |f, map|
12
+ @bowler = Qipowl::Ruler.new_bowler(f, additional_maps: map)
13
+ end
14
+
8
15
  When(/^the input string is "(.*?)"$/) do |input|
9
16
  @input = input
10
17
  end
@@ -25,6 +32,16 @@ When(/^rule "(.*?)" is removed from mapping$/) do |key|
25
32
  @bowler.remove_entity key
26
33
  end
27
34
 
35
+ When(/^we request param "(.*?)"$/) do |param|
36
+ @param_value = Qipowl["#{param}".to_sym]
37
+ end
38
+
39
+ When(/^we add additional bowler directory "(.*?)"$/) do |dir|
40
+ Qipowl::configure do
41
+ add :bowlers, dir
42
+ end
43
+ end
44
+
28
45
  Then(/^bowler has all the method aliases$/) do
29
46
  puts @bowler.class.instance_methods(false)
30
47
  puts '='*60
@@ -39,3 +56,6 @@ Then(/^the output is "(.*?)"$/) do |result|
39
56
  expect(@result).to eq(result)
40
57
  end
41
58
 
59
+ Then(/^param value ends with "(.*?)"$/) do |s|
60
+ expect("#{@param_value}").to match(/#{s}$/)
61
+ end
data/lib/qipowl.rb CHANGED
@@ -18,30 +18,40 @@ Encoding.default_internal = Encoding::UTF_8
18
18
  module Qipowl
19
19
  extend self
20
20
 
21
- # Basic single-method DSL with .parameter method
22
- # being used to define a set of available settings.
23
- # This method takes one or more symbols, with each one being
24
- # a name of the configuration option.
25
- def params *names
26
- names.each do |name|
27
- attr_accessor name
28
- define_method name do |*values|
29
- value = values.first
30
- value ? self.send("#{name}=", value) : instance_variable_get("@#{name}")
31
- end
32
- end
33
- end
34
-
35
21
  # A wrapper for the configuration block
36
- def config &block
22
+ def configure &block
37
23
  instance_eval(&block)
38
24
  end
39
25
 
26
+ def [](key)
27
+ config[key.to_sym]
28
+ end
29
+
30
+ private
31
+
32
+ def set(key, value)
33
+ config[key.to_sym] = value
34
+ end
35
+
36
+ def add(key, value)
37
+ config[key.to_sym] = [*config[key.to_sym]] << value
38
+ end
39
+
40
+ def config
41
+ @config ||= Hash.new
42
+ end
43
+
44
+ def method_missing(sym, *args)
45
+ if sym.to_s =~ /(.+)=$/
46
+ config[$1.to_sym] = args.first
47
+ else
48
+ config[sym.to_sym]
49
+ end
50
+ end
40
51
  end
41
52
 
42
- Qipowl::config do
43
- params :bowlers_dir
44
- bowlers_dir File.expand_path(File.join(__dir__, '..', 'config', 'bowlers'))
53
+ Qipowl::configure do
54
+ set :bowlers, File.expand_path(File.join(__dir__, '..', 'config', 'bowlers'))
45
55
  end
46
56
 
47
57
  class Qipowl::Html
@@ -49,4 +59,4 @@ class Qipowl::Html
49
59
  def self.parse s
50
60
  (@bowler ||= Qipowl::Ruler.new_bowler "html").execute s
51
61
  end
52
- end
62
+ end
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'net/http'
4
+ require 'base64'
4
5
  require 'typogrowth'
5
6
 
6
7
  require_relative '../core/bowler'
@@ -8,7 +9,7 @@ require_relative '../core/bowler'
8
9
  module Qipowl
9
10
  module Mappers
10
11
  class HtmlBowlerMapper < BowlerMapper
11
-
12
+
12
13
  end
13
14
  end
14
15
 
@@ -23,59 +24,80 @@ module Qipowl
23
24
  # @param [Array] args the words, gained since last call to {#harvest}
24
25
  # @return [Array] the array of words with trimmed `grip` tag
25
26
  def ∀_grip *args
27
+ data = ∃_grip(__callee__)
26
28
  mine, rest = [*args].join(SEPARATOR).split("#{__callee__}∎", 2)
27
- [tagify(∃_grip_tag(__callee__), {:class => ∃_grip(__callee__)[:class]}, mine), rest]
29
+ [tagify(data[:tag], {:class => data[:class]}, mine), rest]
28
30
  end
29
31
 
30
32
  # `:alone` default handler
31
33
  # @param [Array] args the words, gained since last call to {#harvest}
32
34
  # @return [Array] the array of words with prepended `alone` tag
33
35
  def ∀_alone *args
34
- [standalone(∃_alone_tag(__callee__), {:class => ∃_alone(__callee__)[:class]}), args]
36
+ data = ∃_alone(__callee__)
37
+ [standalone(data[:tag], {:class => data[:class]}), args]
35
38
  end
36
39
 
37
40
  # `:block` default handler
41
+ # FIXME TODO make an ability to supply class
38
42
  # @param [Array] args the words, gained since last call to {#harvest}
39
43
  # @param [String] param the text to be places on the same string as
40
44
  # opening tag
41
45
  # @return [Nil] nil
42
- def ∀_block *args
43
- param, *args = args.flatten
44
- param = param.to_s
45
- harvest __callee__,
46
+ def ∀_block arg
47
+ data = ∃_block(__callee__)
48
+ param, body = Base64.decode64(
49
+ "#{arg.to_s.unbowl.uncarriage(false)}"
50
+ ).force_encoding('UTF-8').split(/\n/, 2)
51
+ param, body = '', param if body.nil?
52
+ harvest __callee__,
46
53
  tagify(
47
- ∃_block_tag(__callee__),
48
- {:class => (param.strip.empty? ? ∃_block(__callee__)[:class] : param.strip)},
49
- args.join(SEPARATOR).hsub(String::HTML_ENTITIES)
54
+ data[:tag],
55
+ {:class => param.strip.empty? ? data[:class] : param.strip },
56
+ body.hsub(String::HTML_ENTITIES)
50
57
  )
51
58
  end
52
-
59
+
53
60
  # `:magnet` default handler
54
61
  # @param [Array] args the words, gained since last call to {#harvest}
55
62
  # @return [Array] the array of words with trimmed `magnet` tag
56
63
  def ∀_magnet *args
64
+ data = ∃_magnet(__callee__)
57
65
  param, *rest = args.flatten
58
66
  param = param.unbowl.to_s.prepend("#{__callee__}#{String::NBSP}")
59
- [tagify(∃_magnet_tag(__callee__), {:class => ∃_magnet(__callee__)[:class]}, param), rest]
67
+ [tagify(data[:tag], {:class => data[:class]}, param), rest]
60
68
  end
61
-
69
+
62
70
  # `:regular` default handler
63
71
  # @param [Array] args the words, gained since last call to {#harvest}
64
72
  def ∀_regular *args
65
- harvest __callee__,
66
- tagify(
67
- ∃_regular_tag(canonize(__callee__)),
68
- {:class => ∃_regular(canonize(__callee__))[:class]},
69
- args
70
- )
73
+ data = ∃_regular(canonize __callee__)
74
+ harvest __callee__, tagify(data[:tag], {:class => data[:class]}, args)
71
75
  end
72
-
76
+
73
77
  # `:self` default handler
74
78
  # @param [Array] args the words, gained since last call to {#harvest}
75
- def ∀_self *args
76
- [tagify(∃_self_tag(__callee__), {:class => ∃_self(__callee__)[:class]}, __callee__), args]
79
+ def ∀_self *args, &cb
80
+ data = ∃_self(__callee__)
81
+ cally = block_given? ? yield : __callee__
82
+ text = case data[:format]
83
+ when NilClass then cally
84
+ when String then cally.to_s.gsub(/(#{cally})/, data[:format])
85
+ # when Regexp then cally.to_s.gsub(cally.to_s, data[:format])
86
+ when Symbol then send(data[:format], cally) rescue cally # FIXME Do I need rescue here?!
87
+ else raise "Bad format specified for #{data[:tag]}"
88
+ end
89
+ [data[:tag] ? tagify(data[:tag], {:class => data[:class]}, text) : text, args]
90
+ end
91
+
92
+ ##############################################################################
93
+ ### Self :: Specific handlers ###
94
+ ##############################################################################
95
+ # Handler for tags.
96
+ # @param [String] arg the word to be processed
97
+ # @return [Array] the array of words with procesed tag
98
+ def tagger_format tag
99
+ "<a href='/tags/#{tag}'>#{tag}</a>"
77
100
  end
78
-
79
101
  ##############################################################################
80
102
  ### Grip :: Specific handlers ###
81
103
  ##############################################################################
@@ -83,28 +105,30 @@ module Qipowl
83
105
  # @param [Array] args the words, gained since last call to {#harvest}
84
106
  # @return [Array] the array of words with trimmed `abbr` tag
85
107
  def † *args
108
+ data = ∃_grip(__callee__)
86
109
  term, *title = args.flatten
87
110
  mine, rest = [*title].join(SEPARATOR).split("#{__callee__}∎", 2)
88
- [tagify(∃_grip_tag(__callee__), {:title => mine, :class => ∃_grip(__callee__)[:class]}, term), rest]
111
+ [tagify(data[:tag], {:title => mine, :class => data[:class]}, term), rest]
89
112
  end
90
113
 
91
114
  # Handler for anchors.
92
115
  # @param [Array] args the words, gained since last call to {#harvest}
93
116
  # @return [Array] the array of words with trimmed `a` tag
94
117
  def ⚓ *args
118
+ data = ∃_grip(__callee__)
95
119
  href, *title = args.flatten
96
120
  mine, rest = [*title].join(SEPARATOR).split("#{__callee__}∎", 2)
97
121
  href = href.unbowl
98
122
  [
99
123
  case get_href_content(href)
100
- when :img
124
+ when :img
101
125
  standalone :img, { :src => href, :alt => [*mine].join(SEPARATOR), :class => 'inplace' }
102
- else
103
- tagify ∃_grip_tag(__callee__), {:href => href}, mine
126
+ else
127
+ tagify data[:tag], {:href => href}, mine
104
128
  end, rest
105
129
  ]
106
130
  end
107
-
131
+
108
132
  ##############################################################################
109
133
  ### Alone :: Specific handlers ###
110
134
  ##############################################################################
@@ -114,7 +138,7 @@ module Qipowl
114
138
  # @return [Nil] nil
115
139
  def —— *args
116
140
  harvest nil, orphan(args.join(SEPARATOR)) unless args.vacant?
117
- harvest __callee__, standalone(∃_alone_tag(__callee__))
141
+ harvest __callee__, standalone(∃_alone(__callee__)[:tag])
118
142
  end
119
143
 
120
144
  ##############################################################################
@@ -142,12 +166,12 @@ module Qipowl
142
166
  ljref = "<span style='white-space: nowrap;'><a href='http://#{param}.livejournal.com/profile?mode=full'><img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' style='border: 0pt none ; vertical-align: bottom; padding-right: 1px;' height='17' width='17'></a><a href='http://#{param}.livejournal.com/?style=mine'><b>#{param}</b></a></span>"
143
167
  [ljref, rest]
144
168
  end
145
-
169
+
146
170
  def ☇ *args
147
171
  param, *rest = args.flatten
148
- [tagify(∃_magnet_tag(__callee__), {:name => param.unbowl}, String::ZERO_WIDTH_SPACE), rest]
172
+ [tagify(∃_magnet(__callee__)[:tag], {:name => param.unbowl}, String::ZERO_WIDTH_SPACE), rest]
149
173
  end
150
-
174
+
151
175
  ##############################################################################
152
176
  ### Regular :: Specific handlers ###
153
177
  ##############################################################################
@@ -158,25 +182,24 @@ module Qipowl
158
182
  id, *rest = args.flatten
159
183
  harvest nil, orphan(rest.join(SEPARATOR)) unless rest.vacant?
160
184
  harvest __callee__, %Q(
161
- <iframe class='youtube' width='560' height='315' src='http://www.youtube.com/embed/#{id.unbowl}'
185
+ <iframe class='youtube' width='560' height='315' src='http://www.youtube.com/embed/#{id.unbowl}'
162
186
  frameborder='0' allowfullscreen></iframe>
163
187
  )
164
188
  end
165
-
189
+
166
190
  # Handler for standalone pictures and
167
191
  # @todo Make it to understand quotes when there is a plain HTML on the other side
168
- #
169
- # @param
192
+ #
193
+ # @param
170
194
  # @return [Nil] nil
171
195
  def ⚘ *args
172
196
  href, *title = args.flatten
197
+ title = title.join(SEPARATOR).strip
173
198
  harvest __callee__, %Q(
174
199
  <figure>
175
200
  <img src='#{href.unbowl}'/>
176
201
  <figcaption>
177
- <p>
178
- #{title.join(SEPARATOR)}
179
- </p>
202
+ <p>#{title}</p>
180
203
  </figcaption>
181
204
  </figure>
182
205
  )
@@ -193,35 +216,61 @@ module Qipowl
193
216
  #{tagify :dd, {}, dd}
194
217
  )
195
218
  end
196
- # Alias for {#▶}, according to YAML rules specifies additional
219
+ # Alias for {#▶}, according to YAML rules specifies additional
197
220
  # class for the data list `<dl>` tag behind (`dl-horizontal`.)
198
221
  alias_method :▷, :▶
199
222
 
200
223
  protected
224
+ def shadows
225
+ @shadows ||= ([] \
226
+ << self.class::BLOCK_TAGS.keys.map {|b| /#{b}.*?#{b}/m } \
227
+ << self.class::CUSTOM_TAGS.keys.map {|re| /#{re}/m} \
228
+ << self.class::MAGNET_TAGS.keys.map {|m| /#{m}\s+\S+/} \
229
+ ).flatten
230
+ end
231
+
201
232
  # @see {Qipowl::Bowlers::Bowler#defreeze}
202
- #
233
+ #
203
234
  # @param [String] str to be defreezed
204
235
  def defreeze str
205
- (super str)
236
+ s = shadows
237
+ str.typo(sections: [:sequence, :quotes], shadows: s).defuse(shadows: s)
206
238
  end
207
239
 
240
+ def serveup str
241
+ s = [
242
+ /<pre.*?>.*?<\/pre>/m,
243
+ /<code.*?>.*?<\/code>/m
244
+ ]
245
+
246
+ str.gsub(/⌦./, '').gsub(/.⌫/, '').typo(
247
+ sections: [:punctuation, :orphans], shadows: s
248
+ )
249
+ end
250
+
251
+
208
252
  # Computes the level of the `:linewide` element by counting
209
253
  # preceeding non-breakable spaces. For instance, nested lists
210
254
  # are produced by appending `"\u{00A0}"` to the line item
211
- # DSL tag:
212
- #
255
+ # DSL tag:
256
+ #
213
257
  # li = "• li1 \u{00A0}• nested 1 \u{00A0}• nested 2 • li2"
214
- #
215
- # @param [Symbol|String] callee the DSL symbol to get the level information for.
216
- # @return [Integer] the level requested.
217
258
  #
218
- def level callee
219
- (callee = callee.to_s).gsub(/#{String::NBSP}/, '').empty? ?
220
- -1 : (0..callee.length-1).each { |i| break i if callee[i] != String::NBSP }
259
+ # @param [Symbol|String] cally the DSL symbol to get the level information for.
260
+ # @return [Integer] the level requested.
261
+ #
262
+ def level cally
263
+ (cally = cally.to_s).gsub(/#{String::NBSP}/, '').empty? ?
264
+ -1 : (0..cally.length-1).each { |i| break i if cally[i] != String::NBSP }
221
265
  end
222
-
223
- def canonize callee
224
- callee.to_s.gsub(/^#{String::NBSP}*/, '').to_sym if callee
266
+
267
+ def canonize cally
268
+ cally.to_s.gsub(/^#{String::NBSP}*/, '').to_sym if cally
269
+ end
270
+
271
+ def normalize cally
272
+ scally = cally.to_s.unbowl
273
+ scally.gsub(/\p{L}/, '').empty? ? scally.downcase.bowl.to_sym : cally
225
274
  end
226
275
 
227
276
  # Produces html paragraph tag (`<p>`) with no class.
@@ -233,70 +282,73 @@ module Qipowl
233
282
  end
234
283
 
235
284
  # @see Qipowl::Bowler#harvest
236
- #
285
+ #
237
286
  # Additionally it checks if there was a `:linewide` item, requiring
238
287
  # surrounding html element (like `<ul>` aroung several `<li>`s.)
239
- #
240
- # @param [Symbol] callee of method
288
+ #
289
+ # @param [Symbol] cally of method
241
290
  # @param [String] str to be harvested
242
- def harvest callee, str
243
- if callee.nil? || callee != @callee
244
- level(callee).downto(level(@callee) + 1) { |i|
291
+ def harvest cally, str
292
+ if cally.nil? || cally != @cally
293
+ level(cally).downto(level(@cally) + 1) { |i|
245
294
  str += i.␚ify
246
- } unless ∃_enclosures(canonize(callee)).nil?
247
-
248
- if prev = ∃_enclosures(canonize(@callee))
249
- level(@callee).downto(level(callee) + 1) { |i|
295
+ } unless ∃_enclosures(canonize cally).nil?
296
+
297
+ if prev = ∃_enclosures(canonize(@cally))
298
+ level(@cally).downto(level(cally) + 1) { |i|
250
299
  @yielded.last.sub!(/\A/, opening(prev[:tag], {:class => prev[:class]}))
251
300
  @yielded.each { |s| s.gsub!(/#{i.␚ify}/) { closing(prev[:tag]) } }
252
301
  }
253
302
  end
254
-
255
- @callee = callee
303
+
304
+ @cally = cally
256
305
  end
257
- super callee, str
306
+ super cally, str
258
307
  end
259
308
 
260
309
  private
261
- # Hence we cannot simply declare the DSL for it, we need to handle
310
+ # Hence we cannot simply declare the DSL for it, we need to handle
262
311
  # calls to all the _methods_, starting with those symbols.
263
- #
312
+ #
264
313
  # @param [Symbol] method as specified by caller (`method_missing`.)
265
314
  # @param [Array] args as specified by caller (`method_missing`.)
266
315
  # @param [Proc] block as specified by caller (`method_missing`.)
267
- #
316
+ #
268
317
  # @return [Array] the array of words
269
318
  def special_handler method, *args, &block
270
319
  # Sublevel markers, e.g. “ •” is level 2 line-item
271
- return [method, args].flatten \
272
- unless level(method) > 0 && self.class::REGULAR_TAGS.keys.include?(canonize(method))
273
-
274
- self.class.class_eval "alias_method :#{method}, :#{canonize(method)}"
275
- send method, args, block
320
+ if level(method) > 0 && self.class::REGULAR_TAGS.keys.include?(m = (canonize method))
321
+ self.class.class_eval "alias_method :#{method}, :#{m}"
322
+ send method, args, block
323
+ elsif self.class.instance_methods.include?(m = (normalize method))
324
+ send(m, args) { yield if block_given? ; method.to_s }
325
+ else
326
+ [method, args].flatten
327
+ end
276
328
  end
277
329
 
278
330
  # Constructs opening html tag for the input given.
279
- #
331
+ #
280
332
  # To construct `abbr` tag with `title` _Title_ and class _default_:
281
- #
333
+ #
282
334
  # opening :abbr, { :title=>'Title', :class=>'default' }
283
- #
335
+ #
284
336
  # @param [String] tag to produce opening tag string from.
285
- # @param [Hash] params to be put into opening tag as attributes.
337
+ # @param [Hash] params to be put into opening tag as attributes.
286
338
  # @return [String] opening tag for the input given.
287
339
  def opening tag, params={}
288
340
  attrs = params.inject("") { |m, el| m.prepend " #{el.first}='#{el.last}'" unless el.last.nil? ; m }
289
341
  "<#{tag}#{attrs}>"
290
342
  end
291
-
343
+
292
344
  # Constructs closing html tag for the input given.
293
- #
345
+ #
294
346
  # @param [String] tag to produce closing tag string from.
295
347
  # @return [String] opening tag for the input given.
296
348
  def closing tag
297
349
  "</#{tag}>"
298
350
  end
299
-
351
+
300
352
  # (see opening)
301
353
  # Acts most like an {#opening} method, but closes an element inplace
302
354
  # (used for `hr`, `br`, `img`).
@@ -305,14 +357,14 @@ module Qipowl
305
357
  end
306
358
  # Constructs valid tag for the input given, concatenating
307
359
  # opening and closing tags around the text passed in `args`.
308
- #
360
+ #
309
361
  # @param [String] tag to produce html tag string from.
310
- # @param [Hash] params to be put into opening tag as attributes.
311
- # @param [Array] args the words, to be tagged around.
362
+ # @param [Hash] params to be put into opening tag as attributes.
363
+ # @param [Array] args the words, to be tagged around.
312
364
  # @return [String] opening tag for the input given.
313
365
  def tagify tag, params, *args
314
366
  text = [*args].join(SEPARATOR)
315
- text.vacant? ? '' : "#{opening tag, params}#{text}#{closing tag}"
367
+ text.vacant? ? '' : "#{opening tag, params}#{text.strip}#{closing tag}"
316
368
  end
317
369
 
318
370
 
@@ -329,7 +381,7 @@ module Qipowl
329
381
  else
330
382
  :text
331
383
  end
332
-
384
+
333
385
  # uri = URI(href.to_s.unbowl)
334
386
  # Net::HTTP.start(uri.host, uri.port) do |http|
335
387
  # http.open_timeout = 1
@@ -353,17 +405,17 @@ module Qipowl
353
405
  end
354
406
  =begin
355
407
  # Markup processor for Html output.
356
- #
408
+ #
357
409
  # This class produces HTML from markup as Markdown does.
358
-
410
+
359
411
  # Amount of unnamed instances of the class (needed for new class name generation)
360
412
  @@inst_count = 0
361
-
362
-
413
+
414
+
363
415
  # `:handshake` default handler
364
416
  # @param [String] from packed as string operand “before”
365
417
  # @param [String] from packed as string operand “after”
366
- # @return
418
+ # @return
367
419
  def ∈ *args
368
420
  from, till, *rest = args.flatten
369
421
  tag = @mapping.handshake(__callee__)
@@ -371,13 +423,13 @@ end
371
423
  [tagify(tag, {}, "#{from.unbowl}#{__callee__}#{till.unbowl}".gsub(String::SYMBOL_FOR_SPACE, ' ')), rest]
372
424
  end
373
425
  alias_method :⊂, :∈
374
-
375
426
 
376
-
427
+
428
+
377
429
  # @see {Qipowl::Bowler#serveup}
378
430
  #
379
431
  # Additionally it beatifies the output HTML
380
- #
432
+ #
381
433
  # @param [String] str to be roasted
382
434
  def serveup str
383
435
  result = ''
@@ -402,11 +454,11 @@ end
402
454
  end
403
455
 
404
456
  if __FILE__ == $0
405
-
457
+
406
458
  i = 0
407
459
  Dir.glob("#{File.dirname(__FILE__)}/../../../data/octopress-site/source/_posts/**/*.owl").each {|f|
408
460
  puts "Processing ##{i += 1}: #{f}"
409
461
  Qipowl::Html.parse File.read(f)
410
462
  }
411
463
  end
412
- =end
464
+ =end