qipowl 0.9.3 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +157 -76
- data/bin/bowler +4 -2
- data/config/bowlers/html.yaml +24 -9
- data/extras/drafts/parsing.md +53 -42
- data/features/bowler.feature +14 -0
- data/features/html.feature +76 -27
- data/features/step_definitions/bowler_steps.rb +20 -0
- data/lib/qipowl.rb +29 -19
- data/lib/qipowl/bowlers/html.rb +148 -96
- data/lib/qipowl/bowlers/i_sp_ru.rb +9 -9
- data/lib/qipowl/constants.rb +2 -1
- data/lib/qipowl/core/bowler.rb +31 -22
- data/lib/qipowl/core/mapper.rb +20 -22
- data/lib/qipowl/core/monkeypatches.rb +18 -25
- data/lib/qipowl/core/ruler.rb +48 -43
- data/lib/qipowl/version.rb +1 -1
- data/qipowl.gemspec +0 -2
- data/spec/html_additional_test.yaml +3 -0
- metadata +2 -35
@@ -1,10 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
# КТО ЧТО_ДЕЛАЕТ КОМУ ЧТО
|
4
|
-
# ☺ ⚙
|
4
|
+
# ☺ ⚙ ♿ ☕
|
5
5
|
|
6
6
|
# КАКОЙ КАК КАКОЙ КАКОЙ
|
7
|
-
# ☼
|
7
|
+
# ☼ ☂ ☼ ☼
|
8
8
|
|
9
9
|
# ПОКА НЕ ОПРЕДЕЛЕНА ЧАСТЬ РЕЧИ (найти термин для)
|
10
10
|
# ∈
|
@@ -19,7 +19,7 @@ require_relative '../core/bowler'
|
|
19
19
|
module Qipowl
|
20
20
|
module Mappers
|
21
21
|
class IspruBowlerMapper < BowlerMapper
|
22
|
-
|
22
|
+
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -30,7 +30,7 @@ module Qipowl
|
|
30
30
|
|
31
31
|
LANG_FROM = 'es' # FIXME UGLY
|
32
32
|
LANG_TO = 'ru' # FIXME UGLY
|
33
|
-
|
33
|
+
|
34
34
|
##############################################################################
|
35
35
|
### Default handlers for all the types of markup ###
|
36
36
|
##############################################################################
|
@@ -73,20 +73,20 @@ module Qipowl
|
|
73
73
|
# @see {Qipowl::Bowler#serveup}
|
74
74
|
#
|
75
75
|
# Additionally it beatifies the output HTML
|
76
|
-
#
|
76
|
+
#
|
77
77
|
# @param [String] str to be roasted
|
78
78
|
def serveup str
|
79
|
-
(super str).typo(LANG_TO).strip
|
79
|
+
(super str).typo(lang: LANG_TO).strip
|
80
80
|
end
|
81
81
|
|
82
82
|
private
|
83
|
-
# Hence we cannot simply declare the DSL for it, we need to handle
|
83
|
+
# Hence we cannot simply declare the DSL for it, we need to handle
|
84
84
|
# calls to all the _methods_, starting with those symbols.
|
85
|
-
#
|
85
|
+
#
|
86
86
|
# @param [Symbol] method as specified by caller (`method_missing`.)
|
87
87
|
# @param [Array] args as specified by caller (`method_missing`.)
|
88
88
|
# @param [Proc] block as specified by caller (`method_missing`.)
|
89
|
-
#
|
89
|
+
#
|
90
90
|
# @return [Array] the array of words
|
91
91
|
def special_handler method, *args, &block
|
92
92
|
∀_word method, args, block
|
data/lib/qipowl/constants.rb
CHANGED
data/lib/qipowl/core/bowler.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'typogrowth'
|
4
|
+
|
3
5
|
require_relative "../constants"
|
4
6
|
require_relative '../utils/logging'
|
5
7
|
|
@@ -34,9 +36,9 @@ module Qipowl::Bowlers
|
|
34
36
|
#
|
35
37
|
class Bowler
|
36
38
|
include TypoLogging
|
37
|
-
|
39
|
+
|
38
40
|
attr_reader :in, :out
|
39
|
-
|
41
|
+
|
40
42
|
# Internal constant for joining/splitting the strings during processing.
|
41
43
|
# Override on your own risk. I can′t imagine why you would need to do so.
|
42
44
|
SEPARATOR = $, || ' '
|
@@ -99,9 +101,11 @@ module Qipowl::Bowlers
|
|
99
101
|
key = key.bowl.to_sym
|
100
102
|
tags[key] = value.to_sym
|
101
103
|
self.class.const_get("ENCLOSURES_TAGS")[key] = enclosure_value.to_sym if enclosure_value
|
104
|
+
self.class.const_get("ENTITIES")[section.to_sym][key] = value.to_sym
|
102
105
|
self.class.class_eval %Q{
|
103
106
|
alias_method :#{key}, :∀_#{section}
|
104
107
|
} # unless self.class.instance_methods(true).include?(key.bowl)
|
108
|
+
@shadows = nil
|
105
109
|
else
|
106
110
|
logger.warn "Trying to add key “#{key}” in an invalid section “#{section}”. Ignoring…"
|
107
111
|
end
|
@@ -109,21 +113,25 @@ module Qipowl::Bowlers
|
|
109
113
|
|
110
114
|
# Removes key from both {Mapping.SPICES} and {Mapping.SALT}. See {#add_spice}
|
111
115
|
#
|
112
|
-
# @param [Symbol]
|
113
|
-
def remove_entity
|
116
|
+
# @param [Symbol] entity the key to be removed
|
117
|
+
def remove_entity entity
|
118
|
+
key = entity.to_sym
|
114
119
|
Qipowl::ENTITIES.each { |section|
|
115
120
|
next unless (curr_sect = self.class.const_get("#{section.upcase}_TAGS") rescue nil)
|
116
|
-
|
117
|
-
|
121
|
+
curr_tag = send(:"∃_#{section}", key)
|
122
|
+
next unless curr_tag
|
123
|
+
|
118
124
|
curr_sect.delete key
|
119
125
|
self.class.const_get("ENCLOSURES_TAGS").delete key
|
126
|
+
self.class.const_get("ENTITIES")[section.to_sym].delete key
|
127
|
+
|
120
128
|
self.class.class_eval %Q{
|
121
129
|
remove_method :#{key.bowl}
|
122
130
|
}
|
131
|
+
@shadows = nil
|
123
132
|
}
|
124
133
|
end
|
125
134
|
|
126
|
-
|
127
135
|
protected
|
128
136
|
Qipowl::ENTITIES.each { |section|
|
129
137
|
define_method "∀_#{section}".to_sym, ->(*args) {
|
@@ -132,7 +140,7 @@ module Qipowl::Bowlers
|
|
132
140
|
}
|
133
141
|
|
134
142
|
def defreeze str
|
135
|
-
str
|
143
|
+
str.typo(sections: :quotes).defuse
|
136
144
|
end
|
137
145
|
|
138
146
|
def roast str
|
@@ -143,7 +151,10 @@ module Qipowl::Bowlers
|
|
143
151
|
rescue Exception => e
|
144
152
|
msg = e.message.dup
|
145
153
|
logger.error '='*78
|
146
|
-
logger.error "Could not roast dish [#{msg.force_encoding(Encoding::UTF_8)}].\nWill return as is…
|
154
|
+
logger.error "Could not roast dish [#{msg.force_encoding(Encoding::UTF_8)}].\nWill return as is… Backtrace:\n"
|
155
|
+
logger.error e.backtrace.take(Qipowl::BTRACE_COUNT).join("\n")
|
156
|
+
logger.error '-'*78
|
157
|
+
logger.error "Dish follows:\n"
|
147
158
|
logger.error '-'*78
|
148
159
|
logger.error dish
|
149
160
|
logger.error '='*78
|
@@ -153,16 +164,16 @@ module Qipowl::Bowlers
|
|
153
164
|
@yielded.pop(@yielded.size).reverse.join(SEPARATOR)
|
154
165
|
}.join($/).uncarriage.un␚ify.unspacefy.unbowl
|
155
166
|
end
|
156
|
-
|
167
|
+
|
157
168
|
def serveup str
|
158
|
-
str.gsub(/⌦./, '').gsub(/.⌫/, '')
|
169
|
+
str.gsub(/⌦./, '').gsub(/.⌫/, '').typo
|
159
170
|
end
|
160
171
|
|
161
172
|
protected
|
162
173
|
# The handler of the last “orphaned” text block in the input string.
|
163
174
|
#
|
164
175
|
# E.g.:
|
165
|
-
#
|
176
|
+
#
|
166
177
|
# Here goes a quite significant list:
|
167
178
|
#
|
168
179
|
# • line item 1
|
@@ -195,25 +206,25 @@ module Qipowl::Bowlers
|
|
195
206
|
# After we have this part of input processed, it should be considered
|
196
207
|
# “done.” So block processors call {#harvest} to store processed parts.
|
197
208
|
#
|
198
|
-
# @param [Symbol]
|
209
|
+
# @param [Symbol] cally of this method. Qipowl hardly relies on method namings and sometimes we may need to know if the call was made by, say, lineitem DSL (`•`), not datalist (`▷`).
|
199
210
|
# @param [String] str string to yield
|
200
211
|
#
|
201
212
|
# @return nil
|
202
|
-
def harvest
|
213
|
+
def harvest cally, str
|
203
214
|
@yielded << str unless str.vacant?
|
204
215
|
nil
|
205
216
|
end
|
206
|
-
|
217
|
+
|
207
218
|
private
|
208
219
|
# Prepares blocks in the input for the execution
|
209
220
|
def block str
|
210
221
|
return str unless self.class.const_defined?(:BLOCK_TAGS)
|
211
222
|
result = str.dup
|
212
223
|
self.class::BLOCK_TAGS.each { |tag, value|
|
213
|
-
result.gsub!(/(#{tag})
|
224
|
+
result.gsub!(/(#{tag})(.*?)(?:#{tag}|\Z)/m) { |m|
|
214
225
|
%Q{
|
215
226
|
|
216
|
-
#{$1} #{$2.
|
227
|
+
#{$1} #{Base64.encode64($2).carriage(false).bowl}
|
217
228
|
|
218
229
|
}
|
219
230
|
}
|
@@ -245,14 +256,12 @@ module Qipowl::Bowlers
|
|
245
256
|
}
|
246
257
|
result.unbowl
|
247
258
|
end
|
248
|
-
|
259
|
+
|
249
260
|
def split str
|
250
261
|
(block str).split(/\R{2,}/).map { |para|
|
251
|
-
|
252
|
-
(para =~ /\A(#{self.class::BLOCK_TAGS.keys.join('|')})\s+/) ?
|
253
|
-
para : (grip custom para)
|
262
|
+
(grip custom para)
|
254
263
|
}
|
255
264
|
end
|
256
|
-
|
265
|
+
|
257
266
|
end
|
258
267
|
end
|
data/lib/qipowl/core/mapper.rb
CHANGED
@@ -8,7 +8,7 @@ require_relative '../utils/logging'
|
|
8
8
|
|
9
9
|
# @author Alexei Matyushkin
|
10
10
|
module Qipowl::Mappers
|
11
|
-
|
11
|
+
|
12
12
|
# Operates +mapping+ for loaded +YAML+ rules files.
|
13
13
|
#
|
14
14
|
# - For top level sections, each section name
|
@@ -27,30 +27,34 @@ module Qipowl::Mappers
|
|
27
27
|
@hash
|
28
28
|
end
|
29
29
|
def merge! input
|
30
|
-
|
31
|
-
raise ArgumentError.new "Invalid map for merge in Mapper" \
|
32
|
-
unless
|
30
|
+
map = load_yaml(input) if input.is_one_of?(String, IO)
|
31
|
+
raise ArgumentError.new "Invalid map (#{input} @ #{Qipowl.bowlers}) for merge in Mapper.\nCurrent dir: [#{Dir.pwd}].\n" \
|
32
|
+
unless map.respond_to? :to_hash
|
33
33
|
|
34
|
-
incs =
|
34
|
+
incs = map.delete(:includes)
|
35
35
|
|
36
36
|
@entities_dirty = true
|
37
|
-
@hash.rmerge!(
|
37
|
+
@hash.rmerge!(map.to_hash)
|
38
38
|
incs.each { |inc|
|
39
39
|
merge! inc
|
40
40
|
} rescue NoMethodError # FIXME WTF rescueing here?
|
41
41
|
end
|
42
42
|
private
|
43
|
-
|
43
|
+
def load_yaml_file name
|
44
|
+
[*Qipowl.bowlers].each { |b|
|
45
|
+
(return YAML.load_file("#{b}/#{name}.yaml")) rescue next
|
46
|
+
}
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
44
50
|
def load_yaml input
|
45
|
-
IO === input ?
|
46
|
-
YAML.load_stream(input) :
|
47
|
-
YAML.load_file("#{Qipowl.bowlers_dir}/#{input.downcase}.yaml")
|
51
|
+
IO === input ? YAML.load_stream(input) : load_yaml_file("#{input.downcase}")
|
48
52
|
end
|
49
53
|
end
|
50
|
-
|
54
|
+
|
51
55
|
class BowlerMapper < Mapper
|
52
56
|
include TypoLogging
|
53
|
-
|
57
|
+
|
54
58
|
def initialize input = nil
|
55
59
|
input = self.class.name.split('::').last.downcase.gsub(/bowlermapper\Z/, '') if input.nil?
|
56
60
|
super input
|
@@ -67,11 +71,12 @@ module Qipowl::Mappers
|
|
67
71
|
# Append keys
|
68
72
|
@entities[key][k.bowl] = v.dup
|
69
73
|
if Hash === v
|
70
|
-
@entities[key][k.bowl].delete(:synonyms)
|
74
|
+
@entities[key][k.bowl].delete(:synonyms)
|
71
75
|
# Append explicit synonyms
|
72
76
|
v[:synonyms].each { |syn|
|
73
|
-
|
74
|
-
@entities[key][syn
|
77
|
+
syn = syn.bowl.to_sym
|
78
|
+
(@entities[key][syn] = v.dup).delete(:synonyms)
|
79
|
+
@entities[key][syn][:marker] = k.bowl
|
75
80
|
} if v[:synonyms]
|
76
81
|
end
|
77
82
|
}
|
@@ -81,10 +86,3 @@ module Qipowl::Mappers
|
|
81
86
|
end
|
82
87
|
end
|
83
88
|
end
|
84
|
-
|
85
|
-
if __FILE__ == $0
|
86
|
-
require '../../qipowl'
|
87
|
-
y = Qipowl::Mappers::BowlerMapper.new 'html'
|
88
|
-
require 'awesome_print'
|
89
|
-
ap y[:mail]
|
90
|
-
end
|
@@ -18,12 +18,12 @@ module Qipowl
|
|
18
18
|
end
|
19
19
|
|
20
20
|
# Bowling string means producing interpreter-safe text basing on ascii input.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
class ::String
|
23
23
|
NBSP = "\u{00A0}"
|
24
|
-
|
24
|
+
|
25
25
|
SYMBOL_FOR_SPACE = "\u{2420}" # ␠
|
26
|
-
|
26
|
+
|
27
27
|
WIDESPACE = "\u{FF00}"
|
28
28
|
EN_SPACE = "\u{2002}"
|
29
29
|
EM_SPACE = "\u{2003}"
|
@@ -38,8 +38,8 @@ module Qipowl
|
|
38
38
|
NARROW_NO_BREAK_SPACE = "\u{202F}"
|
39
39
|
MEDIUM_MATHEMATICAL_SPACE = "\u{205F}"
|
40
40
|
ZERO_WIDTH_NO_BREAK_SPACE = "\u{FEFF}"
|
41
|
-
IDEOGRAPHIC_SPACE = "\u{3000}"
|
42
|
-
|
41
|
+
IDEOGRAPHIC_SPACE = "\u{3000}"
|
42
|
+
|
43
43
|
CARRIAGE_RETURN = '␍'
|
44
44
|
NULL = '␀'
|
45
45
|
ASCII_SYMBOLS, ASCII_DIGITS, ASCII_LETTERS_SMALL, ASCII_LETTERS_CAP = [
|
@@ -58,14 +58,14 @@ module Qipowl
|
|
58
58
|
}.flatten]
|
59
59
|
}
|
60
60
|
UTF_ALL = [UTF_SYMBOLS.values, UTF_DIGITS.values, UTF_LETTERS_SMALL.values, UTF_LETTERS_CAP.values]
|
61
|
-
|
61
|
+
|
62
62
|
UTF_ASCII = UTF_SYMBOLS.merge(UTF_DIGITS).merge(UTF_LETTERS_SMALL).merge(UTF_LETTERS_CAP)
|
63
63
|
ASCII_UTF = UTF_ASCII.invert
|
64
|
-
|
64
|
+
|
65
65
|
def vacant?
|
66
66
|
nil? || empty?
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def hsub! hash
|
70
70
|
self.gsub!(/#{hash.keys.join('|')}/, hash)
|
71
71
|
end
|
@@ -101,41 +101,34 @@ module Qipowl
|
|
101
101
|
(out = self.dup).unspacefy!
|
102
102
|
out
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def unuglify
|
106
106
|
self.unbowl.unspacefy.uncarriage.strip
|
107
107
|
end
|
108
108
|
|
109
109
|
HTML_ENTITIES = Hash[[['<', 'lt'], ['>', 'gt'], ['&', 'amp']].map { |k, v| [k.bowl, "&#{v};"] }]
|
110
110
|
|
111
|
-
def carriage
|
112
|
-
self.gsub(/\R/, " #{CARRIAGE_RETURN} ")
|
113
|
-
end
|
114
|
-
def carriage!
|
115
|
-
self.gsub!(/\R/, " #{CARRIAGE_RETURN} ")
|
111
|
+
def carriage spaces = true
|
112
|
+
self.gsub(/\R/, spaces ? " #{CARRIAGE_RETURN} " : "#{CARRIAGE_RETURN}")
|
116
113
|
end
|
117
|
-
def uncarriage
|
118
|
-
self.gsub(/\s?#{CARRIAGE_RETURN}\s
|
119
|
-
))
|
120
|
-
end
|
121
|
-
def uncarriage!
|
122
|
-
self.gsub!(/\s?#{CARRIAGE_RETURN}\s?/, %Q(
|
114
|
+
def uncarriage spaces = true
|
115
|
+
self.gsub(spaces ? /\s?#{CARRIAGE_RETURN}\s?/ : /#{CARRIAGE_RETURN}/, %Q(
|
123
116
|
))
|
124
117
|
end
|
125
118
|
|
126
119
|
def un␚ify
|
127
120
|
self.gsub(/␚(.*?)␚/, '')
|
128
121
|
end
|
129
|
-
|
122
|
+
|
130
123
|
def wstrip
|
131
124
|
self.gsub(/#{NBSP}/, '')
|
132
125
|
end
|
133
|
-
|
126
|
+
|
134
127
|
def to_filename
|
135
128
|
self.gsub(/[#{Regexp.quote(ASCII_SYMBOLS.join)}]/, UTF_ASCII).gsub(/\s/, "#{NBSP}")[0..50]
|
136
129
|
end
|
137
130
|
end
|
138
|
-
|
131
|
+
|
139
132
|
class ::Symbol
|
140
133
|
def dup
|
141
134
|
self.to_s.dup.to_sym
|
@@ -159,11 +152,11 @@ module Qipowl
|
|
159
152
|
self.to_s.wstrip.to_sym
|
160
153
|
end
|
161
154
|
end
|
162
|
-
|
155
|
+
|
163
156
|
class ::Fixnum
|
164
157
|
def ␚ify
|
165
158
|
"␚#{self}␚"
|
166
159
|
end
|
167
160
|
end
|
168
|
-
|
161
|
+
|
169
162
|
end
|
data/lib/qipowl/core/ruler.rb
CHANGED
@@ -5,7 +5,7 @@ require_relative '../utils/logging'
|
|
5
5
|
|
6
6
|
# @author Alexei Matyushkin
|
7
7
|
module Qipowl
|
8
|
-
|
8
|
+
|
9
9
|
# Operates +mapping+ for loaded +YAML+ rules files.
|
10
10
|
#
|
11
11
|
# - For top level sections, each section name
|
@@ -14,18 +14,18 @@ module Qipowl
|
|
14
14
|
# method which is simply loads rules from the respective file
|
15
15
|
#
|
16
16
|
# Mapping may be loaded from YAML file, as well as be merged
|
17
|
-
# against other YAML file, hash or `Ruler` instance.
|
17
|
+
# against other YAML file, hash or `Ruler` instance.
|
18
18
|
module Ruler
|
19
19
|
include TypoLogging
|
20
20
|
extend self
|
21
21
|
|
22
22
|
@@bowlers = {} # FIXME REDIS!!!!
|
23
|
-
|
23
|
+
|
24
24
|
def get_bowler id: nil, type: nil
|
25
25
|
@@bowlers[id] || new_bowler(type, true)
|
26
26
|
end
|
27
|
-
|
28
|
-
def new_bowler type, persistent
|
27
|
+
|
28
|
+
def new_bowler type, persistent: false, additional_maps: []
|
29
29
|
yaml, clazz = \
|
30
30
|
case type
|
31
31
|
when Class
|
@@ -33,63 +33,73 @@ module Qipowl
|
|
33
33
|
when String, Symbol
|
34
34
|
["#{type.to_s.downcase}", Qipowl::Bowlers.const_get(type.to_s.capitalize.to_sym)]
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
raise NameError.new("Invalid bowler type: #{type}") \
|
38
38
|
unless clazz.is_a?(Class) && clazz < Qipowl::Bowlers::Bowler
|
39
|
-
|
39
|
+
|
40
40
|
id = "#{Time.now.to_i}#{rand(1..1_000_000_000)}"
|
41
41
|
name = "#{clazz.name.split('::').last}_#{id}"
|
42
42
|
clazz = Qipowl::Bowlers.const_set(name, Class.new(clazz))
|
43
43
|
|
44
|
-
teach_class clazz, get_yaml(yaml)
|
44
|
+
teach_class clazz, get_yaml(yaml, additional_maps: additional_maps)
|
45
45
|
|
46
46
|
persistent ? [@@bowlers[id] = clazz.new, id] : clazz.new
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
private
|
50
|
-
def get_yaml yaml
|
50
|
+
def get_yaml yaml, additional_maps: []
|
51
51
|
clazz = Qipowl::Mappers.const_get("#{yaml.capitalize}BowlerMapper")
|
52
52
|
raise NameError.new("Invalid mapper type: #{clazz}") \
|
53
53
|
unless clazz.is_a?(Class) && clazz < Qipowl::Mappers::BowlerMapper
|
54
|
-
|
55
|
-
clazz.new
|
54
|
+
|
55
|
+
result = clazz.new
|
56
|
+
[*additional_maps].each { |map|
|
57
|
+
result.merge! map
|
58
|
+
}
|
59
|
+
result
|
56
60
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
clazz.const_set(
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
|
62
|
+
def teach_class_prepare clazz
|
63
|
+
clazz.const_set('CUSTOM_TAGS', {}) unless clazz.const_defined? 'CUSTOM_TAGS'
|
64
|
+
clazz.const_set('ENCLOSURES_TAGS', {}) unless clazz.const_defined? 'ENCLOSURES_TAGS'
|
65
|
+
Qipowl::ENTITIES.each { |section|
|
66
|
+
clazz.const_set("#{section.upcase}_TAGS", {}) \
|
67
|
+
unless clazz.const_defined? "#{section.upcase}_TAGS"
|
68
|
+
}
|
69
|
+
clazz.const_set('ENTITIES', {}) unless clazz.const_defined? 'ENTITIES'
|
70
|
+
clazz.const_set('TAGS', {}) unless clazz.const_defined? 'TAGS'
|
71
|
+
end
|
72
|
+
|
73
|
+
def ∃_template section
|
74
|
+
%Q{
|
75
|
+
def ∃_#{section} entity
|
76
|
+
self.class::#{section.upcase}_TAGS.each { |k, v|
|
67
77
|
next unless k == entity
|
68
78
|
v = {:tag => v} unless Hash === v
|
69
79
|
v[:origin] = self.class::TAGS[v[:tag]]
|
80
|
+
v[:section] = k
|
70
81
|
return v
|
71
82
|
}
|
72
83
|
nil
|
73
84
|
end
|
74
85
|
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def teach_class clazz, mapper
|
89
|
+
teach_class_prepare clazz
|
90
|
+
|
91
|
+
clazz::CUSTOM_TAGS.rmerge! mapper.to_hash[:custom] if mapper.to_hash[:custom]
|
92
|
+
clazz::ENCLOSURES_TAGS.rmerge! mapper.to_hash[:enclosures] if mapper.to_hash[:enclosures]
|
93
|
+
clazz::ENTITIES.rmerge! mapper.entities if mapper.entities
|
94
|
+
|
95
|
+
clazz.class_eval ∃_template 'enclosures'
|
96
|
+
|
75
97
|
Qipowl::ENTITIES.each { |section|
|
76
98
|
next unless mapper.entities && mapper.entities[section.to_sym]
|
77
|
-
clazz.
|
78
|
-
clazz.
|
79
|
-
|
80
|
-
|
81
|
-
self.class::#{section.upcase}_TAGS.each { |k, v|
|
82
|
-
next unless k == entity
|
83
|
-
v = {:tag => v} unless Hash === v
|
84
|
-
v[:section] = k
|
85
|
-
return v
|
86
|
-
}
|
87
|
-
nil
|
88
|
-
end
|
89
|
-
def ∃_#{section}_tag entity
|
90
|
-
∃_#{section}(entity)[:tag] if ∃_#{section}(entity)
|
91
|
-
end
|
92
|
-
}
|
99
|
+
clazz.const_get("#{section.upcase}_TAGS").rmerge! mapper.entities[section.to_sym]
|
100
|
+
clazz.const_get('TAGS').rmerge! clazz.const_get("#{section.upcase}_TAGS")
|
101
|
+
clazz.class_eval ∃_template section
|
102
|
+
|
93
103
|
mapper.entities[section.to_sym].each { |key, value|
|
94
104
|
tag = Hash === value && value[:marker] ? value[:marker] : "∀_#{section}"
|
95
105
|
clazz.class_eval %Q{
|
@@ -97,11 +107,6 @@ module Qipowl
|
|
97
107
|
} unless clazz.instance_methods.include?(key.to_sym)
|
98
108
|
}
|
99
109
|
}
|
100
|
-
clazz.class_eval %Q{
|
101
|
-
def ∀_tags
|
102
|
-
self.class::TAGS.keys
|
103
|
-
end
|
104
|
-
}
|
105
110
|
end
|
106
111
|
end
|
107
112
|
end
|