qipowl 0.9.3 → 0.9.7
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 +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
|