qipowl 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
- metadata.gz: 11832e5a92068dd4a814b706480c20aae99c3a30
4
- data.tar.gz: 01dc0566c1f58d83664dff49c923dc68d5b58eeb
3
+ metadata.gz: c656b2aa5f88eb634e30f0ae4c9f8a1dae18237d
4
+ data.tar.gz: 26b1185aedc158f4fcb660b807bf5691fea97570
5
5
  !binary "U0hBNTEy":
6
- metadata.gz: f4ee26556053853856c043979387e2fedd29901d0b199902bbff5bbd9ce0b37bfe5f5c3e819d77643655c811d8b2df42c2318ae4f7b4f536aea7e8452c39cefd
7
- data.tar.gz: eeac33cd357ad9c0c5ebf3785c4ecb4a98289ac5498c3291b1c19029ed3ab431d7a7befdd03741e1a32a12a3b594f291943c8cc76a75d61c97939e090864904a
6
+ metadata.gz: 78be05dbfaf7720127cb2da7db32c4b204f8f7146d69fc3749f330e0e95ec2ce5fa3d99451fc38aa38b3e041c3a41e10f3c99ea37238c4bc5c5180943bfcf4e6
7
+ data.tar.gz: 50e3187848e51d7aca086f5410ed23cf0f472bd40844e2b83101cf67c574c6267c483e53e31db4ac3ae6d37a82616cf3b6005cc9a13f9bdacd20d22e6534a89c
data/.travis.yml CHANGED
@@ -1,3 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
+ - 2.1.0
data/Gemfile CHANGED
@@ -3,7 +3,6 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in typogrowl.gemspec
4
4
  gemspec
5
5
 
6
- gem 'htmlbeautifier', :git => 'https://github.com/threedaymonk/htmlbeautifier'
7
6
  gem 'aquarium', '~> 0.6', :git => 'git://github.com/deanwampler/Aquarium.git'
8
7
  gem "crochets", :git => 'git://github.com/mudasobwa/crochets.git'
9
8
 
data/bin/bowler CHANGED
@@ -12,7 +12,7 @@ OptionParser.new do |opts|
12
12
 
13
13
  # Bowl result?
14
14
  opts.on("-a", "--action ACTION", [:bowl, :ruby, :cmd, :yaml, :html],
15
- "Action to apply on input (bowl, ruby, cmd, yaml, html); default: html") do |action|
15
+ "Action to apply on input (bowl, html); default: html") do |action|
16
16
  options[:action] = action || :bowl
17
17
  end
18
18
 
@@ -31,14 +31,6 @@ file_or_string = File.read(file_or_string) if File.exist?(file_or_string)
31
31
  case options[:action]
32
32
  when :bowl
33
33
  puts file_or_string.bowl
34
- when :ruby
35
- puts Qipowl::Mapping.new(nil, file_or_string).to_ruby
36
- when :html
37
- puts Qipowl::Html.parse file_or_string
38
- when :cmd
39
- puts Qipowl::Cmd.execute file_or_string
40
- when :yaml
41
- puts Qipowl::Yaml.parse file_or_string
42
34
  else
43
35
  puts Qipowl::Html.parse file_or_string
44
36
  end
@@ -74,18 +74,20 @@
74
74
  :tag : :p
75
75
  :class : :lead
76
76
  :☆ :
77
- :tag : :p
78
- :class : :text_muted
79
- :★ : :em
77
+ :tag : :span
78
+ :class : :'text-warning'
79
+ :★ :
80
+ :tag : :span
81
+ :class : :'label label-info'
80
82
  :☛ :
81
83
  :tag : :p
82
- :class : :text_success
84
+ :class : :'text-success'
83
85
  :☞ :
84
86
  :tag : :p
85
- :class : :text_info
87
+ :class : :'text-info'
86
88
  :☣ :
87
89
  :tag : :p
88
- :class : :text_warning
90
+ :class : :'text-warning'
89
91
  :☢ :
90
92
  :tag : :p
91
93
  :class : :text_danger
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ :entities :
4
+ :regular :
5
+ '.' : :dot
6
+ ',' : :comma
7
+ ':' : :colon
8
+ ';' : :semicolon
9
+ '¡' : :exclm_start
10
+ '!' : :exclm_end
11
+ '¿' : :quest_start
12
+ '?' : :quest_end
13
+
14
+ :custom :
15
+ '([.,:;?!])(?=\s|\Z)' : ' \1 '
16
+ '(?<=\s|\A)([¿¡])' : ' \1 '
data/extras/demo/main.rb CHANGED
@@ -4,31 +4,32 @@ require 'cgi'
4
4
  require 'json'
5
5
  require 'sinatra'
6
6
 
7
- require_relative '../qipowl'
7
+ require_relative '../../lib/qipowl'
8
8
 
9
9
  use Rack::Session::Pool, :expire_after => 2592000
10
10
 
11
11
  before do
12
- session[:typo] ||= Qipowl.tg_md__html
12
+ session[:typo] ||= Qipowl::Ruler.new_bowler "html"
13
+ session[:mapping] ||= session[:typo].class::ENTITIES.rmerge({:custom => session[:typo].class::CUSTOM_TAGS}).to_json
13
14
  end
14
15
 
15
16
  get '/html/mapping' do
16
17
  content_type :json
17
- session[:typo].mapping.hash.to_json
18
+ session[:mapping]
18
19
  end
19
20
 
20
21
  delete '/html/mapping/:key' do |key|
21
22
  content_type :json
22
- session[:typo].mapping.remove_spice(key.to_sym).to_json
23
+ session[:typo].remove_entity(key.to_sym).to_json
23
24
  end
24
25
 
25
26
  put '/html/mapping/:section/:key/:value/?:enclosure?' do |section, key, value, enclosure|
26
27
  content_type :json
27
- session[:typo].mapping.add_spice(section.to_sym, key.to_sym, value.to_sym, enclosure ? enclosure.to_sym : nil).to_json
28
+ session[:typo].add_entity(section.to_sym, key.to_sym, value.to_sym, enclosure ? enclosure.to_sym : nil).to_json
28
29
  end
29
30
 
30
31
  get '/html/parse' do
31
32
  str = CGI::parse(request.query_string)['text'].first
32
33
  content_type :html
33
- session[:typo].parse_and_roll str
34
+ session[:typo].execute str
34
35
  end
@@ -6,7 +6,7 @@
6
6
  <head>
7
7
  <meta charset="utf-8">
8
8
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9
- <title>Typogrowl for HTML</title>
9
+ <title>Qipowl for HTML</title>
10
10
  <meta name="description" content="">
11
11
  <meta name="viewport" content="width=device-width">
12
12
 
@@ -17,7 +17,7 @@
17
17
  padding-bottom: 20px;
18
18
  }
19
19
  table.mapping {
20
- font: 9px monospace;
20
+ font: 10px monospace;
21
21
  }
22
22
  table.mapping thead {
23
23
  font-size: 12px;
@@ -87,13 +87,12 @@
87
87
  ' <input class="form-control" id="mapping-new-enclosure" name="enclosure" placeholder="Enclosure">' +
88
88
  ' </div>' +
89
89
  ' <div class="form-group">' +
90
- ' <select class="form-control" id="mapping-new-section" name="section">' +
91
- ' <option>' + 'flush' + '</option>' +
90
+ ' <select class="form-control" id="mapping-new-section" name="section">' +
92
91
  ' <option>' + 'block' + '</option>' +
92
+ ' <option>' + 'alone' + '</option>' +
93
93
  ' <option>' + 'magnet' + '</option>' +
94
- ' <option>' + 'inplace' + '</option>' +
95
- ' <option>' + 'linewide' + '</option>' +
96
- ' <option>' + 'custom' + '</option>' +
94
+ ' <option>' + 'grip' + '</option>' +
95
+ ' <option>' + 'regular' + '</option>' +
97
96
  ' </select>' +
98
97
  ' </div>' +
99
98
  ' <div class="form-group">' +
@@ -153,11 +152,11 @@
153
152
  <span class="icon-bar"></span>
154
153
  <span class="icon-bar"></span>
155
154
  </button>
156
- <a class="navbar-brand" href="index.html">Typogrowl Demo</a>
155
+ <a class="navbar-brand" href="index.html">Qipowl Demo</a>
157
156
  </div>
158
157
  <div class="navbar-collapse collapse">
159
158
  <ul class="nav navbar-nav">
160
- <li><a href="http://github.com/mudasobwa/typogrowl">Source</a></li>
159
+ <li><a href="http://github.com/mudasobwa/qipowl">Source</a></li>
161
160
  <li class="active"><a href="#">HTML</a></li>
162
161
  <!--li class="dropdown">
163
162
  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
@@ -197,9 +196,10 @@
197
196
  <textarea style="margin-bottom:0.2em;" type="text" rows="21" id="text" name="text" class="form-control">
198
197
  §1 Welcome!
199
198
 
200
- Typogrowl ≈helps≈ you to ≡format rich≡ using plain text. This para is, for instance, the leading one in terms of bootstrap ( `class='lead'`).
199
+ Qipowl ≈helps≈ you to ≡format rich≡ using plain text. This para is, for instance,
200
+ has “leading para” bootstrap class ( `class='lead'`).
201
201
 
202
- This is a text with typogrowl markup.
202
+ This is a plain para with slight ≡qipowl≡ markup.
203
203
 
204
204
  • unbulleted lists:
205
205
   • nice
@@ -208,8 +208,8 @@ Typogrowl ≈helps≈ you to ≡format rich≡ using plain text. This para is, f
208
208
 
209
209
  ★ Feel free to test:
210
210
  ▷ bulleted lists — with “•” symbol
211
- ▷ data lists — with “▶”
212
- ▷ blockquotes — with “〉” and nesteds
211
+ ▷ data lists — with “▶”
212
+ ▷ blockquotes — with “〉” and nesteds
213
213
  ▷ links — with “ ¹” and other human readables
214
214
 
215
215
  §3 Even bootstrap classes are available:
@@ -221,9 +221,16 @@ Typogrowl ≈helps≈ you to ≡format rich≡ using plain text. This para is, f
221
221
  • “☣” for “warning” text
222
222
  • “☢” for “danger” text
223
223
 
224
-
224
+
225
225
  Comments are visible in HTML source only
226
-
226
+
227
+
228
+ Λ ruby
229
+ # Source code snippet
230
+ void main() {
231
+ exit("Hello, World!");
232
+ }
233
+ Λ
227
234
 
228
235
  Hope you’ll enjoy!
229
236
  </textarea>
@@ -6,7 +6,7 @@
6
6
  <head>
7
7
  <meta charset="utf-8">
8
8
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9
- <title>Typogrowl Demo</title>
9
+ <title>Qipowl Demo</title>
10
10
  <meta name="description" content="">
11
11
  <meta name="viewport" content="width=device-width">
12
12
 
@@ -34,11 +34,11 @@
34
34
  <span class="icon-bar"></span>
35
35
  <span class="icon-bar"></span>
36
36
  </button>
37
- <a class="navbar-brand" href="index.html">Typogrowl Demo</a>
37
+ <a class="navbar-brand" href="index.html">Qipowl Demo</a>
38
38
  </div>
39
39
  <nav class="navbar-collapse collapse">
40
40
  <ul class="nav navbar-nav">
41
- <li><a href="http://github.com/mudasobwa/typogrowl">Source</a></li>
41
+ <li><a href="http://github.com/mudasobwa/qipowl">Source</a></li>
42
42
  <li><a href="html.html">HTML</a></li>
43
43
  <!--li class="dropdown">
44
44
  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
@@ -69,12 +69,12 @@
69
69
  <!-- Main jumbotron for a primary marketing message or call to action -->
70
70
  <div class="jumbotron">
71
71
  <div class="container">
72
- <h1>Typogrowl rules</h1>
73
- <p><em>Typogrowl</em> is the next generation markup environment. It’s not the
72
+ <h1>Qipowl rules</h1>
73
+ <p><em>Qipowl</em> is the next generation markup environment. It’s not the
74
74
  markup language only, since it provides the very efficient and straightforward
75
75
  library to produce custom markups. It′s not the markup library either,
76
76
  since it comes with ready-to-use markdown-like markup and 2HTML converter.</p>
77
- <p><a class="btn btn-primary btn-lg" href="https://github.com/mudasobwa/typogrowl#usage">Learn more &raquo;</a></p>
77
+ <p><a class="btn btn-primary btn-lg" href="https://github.com/mudasobwa/qipowl#usage">Learn more &raquo;</a></p>
78
78
  </div>
79
79
  </div>
80
80
 
@@ -23,6 +23,15 @@ Feature: All the possibilities of HTML parser
23
23
  | "here λ≡code bold≡λ goes" | "<p>here <code><strong>code bold</strong></code> goes</p>" |
24
24
  | "Hello, ≈World≈!" | "<p>Hello, <em>World</em>!</p>" |
25
25
 
26
+ Scenario Outline: Inplace tags nested
27
+ Given we use "html" bowler
28
+ When the input string is <input>
29
+ And the execute method is called on bowler
30
+ Then the result should NOT equal to <output>
31
+
32
+ Examples:
33
+ | input | output |
34
+ | "here ≡nested ≡bold≡ tags≡ go" | "<p>here <strong>nested <strong>bold</strong> tags</strong> goes</p>" |
26
35
 
27
36
  Scenario Outline: Alone tags
28
37
  Given we use "html" bowler
@@ -42,7 +51,7 @@ Feature: All the possibilities of HTML parser
42
51
  Then the result should equal to
43
52
  """
44
53
 
45
- <pre class='ruby'>@mapping[:block] = ≡bold≡ </pre>
54
+ <pre class='ruby'>@mapping[:block] = ≡bold≡</pre>
46
55
  """
47
56
 
48
57
  Scenario: Block tag ✍
@@ -189,7 +198,6 @@ Feature: All the possibilities of HTML parser
189
198
  Then the result should equal to
190
199
  """
191
200
 
192
-
193
201
  <p>Nice?</p>
194
202
  """
195
203
 
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ Feature: Text must be properly translated with Ispru
4
+
5
+ Scenario Outline: Russian language
6
+ Given we use "ispru" bowler
7
+ When the input string is <input>
8
+ And the execute method is called on bowler
9
+ Then the result should equal to <output>
10
+
11
+ Examples:
12
+ | input | output |
13
+ | "Он сказал: 'Поехали!'." | "Он сказал: «Поехали!»." |
14
+ | "Ссылка: http://wikipedia.org не покорежена." | "Ссылка: http://wikipedia.org не покорежена." |
15
+ | "Mamá lavados marco." | "Мама моет раму." |
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ Feature: String improvements
4
+
5
+ Scenario: I18n of up-/down-case and capitalize
6
+ Given input string is "мама"
7
+ When I call upcase on it
8
+ Then the result should equal to "МАМА"
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  Given(/^we use "(.*?)" bowler$/) do |f|
2
4
  # @f = "config/bowlers/#{f}.yaml"
3
5
  @bowler = Qipowl::Ruler.new_bowler f
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  Then(/^the result should equal to "(.*?)"$/) do |result|
2
4
  expect(@result.carriage).to eq(result)
3
5
  end
@@ -9,3 +11,7 @@ end
9
11
  Then(/^the result should match "(.*?)"$/) do |result|
10
12
  expect(@result).to match(result)
11
13
  end
14
+
15
+ Then(/^the result should NOT equal to "(.*?)"$/) do |result|
16
+ expect(@result.carriage).not_to eq(result)
17
+ end
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ Given(/^input string is "(.*?)"$/) do |s|
4
+ @input = s
5
+ end
6
+
7
+ When(/^I call upcase on it$/) do
8
+ @result = @input.upcase
9
+ end
@@ -1,12 +1,16 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'net/http'
4
- require 'htmlbeautifier'
5
4
 
6
5
  require_relative '../core/bowler'
7
- require_relative '../bowlers/htmldoc'
8
6
 
9
7
  module Qipowl
8
+ module Mappers
9
+ class HtmlBowlerMapper < BowlerMapper
10
+
11
+ end
12
+ end
13
+
10
14
  # Module placeholder for dynamically created bowlers
11
15
  module Bowlers
12
16
  class Html < Bowler
@@ -18,8 +22,7 @@ module Qipowl
18
22
  # @param [Array] args the words, gained since last call to {#harvest}
19
23
  # @return [Array] the array of words with trimmed `grip` tag
20
24
  def ∀_grip *args
21
- text = [*args].join(SEPARATOR)
22
- mine, rest = text.split("#{__callee__}∎", 2)
25
+ mine, rest = [*args].join(SEPARATOR).split("#{__callee__}∎", 2)
23
26
  [tagify(∃_grip_tag(__callee__), {:class => ∃_grip(__callee__)[:class]}, mine), rest]
24
27
  end
25
28
 
@@ -35,12 +38,14 @@ module Qipowl
35
38
  # @param [String] param the text to be places on the same string as
36
39
  # opening tag
37
40
  # @return [Nil] nil
38
- def ∀_block param, args
41
+ def ∀_block *args
42
+ param, *args = args.flatten
43
+ param = param.to_s
39
44
  harvest __callee__,
40
45
  tagify(
41
46
  ∃_block_tag(__callee__),
42
47
  {:class => (param.strip.empty? ? ∃_block(__callee__)[:class] : param.strip)},
43
- args.hsub(String::HTML_ENTITIES)
48
+ args.join(SEPARATOR).hsub(String::HTML_ENTITIES)
44
49
  )
45
50
  end
46
51
 
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+
3
+ # КТО ЧТО_ДЕЛАЕТ КОМУ ЧТО
4
+ # ☺ ⚙ ♿ ☕
5
+
6
+ # КАКОЙ КАК КАКОЙ КАКОЙ
7
+ # ☼ ☂ ☼ ☼
8
+
9
+ # ПОКА НЕ ОПРЕДЕЛЕНА ЧАСТЬ РЕЧИ (найти термин для)
10
+ # ∈
11
+
12
+ # МАРКЕРЫ ДЛЯ ПАДЕЖЕЙ, ВРЕМЕН, [ДЕЕ]ПРИЧАСТИЙ ИТД.
13
+ # например: глагол_наст.вр_деепричастие — «сетуя»
14
+
15
+ require 'typogrowth'
16
+
17
+ require_relative '../core/bowler'
18
+
19
+ module Qipowl
20
+ module Mappers
21
+ class IspruBowlerMapper < BowlerMapper
22
+
23
+ end
24
+ end
25
+
26
+ module Bowlers
27
+ class Ispru < Bowler
28
+
29
+ attr_reader :dict
30
+
31
+ LANG_FROM = 'es' # FIXME UGLY
32
+ LANG_TO = 'ru' # FIXME UGLY
33
+
34
+ ##############################################################################
35
+ ### Default handlers for all the types of markup ###
36
+ ##############################################################################
37
+
38
+ # `:regular` default handler
39
+ # @param [Array] args the words, gained since last call to {#harvest}
40
+ def ∀_regular *args
41
+ ["#{__callee__}", [*args].flatten]
42
+ end
43
+
44
+ # Drum-roll!! The main handler for words
45
+ def ∀_word method, *args, &block
46
+ [(@dict[method.to_s.unbowl] || method).bowl, args]
47
+ end
48
+
49
+ =begin
50
+ def . *args
51
+ end
52
+ def , *args
53
+ end
54
+ def ; *args
55
+ end
56
+ def ! *args
57
+ end
58
+ def ? *args
59
+ end
60
+ def ! *args
61
+ [__callee__, args]
62
+ end
63
+ def : *args
64
+ [__callee__, args]
65
+ end
66
+ =end
67
+ protected
68
+ def defreeze str
69
+ @dict = {'Mamá' => 'Мама', 'lavados' => 'моет', 'marco' => 'раму'}
70
+ (super str) # .typo(LANG_FROM)
71
+ end
72
+
73
+ # @see {Qipowl::Bowler#serveup}
74
+ #
75
+ # Additionally it beatifies the output HTML
76
+ #
77
+ # @param [String] str to be roasted
78
+ def serveup str
79
+ (super str).typo(LANG_TO).strip
80
+ end
81
+
82
+ private
83
+ # Hence we cannot simply declare the DSL for it, we need to handle
84
+ # calls to all the _methods_, starting with those symbols.
85
+ #
86
+ # @param [Symbol] method as specified by caller (`method_missing`.)
87
+ # @param [Array] args as specified by caller (`method_missing`.)
88
+ # @param [Proc] block as specified by caller (`method_missing`.)
89
+ #
90
+ # @return [Array] the array of words
91
+ def special_handler method, *args, &block
92
+ ∀_word method, args, block
93
+ end
94
+ end
95
+ end
96
+ end
@@ -46,7 +46,7 @@ module Qipowl::Bowlers
46
46
  # Everything is a DSL, remember?
47
47
  #
48
48
  # @return true
49
- def respond_to?(method)
49
+ def respond_to? method, incl_priv = false
50
50
  true
51
51
  end
52
52
 
@@ -68,7 +68,7 @@ module Qipowl::Bowlers
68
68
  if self.private_methods.include?(:special_handler)
69
69
  [method, args].flatten
70
70
  end
71
-
71
+
72
72
  # Adds new +entity+ in the section specified.
73
73
  # E. g., call to
74
74
  #
@@ -125,7 +125,7 @@ module Qipowl::Bowlers
125
125
  %w(block alone magnet grip regular).each { |section|
126
126
  define_method "∀_#{section}".to_sym, ->(*args) {
127
127
  raise "Default method for #{section} (“#{self.class.name.gsub(/_\d+\Z/, '')}#∀_#{section}”) MUST be defined"
128
- }
128
+ } unless Bowler.instance_methods(true).include?("∀_#{section}".to_sym)
129
129
  }
130
130
 
131
131
  def defreeze str
@@ -133,14 +133,14 @@ module Qipowl::Bowlers
133
133
  end
134
134
 
135
135
  def roast str
136
- (split str).reverse.map { |dish|
136
+ (split str).map { |dish|
137
137
  @yielded = []
138
138
  rest = begin
139
- eval(dish.strip.carriage)
139
+ eval(dish.bowl.carriage)
140
140
  rescue Exception => e
141
141
  msg = e.message.dup
142
142
  logger.error '='*78
143
- logger.error "Could not roast dish [#{msg.force_encoding(Encoding::UTF_8)}].\nWill return as is… Dish follows:"
143
+ logger.error "Could not roast dish [#{msg.force_encoding(Encoding::UTF_8)}].\nWill return as is… Dish follows:\n\n"
144
144
  logger.error '-'*78
145
145
  logger.error dish
146
146
  logger.error '='*78
@@ -148,7 +148,7 @@ module Qipowl::Bowlers
148
148
  end
149
149
  harvest(nil, orphan([*rest].join(SEPARATOR))) # FIXME Check if this is correct in all the cases
150
150
  @yielded.pop(@yielded.size).reverse.join(SEPARATOR)
151
- }.reverse.join($/).uncarriage.un␚ify.unspacefy.unbowl
151
+ }.join($/).uncarriage.un␚ify.unspacefy.unbowl
152
152
  end
153
153
 
154
154
  def serveup str
@@ -204,12 +204,13 @@ module Qipowl::Bowlers
204
204
  private
205
205
  # Prepares blocks in the input for the execution
206
206
  def block str
207
+ return str unless self.class.const_defined?(:BLOCK_TAGS)
207
208
  result = str.dup
208
209
  self.class::BLOCK_TAGS.each { |tag, value|
209
- result.gsub!(/(#{tag})\s*(\S*\s*|$)(.*?)(#{tag}|\Z)/m) {
210
+ result.gsub!(/(#{tag})\s*(\S*\s?|$)(.*?)(#{tag}|\Z)/m) {
210
211
  %Q{
211
212
 
212
- #{$1}('#{$2.strip}', '#{$3.carriage}')
213
+ #{$1} #{$2.strip.bowl} #{$3.bowl.carriage}
213
214
 
214
215
  }
215
216
  }
@@ -219,17 +220,19 @@ module Qipowl::Bowlers
219
220
 
220
221
  # Prepares customs in the input for the execution
221
222
  def custom str
222
- result = str.unbowl.dup
223
+ return str unless self.class.const_defined?(:CUSTOM_TAGS)
224
+ result = str.dup
223
225
  self.class::CUSTOM_TAGS.each { |tag, value|
224
- result.gsub!(/#{tag}/, value)
226
+ result.gsub!(/#{tag}/m, value)
225
227
  }
226
- result.bowl
228
+ result
227
229
  end
228
230
 
229
231
  # Prepares grips in the input for the execution
230
232
  # FIX<E There is a problem: we append a trailing space, need to remove it later!!
231
233
  def grip str
232
- result = str.dup
234
+ return str unless self.class.const_defined?(:GRIP_TAGS)
235
+ result = str.bowl
233
236
  self.class::GRIP_TAGS.each { |tag, value|
234
237
  result.gsub!(/(?:#{tag})(.*?)(?:#{tag})/m) {
235
238
  next if (args = $1).vacant?
@@ -237,12 +240,13 @@ module Qipowl::Bowlers
237
240
  "⌦ #{tag} #{args}#{tag}∎⌫"
238
241
  }
239
242
  }
240
- result
243
+ result.unbowl
241
244
  end
242
245
 
243
246
  def split str
244
- (block str.bowl).split(/\R{2,}/).map { |para|
245
- para =~ /\A(#{self.class::BLOCK_TAGS.keys.join('|')})\(/ ?
247
+ (block str).split(/\R{2,}/).map { |para|
248
+ self.class.const_defined?(:BLOCK_TAGS) &&
249
+ (para =~ /\A(#{self.class::BLOCK_TAGS.keys.join('|')})\s+/) ?
246
250
  para : (grip custom para)
247
251
  }
248
252
  end
@@ -37,7 +37,7 @@ module Qipowl::Mappers
37
37
  @hash.rmerge!(input.to_hash)
38
38
  incs.each { |inc|
39
39
  merge! inc
40
- } rescue NoMethodError
40
+ } rescue NoMethodError # FIXME WTF rescueing here?
41
41
  end
42
42
  private
43
43
  # FIXME Make file search more flexible!!!
@@ -49,6 +49,8 @@ module Qipowl::Mappers
49
49
  end
50
50
 
51
51
  class BowlerMapper < Mapper
52
+ include TypoLogging
53
+
52
54
  def initialize input = nil
53
55
  input = self.class.name.split('::').last.downcase.gsub(/bowlermapper\Z/, '') if input.nil?
54
56
  super input
@@ -57,7 +59,7 @@ module Qipowl::Mappers
57
59
  @entities_dirty = true
58
60
 
59
61
  def entities
60
- return @entities unless @entities_dirty
62
+ return @entities unless @entities_dirty && @hash[:entities]
61
63
  @entities = {}
62
64
  @hash[:entities].each { |key, value| # :block. :alone etc
63
65
  @entities[key] ||= {}
@@ -78,10 +80,6 @@ module Qipowl::Mappers
78
80
  @entities
79
81
  end
80
82
  end
81
-
82
- class HtmlBowlerMapper < BowlerMapper
83
-
84
- end
85
83
  end
86
84
 
87
85
  if __FILE__ == $0
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require_relative '../utils/unicode_strings'
3
4
  require_relative '../utils/hash_recursive_merge'
4
5
 
5
6
  module Qipowl
@@ -114,11 +115,11 @@ module Qipowl
114
115
  self.gsub!(/\R/, " #{CARRIAGE_RETURN} ")
115
116
  end
116
117
  def uncarriage
117
- self.gsub(/ #{CARRIAGE_RETURN} /, %Q(
118
+ self.gsub(/\s?#{CARRIAGE_RETURN}\s?/, %Q(
118
119
  ))
119
120
  end
120
121
  def uncarriage!
121
- self.gsub!(/ #{CARRIAGE_RETURN} /, %Q(
122
+ self.gsub!(/\s?#{CARRIAGE_RETURN}\s?/, %Q(
122
123
  ))
123
124
  end
124
125
 
@@ -57,9 +57,12 @@ module Qipowl
57
57
 
58
58
  @@yamls[yaml] = clazz.new
59
59
  end
60
+
61
+ # FIXME Make contants PER-EIGENCLASS
60
62
  def teach_class clazz, mapper
61
63
  clazz.const_set("CUSTOM_TAGS", mapper.to_hash[:custom])
62
64
  clazz.const_set("ENCLOSURES_TAGS", mapper.to_hash[:enclosures])
65
+ clazz.const_set("ENTITIES", mapper.entities)
63
66
  clazz.const_set("TAGS", {})
64
67
  clazz.class_eval %Q{
65
68
  def ∃_enclosures entity
@@ -73,9 +76,10 @@ module Qipowl
73
76
  end
74
77
  }
75
78
  %w(block alone magnet grip regular).each { |section|
79
+ next unless mapper.entities && mapper.entities[section.to_sym]
76
80
  clazz.const_set("#{section.upcase}_TAGS", mapper.entities[section.to_sym])
77
81
  clazz.class_eval %Q{
78
- #{clazz}::TAGS.rmerge! #{clazz}::#{section.upcase}_TAGS
82
+ self::TAGS.rmerge! self::#{section.upcase}_TAGS
79
83
  def ∃_#{section} entity
80
84
  self.class::#{section.upcase}_TAGS.each { |k, v|
81
85
  next unless k == entity
@@ -93,7 +97,7 @@ module Qipowl
93
97
  tag = Hash === value && value[:marker] ? value[:marker] : "∀_#{section}"
94
98
  clazz.class_eval %Q{
95
99
  alias_method :#{key}, :#{tag}
96
- } unless clazz.instance_methods.include?(key)
100
+ } unless clazz.instance_methods.include?(key.to_sym)
97
101
  }
98
102
  }
99
103
  clazz.class_eval %Q{
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ if 'мама'.upcase != 'МАМА'
4
+ require 'unicode'
5
+ class ::String
6
+ def downcase
7
+ Unicode::downcase(self)
8
+ end
9
+ def downcase!
10
+ self.replace downcase
11
+ end
12
+ def upcase
13
+ Unicode::upcase(self)
14
+ end
15
+ def upcase!
16
+ self.replace upcase
17
+ end
18
+ def capitalize
19
+ Unicode::capitalize(self)
20
+ end
21
+ def capitalize!
22
+ self.replace capitalize
23
+ end
24
+ end
25
+ end
26
+
@@ -1,3 +1,3 @@
1
1
  module Qipowl
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.1"
3
3
  end
data/lib/qipowl.rb CHANGED
@@ -4,7 +4,9 @@ require_relative "qipowl/version"
4
4
  require_relative "qipowl/core/mapper"
5
5
  require_relative "qipowl/core/ruler"
6
6
  require_relative "qipowl/core/bowler"
7
+
7
8
  require_relative "qipowl/bowlers/html"
9
+ require_relative "qipowl/bowlers/i_sp_ru"
8
10
  #require_relative "qipowl/bowlers/cmd"
9
11
  #require_relative "qipowl/bowlers/yaml"
10
12
 
@@ -33,18 +35,16 @@ module Qipowl
33
35
  instance_eval(&block)
34
36
  end
35
37
 
36
- def self.tg__html
37
- Html.new
38
- end
39
-
40
- def self.tg_md__html
41
- result = tg__html
42
- result.merge_rules "#{File.dirname(__FILE__)}/tagmaps/markdown2html.yaml"
43
- result
44
- end
45
38
  end
46
39
 
47
40
  Qipowl::config do
48
41
  params :bowlers_dir
49
42
  bowlers_dir File.expand_path(File.join(__dir__, '..', 'config', 'bowlers'))
43
+ end
44
+
45
+ class Qipowl::Html
46
+ attr_reader :bowler
47
+ def self.parse s
48
+ (@bowler ||= Qipowl::Ruler.new_bowler "html").execute s
49
+ end
50
50
  end
data/qipowl.gemspec CHANGED
@@ -34,8 +34,8 @@ Gem::Specification.new do |s|
34
34
  s.add_development_dependency 'yard-cucumber'
35
35
 
36
36
  s.add_dependency 'psych'
37
- s.add_dependency 'nokogiri'
38
- s.add_dependency 'htmlbeautifier'
37
+ s.add_dependency 'unicode'
38
+ s.add_dependency 'typogrowth'
39
39
  s.add_dependency 'aquarium'
40
40
  s.add_dependency 'crochets'
41
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qipowl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexei Matyushkin
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: nokogiri
98
+ name: unicode
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: htmlbeautifier
112
+ name: typogrowth
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ! '>='
@@ -172,6 +172,7 @@ files:
172
172
  - config/bowlers/cmd.yaml
173
173
  - config/bowlers/html.yaml
174
174
  - config/bowlers/html_supplemental.yaml
175
+ - config/bowlers/ispru.yaml
175
176
  - config/bowlers/markdown2html.yaml
176
177
  - extras/demo/main.rb
177
178
  - extras/demo/public/apple-touch-icon-114x114-precomposed.png
@@ -201,8 +202,12 @@ files:
201
202
  - extras/support/typo
202
203
  - features/bowler.feature
203
204
  - features/html.feature
205
+ - features/ispru.feature
206
+ - features/monkey.feature
204
207
  - features/step_definitions/bowler_steps.rb
205
208
  - features/step_definitions/html_steps.rb
209
+ - features/step_definitions/ispru_steps.rb
210
+ - features/step_definitions/monkey_steps.rb
206
211
  - features/support/env.rb
207
212
  - images/owl-old.png
208
213
  - images/owl-old.xcf
@@ -211,7 +216,7 @@ files:
211
216
  - lib/qipowl.rb
212
217
  - lib/qipowl/bowlers/cmd.rb
213
218
  - lib/qipowl/bowlers/html.rb
214
- - lib/qipowl/bowlers/htmldoc.rb
219
+ - lib/qipowl/bowlers/i_sp_ru.rb
215
220
  - lib/qipowl/bowlers/yaml.rb
216
221
  - lib/qipowl/core/bowler.rb
217
222
  - lib/qipowl/core/mapper.rb
@@ -219,6 +224,7 @@ files:
219
224
  - lib/qipowl/core/ruler.rb
220
225
  - lib/qipowl/utils/hash_recursive_merge.rb
221
226
  - lib/qipowl/utils/logging.rb
227
+ - lib/qipowl/utils/unicode_strings.rb
222
228
  - lib/qipowl/version.rb
223
229
  - qipowl.gemspec
224
230
  - qipowl.komodoproject
@@ -1,268 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'nokogiri'
4
- require 'fileutils'
5
- require 'yaml'
6
- require_relative '../core/monkeypatches.rb'
7
- require_relative '../utils/hash_recursive_merge.rb'
8
-
9
- module Qipowl
10
-
11
- class HtmlDoc < Nokogiri::XML::SAX::Document
12
- attr_reader :qp, :tags
13
- def initialize mapping
14
- @mapping = mapping
15
- @inside = nil
16
- @collector = {}
17
- @tags = {:inplace => {}, :linewide => {}}
18
- @qp = ''
19
- @level = 0
20
- end
21
-
22
- def start_element name, attributes = []
23
- current_attrs = Hash[attributes]
24
-
25
- @qp += case name.to_sym
26
- when :p, :div
27
- if current_attrs['class']
28
- @collector[name.to_sym] = "✿_#{name.to_sym}_#{current_attrs['class'].gsub(/\s+/, '_')}".to_sym
29
- @tags[:linewide][@collector[name.to_sym]] = "#{name.to_sym}†#{current_attrs['class'].gsub(/\s+/, '†')}".to_sym
30
- "\n\n#{@collector[name.to_sym]} "
31
- else
32
- "\n\n"
33
- end
34
- when :ul, :ol, :table, :dl
35
- @inside = name.to_sym
36
- "\n"
37
- when :pre then "\n\nΛ\n"
38
- when :tr then " ┇ "
39
- when :td then " ┆ "
40
- when :a
41
- @inside = :a
42
- @collector[:href] = current_attrs['href']
43
- @collector[:name] = current_attrs['name']
44
- ''
45
- when :li then (@inside == :ol) ? "◦ " : "• "
46
- when :b, :strong then "≡"
47
- when :i, :em, :nobr then "≈"
48
- when :strike, :del, :s then "─"
49
- when :small then "↓"
50
- when :u then "▁"
51
- when :code, :tt then "λ"
52
- when :dfn, :abbr, :cite
53
- @inside = name.to_sym
54
- @collector[:title] = current_attrs['title']
55
- when :hr then "\n\n——\n\n"
56
- when :br then " ⏎\n"
57
- when :center then "\n— "
58
- when :dt then "▷ "
59
- when :dd then " — "
60
- when :h1 then "§1 "
61
- when :h2 then "§2 "
62
- when :h3 then "§3 "
63
- when :h4 then "§4 "
64
- when :h5 then "§5 "
65
- when :h6 then "§6 "
66
- when :blockquote then "\n\n〉 "
67
- when :figure
68
- @inside = :figure
69
- "\n\n"
70
- when :figcaption then " "
71
- when :img then fix_href(current_attrs['src'])
72
- when :span, :sup
73
- if current_attrs['class'].nil?
74
- ''
75
- else
76
- @collector[name.to_sym] = "✿_span_#{current_attrs['class'].gsub(/\s+/, '_')}".to_sym
77
- @tags[:inplace][@collector[name.to_sym]] = "span†#{current_attrs['class'].gsub(/\s+/, '†')}".to_sym
78
- " #{@collector[name.to_sym]}"
79
- end
80
- when :embed, :iframe then "\n\n#{current_attrs['src']}\n\n"
81
- when :html, :body, :object, :param, :thead, :tbody, :font, :'lj-embed', :'lj-cut'
82
- ''
83
- else
84
- raise "=== Unhandled: #{name} with attrs: [#{current_attrs}]"
85
- ''
86
- end
87
- end
88
-
89
- def characters str
90
- case @inside
91
- when :a, :dfn, :abbr
92
- @collector[:text] = str
93
- else
94
- @qp += str
95
- end
96
- end
97
-
98
- def end_element name
99
- @qp += case name.to_sym
100
- when :p, :div
101
- @collector.delete(name.to_sym)
102
- "\n\n"
103
- when :a
104
- @inside = nil
105
- (href= @collector.delete(:href)) ?
106
- " #{(@collector.delete(:text) || '').gsub(/\s+/, "\u{00A0}")}¹#{fix_href href} " :
107
- "☇ #{@collector.delete(:name)} #{@collector.delete(:text)}"
108
- when :dfn, :abbr, :cite
109
- @inside = nil
110
- result = " #{@collector.delete(:text).gsub(/\s+/, "\u{00A0}")}†#{@collector.delete(:title)}† " rescue ''
111
- result
112
- when :ul, :ol, :table, :dl
113
- @inside = nil
114
- "\n"
115
- when :li then "\n"
116
- when :pre then "\nΛ\n\n"
117
- when :b, :strong then "≡"
118
- when :i, :em, :nobr then "≈"
119
- when :u then "▁"
120
- when :dd then "\n"
121
- when :strike, :del, :s then "─"
122
- when :small then "↓"
123
- when :code, :tt then "λ"
124
- when :span, :sup
125
- "#{@collector.delete(name.to_sym)} "
126
- when :h1, :h2, :h3, :h4, :h5, :h6 then "\n\n"
127
- when :blockquote then "\n\n"
128
- when :figure
129
- @inside = nil
130
- "\n\n"
131
- else
132
- ''
133
- end
134
- end
135
-
136
- private
137
- def fix_href href, site = 'http://mudasobwa.ru/'
138
- href.start_with?('http') ? href : href.gsub(/\A\/+/, '').prepend(site)
139
- end
140
- end
141
-
142
- end
143
-
144
- if __FILE__ == $0
145
-
146
- def prepare str
147
- str.gsub(/&[nm]dash;/, '—') # dashes
148
- .gsub(/&nbsp;/, ' ') # dashes
149
- .gsub(/\s+--\s+/, ' — ') # dashes
150
- .gsub(/^\s*/, '') # leading spaces
151
- .gsub(/<img src="\/i\/>/, '')
152
- .gsub(/&trade;/, '™') # other entities
153
- .gsub(/&copy;/, '©') # other entities
154
- .gsub(/(1st@1stone.ru|am@secondiary.ru)/, 'am@mudasobwa.ru')
155
- .gsub(/http:\/\/(www\.)?(secondiary|1stone|matiouchkine.net)\.ru/, 'http://mudasobwa.ru') # obsolete site name
156
- .gsub(/\[(http[^\]]*)\]/, '\1') # obsolete markdown pics
157
- .gsub(/<span>\s*<\/span>/, 'λ\1λ') # obsolete markdown pics
158
- .gsub(/<lj (?:comm|user)="(.*?)">/, '✎ \1') # obsolete markdown pics
159
- .gsub(/<([^<>]*?@[^<>]*?)>/, '\1') # obsolete markdown pics
160
- .gsub(/<imgsrc=/, '<img src=') # obsolete markdown pics
161
- .gsub(/<ahref=/, '<a href=') # obsolete markdown pics
162
- .gsub(/<\/p>\s*<p>\s*—/, " ⏎\n—") # direct speech
163
- .gsub(/<br(?:\s*\/?\s*)>\s*<br(?:\s*\/?\s*)>/, "\n\n") # old-fashioned carriage
164
- .gsub(/<[!]--[^<>]*?-->/, '') # comments
165
- # .gsub(/([\.,:;!?])(?=\S)/, '\1 ') # fix punctuation
166
- end
167
-
168
- def postpare str
169
- str.gsub(/\R{2,}/, "\n\n")
170
- .gsub(/\A(\s|⏎)*/, '')
171
- .gsub(/(\s|⏎)*\Z/, '')
172
- end
173
-
174
- tags = {
175
- :magnet => {:✎ => :lj, :☇ => :a},
176
- :inplace => {:▁ => :u, :─ => :del},
177
- :linewide => {:☛ => :twit},
178
- :block => {:✁ => :cut}
179
- }
180
- file = "#{File.dirname(__FILE__)}/../../../data/internals/posts.csv"
181
- file_errors = "#{File.dirname(__FILE__)}/../../../data/internals/errors.txt"
182
- FileUtils.rm file_errors if File.exist? file_errors
183
-
184
- FileUtils.mkdir("#{File.dirname(__FILE__)}/../../../data/site")
185
- # %w{txt pic ref twt}.each {|d| FileUtils.mkdir("#{File.dirname(__FILE__)}/../../../data/site/#{d}")}
186
-
187
- puts "Reading #{file} …"
188
- File.readlines(file).each { |l|
189
- data = l.split('☢')
190
- puts "Processing record #{data[0]}"
191
- begin
192
- html_doc = Qipowl::HtmlDoc.new nil
193
- parser = Nokogiri::HTML::SAX::Parser.new(html_doc)
194
- parser.parse(prepare data[2])
195
- tags.rmerge! html_doc.tags
196
- body = postpare(html_doc.qp)
197
-
198
- body = body.strip if body
199
-
200
- id = data[0]
201
- title = data[1].gsub(/'/, "’")
202
- date = data[3]
203
- img = data[4]
204
-
205
- if img && !img.empty? && !img.start_with?('http://')
206
- img = "http://mudasobwa.ru/i/#{img.gsub(/\A\/+/, '')}"
207
- end
208
-
209
- q_doc = Qipowl::HtmlDoc.new nil
210
- q_parser = Nokogiri::HTML::SAX::Parser.new(q_doc)
211
- q_parser.parse(prepare data[5])
212
- tags.rmerge! q_doc.tags
213
- quote = postpare(q_doc.qp)
214
-
215
- q_url = data[6]
216
- type = data[7].to_i # 1 => text, 2 => image, 3 => quote, 4 => twit
217
- stype = case type
218
- when 1 then :txt
219
- when 2 then :pic
220
- when 3 then :ref
221
- when 4 then :twt
222
- else :txt
223
- end
224
-
225
- owl_text = %Q(---
226
- title: '#{title}'
227
- id: #{id}
228
- date: '#{date}'
229
- categories: [#{stype}]
230
- ---
231
-
232
- )
233
- # owl_text << (type == 4 ? "☛ " : "§1 ")
234
- # owl_text << title
235
- # owl_text << "\n\n"
236
-
237
- owl_text << case type
238
- when 2
239
- "#{img} #{body.gsub(/\R/, ' ⏎ ')}"
240
- when 3
241
- q_ref = q_url[/http:\/\/(.*?)\/|\Z/, 1].split('.').last(2).join('.') rescue nil
242
- "\n〉 #{quote.strip}\n‒ #{q_ref ? q_ref : q_url}, #{q_url}\n\n#{body}"
243
- else body
244
- end
245
-
246
- fname = "#{date.split.first}-#{title.to_filename}.owl"
247
- fname = (1..100).each {|i|
248
- break "#{date.split.first}-#{title.to_filename}-#{i}.owl" \
249
- unless File.exist?("#{File.dirname(__FILE__)}/../../../data/site/#{date.split.first}-#{title.to_filename}-#{i}.owl")
250
- } if File.exist?("#{File.dirname(__FILE__)}/../../../data/site/#{fname}")
251
- File.open("#{File.dirname(__FILE__)}/../../../data/site/#{fname}", 'a') { |f| f.write(owl_text) }
252
-
253
- rescue Exception => e
254
- puts '—'*40
255
- puts 'Error occured'
256
- puts prepare(data[2])
257
- puts '—'*40
258
- puts prepare(data[5])
259
- puts '—'*40
260
- raise e
261
- end
262
- }
263
-
264
- File.open("#{File.dirname(__FILE__)}/../../../data/site/rules.yaml", 'a') { |f|
265
- f.write(tags.to_yaml)
266
- }
267
-
268
- end