infoboxer 0.1.0

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.dokaz +1 -0
  3. data/.yardopts +1 -0
  4. data/LICENSE.txt +22 -0
  5. data/Parsing.md +33 -0
  6. data/README.md +115 -0
  7. data/examples/output/.gitkeep +0 -0
  8. data/examples/pages/argentina.wiki +808 -0
  9. data/examples/to_text.rb +8 -0
  10. data/examples/tree.rb +8 -0
  11. data/infoboxer.gemspec +43 -0
  12. data/lib/infoboxer.rb +196 -0
  13. data/lib/infoboxer/core_ext.rb +10 -0
  14. data/lib/infoboxer/definitions/en.wikipedia.org.rb +355 -0
  15. data/lib/infoboxer/media_wiki.rb +162 -0
  16. data/lib/infoboxer/media_wiki/page.rb +38 -0
  17. data/lib/infoboxer/media_wiki/traits.rb +60 -0
  18. data/lib/infoboxer/navigation.rb +84 -0
  19. data/lib/infoboxer/navigation/lookup.rb +216 -0
  20. data/lib/infoboxer/navigation/sections.rb +179 -0
  21. data/lib/infoboxer/navigation/selector.rb +59 -0
  22. data/lib/infoboxer/navigation/shortcuts.rb +165 -0
  23. data/lib/infoboxer/parser.rb +71 -0
  24. data/lib/infoboxer/parser/context.rb +165 -0
  25. data/lib/infoboxer/parser/html.rb +58 -0
  26. data/lib/infoboxer/parser/image.rb +59 -0
  27. data/lib/infoboxer/parser/inline.rb +142 -0
  28. data/lib/infoboxer/parser/paragraphs.rb +66 -0
  29. data/lib/infoboxer/parser/table.rb +132 -0
  30. data/lib/infoboxer/parser/template.rb +47 -0
  31. data/lib/infoboxer/parser/util.rb +73 -0
  32. data/lib/infoboxer/templates.rb +10 -0
  33. data/lib/infoboxer/templates/base.rb +82 -0
  34. data/lib/infoboxer/templates/set.rb +72 -0
  35. data/lib/infoboxer/tree.rb +70 -0
  36. data/lib/infoboxer/tree/compound.rb +81 -0
  37. data/lib/infoboxer/tree/document.rb +11 -0
  38. data/lib/infoboxer/tree/html.rb +76 -0
  39. data/lib/infoboxer/tree/image.rb +53 -0
  40. data/lib/infoboxer/tree/inline.rb +39 -0
  41. data/lib/infoboxer/tree/list.rb +160 -0
  42. data/lib/infoboxer/tree/node.rb +181 -0
  43. data/lib/infoboxer/tree/nodes.rb +185 -0
  44. data/lib/infoboxer/tree/paragraphs.rb +122 -0
  45. data/lib/infoboxer/tree/ref.rb +34 -0
  46. data/lib/infoboxer/tree/table.rb +89 -0
  47. data/lib/infoboxer/tree/template.rb +82 -0
  48. data/lib/infoboxer/tree/text.rb +60 -0
  49. data/lib/infoboxer/tree/wikilink.rb +83 -0
  50. data/lib/infoboxer/version.rb +4 -0
  51. data/profile/out/.gitkeep +0 -0
  52. data/profile/pages/argentina.txt +808 -0
  53. data/profile/pages/canada.wiki +544 -0
  54. data/profile/pages/ukraine.wiki +1006 -0
  55. data/profile/pages/usa.wiki +843 -0
  56. data/regression/pages/canada.wiki +544 -0
  57. data/regression/pages/chiang_mai.wiki +2615 -0
  58. data/regression/pages/south_america.wiki +640 -0
  59. data/regression/pages/ukraine.wiki +1006 -0
  60. data/regression/pages/usa.wiki +843 -0
  61. metadata +272 -0
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require_relative '../lib/infoboxer'
3
+
4
+ document = Infoboxer::Parser.parse(File.read('examples/pages/argentina.wiki'))
5
+
6
+ FileUtils.mkdir_p 'examples/output'
7
+
8
+ File.write('examples/output/argentina-text.txt', document.to_text)
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require_relative '../lib/infoboxer'
3
+
4
+ document = Infoboxer::Parser.document(File.read('examples/pages/argentina.wiki'))
5
+
6
+ FileUtils.mkdir_p 'examples/output'
7
+
8
+ File.write('examples/output/argentina-tree.txt', document.to_tree)
@@ -0,0 +1,43 @@
1
+ require './lib/infoboxer/version'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'infoboxer'
5
+ s.version = Infoboxer::VERSION
6
+ s.authors = ['Victor Shepelev']
7
+ s.email = 'zverok.offline@gmail.com'
8
+ s.homepage = 'https://github.com/zverok/infoboxer'
9
+
10
+ s.summary = 'MediaWiki client and parser, targeting information extraction.'
11
+ s.description = <<-EOF
12
+ Infoboxer is library targeting use of Wikipedia (or any other
13
+ MediaWiki-based wiki) as a rich powerful data source.
14
+ EOF
15
+ s.licenses = ['MIT']
16
+
17
+ s.files = `git ls-files`.split($RS).reject do |file|
18
+ file =~ /^(?:
19
+ spec\/.*
20
+ |Gemfile
21
+ |Rakefile
22
+ |\.rspec
23
+ |\.gitignore
24
+ |\.rubocop.yml
25
+ |\.travis.yml
26
+ )$/x
27
+ end
28
+ s.require_paths = ["lib"]
29
+
30
+ s.add_dependency 'htmlentities'
31
+ s.add_dependency 'procme'
32
+ s.add_dependency 'rest-client'
33
+ s.add_dependency 'addressable'
34
+ s.add_dependency 'terminal-table'
35
+ s.add_dependency 'backports'
36
+
37
+ s.add_development_dependency 'rake'
38
+ s.add_development_dependency 'rspec', '~> 3'
39
+ s.add_development_dependency 'rspec-its', '~> 1'
40
+ s.add_development_dependency 'ruby-prof'
41
+ s.add_development_dependency 'vcr'
42
+ s.add_development_dependency 'webmock'
43
+ end
@@ -0,0 +1,196 @@
1
+ # encoding: utf-8
2
+ require 'procme'
3
+ require 'backports/2.1.0/array/to_h'
4
+ #require 'backports/2.2.0/object/itself' Y U NO???
5
+
6
+ # Main client module for entire infoboxer functionality. If you're lucky,
7
+ # there's no other classes/modules you need to instantiate or call
8
+ # directly. You just do:
9
+ #
10
+ # ```ruby
11
+ # Infoboxer.wp.get('List of radio telescopes')
12
+ # # or
13
+ # Infoboxer.wikiquote.get('Vonnegut')
14
+ # ```
15
+ # ...and have fully navigable Wiki information.
16
+ #
17
+ # Please read [wiki](http://github.com/molybdenum-99/infoboxer/wiki)
18
+ # for extensive [showcases](https://github.com/molybdenum-99/infoboxer/wiki/Showcase)
19
+ # and usage recommendations.
20
+ #
21
+ # Here's main components list, which also can serve as a TOC for
22
+ # Infoboxer's functionality (we suggest to read their docs in this order):
23
+ #
24
+ # * {Tree} -- nodes, of which Wikipedia AST is consisting; you'll be
25
+ # interested in basic {Tree::Node} functionality, as well as node
26
+ # classes list (which is useful for navigation);
27
+ # * {Navigation} -- how to navigate the tree you have, basic way
28
+ # (children, parents, siblings) and hi-level shortcuts way (like
29
+ # all unnumbered list items in second level-3 section);
30
+ # * {Templates} -- the most advanced data extraction from wikipedia definitely
31
+ # needs your undestanding of this (rather complicated) topic.
32
+ #
33
+ # You also may be interested in (though may be never need to use them directly):
34
+ #
35
+ # * {MediaWiki} client class;
36
+ # * {Parser} -- which, you know, parses.
37
+ #
38
+ module Infoboxer
39
+ private # hiding constants from YARD
40
+
41
+ WIKIA_API_URL = 'http://%s.wikia.com/api.php'
42
+
43
+ WIKIMEDIA_PROJECTS = {
44
+ wikipedia: 'wikipedia.org',
45
+ wikivoyage: 'wikivoyage.org',
46
+ wikiquote: 'wikiquote.org',
47
+ wiktionary: 'wiktionary.org',
48
+ wikibooks: 'wikibooks.org',
49
+ wikinews: 'wikinews.org',
50
+ wikiversity: 'wikiversity.org',
51
+ wikisource: 'wikisource.org'
52
+ }
53
+
54
+ WIKIMEDIA_COMMONS = {
55
+ commons: 'commons.wikimedia.org',
56
+ species: 'species.wikimedia.org',
57
+ }
58
+
59
+ class << self
60
+
61
+ # Default method for creating MediaWiki API client.
62
+ #
63
+ # @param api_url should be URL of api.php for your MediaWiki
64
+ # @param options list of options.
65
+ # The only recognized option for now, though, is
66
+ # * `:user_agent` (also aliased as `:ua`) -- custom User-Agent header.
67
+ # @return [MediaWiki] an instance of API client, which you can
68
+ # further use like this:
69
+ #
70
+ # ```ruby
71
+ # Infoboxer.wiki('some_url').get('Some page title')
72
+ # ```
73
+ def wiki(api_url, options = {})
74
+ MediaWiki.new(api_url, options || {})
75
+ end
76
+
77
+ # @!method wikipedia(lang = 'en', options = {})
78
+ # Shortcut for creating Wikipedia client.
79
+ #
80
+ # @param lang two-character code for language version
81
+ # @param options (see #wiki for list of options)
82
+ # @return [MediaWiki]
83
+
84
+ # @!method commons(options = {})
85
+ # Shortcut for creating [WikiMedia Commons](https://commons.wikimedia.org/) client.
86
+ #
87
+ # @param options (see #wiki for list of options)
88
+ # @return [MediaWiki]
89
+
90
+ # @!method wikibooks(lang = 'en', options = {})
91
+ # Shortcut for creating [Wikibooks](https://en.wikibooks.org/) client.
92
+ # See {wikipedia} for params explanation.
93
+ # @return [MediaWiki]
94
+
95
+ # @!method wikiquote(lang = 'en', options = {})
96
+ # Shortcut for creating [Wikiquote](https://en.wikiquote.org/) client.
97
+ # See {wikipedia} for params explanation.
98
+ # @return [MediaWiki]
99
+
100
+ # @!method wikiversity(lang = 'en', options = {})
101
+ # Shortcut for creating [Wikiversity](https://en.wikiversity.org/) client.
102
+ # See {wikipedia} for params explanation.
103
+ # @return [MediaWiki]
104
+
105
+ # @!method wikisource(lang = 'en', options = {})
106
+ # Shortcut for creating [Wikisource](https://en.wikisource.org/) client.
107
+ # See {wikipedia} for params explanation.
108
+ # @return [MediaWiki]
109
+
110
+ # @!method wikivoyage(lang = 'en', options = {})
111
+ # Shortcut for creating [Wikivoyage](http://wikivoyage.org) client.
112
+ # See {wikipedia} for params explanation.
113
+ # @return [MediaWiki]
114
+
115
+ # @!method wikinews(lang = 'en', options = {})
116
+ # Shortcut for creating [Wikinews](https://en.wikinews.org/) client.
117
+ # See {wikipedia} for params explanation.
118
+ # @return [MediaWiki]
119
+
120
+ # @!method species(options = {})
121
+ # Shortcut for creating [Wikispecies](https://species.wikimedia.org/) client.
122
+ #
123
+ # @param options (see #wiki for list of options)
124
+ # @return [MediaWiki]
125
+
126
+ # @!method wiktionary(lang = 'en', options = {})
127
+ # Shortcut for creating [Wiktionary](https://en.wiktionary.org/) client.
128
+ # See {wikipedia} for params explanation.
129
+ # @return [MediaWiki]
130
+
131
+ WIKIMEDIA_PROJECTS.each do |name, domain|
132
+ define_method name do |lang = 'en', options = {}|
133
+ if lang.is_a?(Hash)
134
+ lang, options = 'en', lang
135
+ end
136
+
137
+ wiki("http://#{lang}.#{domain}/w/api.php", options)
138
+ end
139
+ end
140
+
141
+ alias_method :wp, :wikipedia
142
+
143
+ WIKIMEDIA_COMMONS.each do |name, domain|
144
+ define_method name do |options = {}|
145
+ wiki("http://#{domain}/w/api.php", options)
146
+ end
147
+ end
148
+
149
+ # Performs request to wikia.com wikis.
150
+ #
151
+ # @overload wikia(*domains)
152
+ # @param *domains list of domains to merge, like this:
153
+ #
154
+ # ```ruby
155
+ # Infoboxer.wikia('tardis') # looks at tardis.wikia.com
156
+ # Infoboxer.wikia('tardis', 'ru') # looks in Russian version, ru.tardis.wikia.com
157
+ # ```
158
+ # If you are surprised by "reversing" list of subdomains, think of
159
+ # it as of chain of refinements (looking in "tardis" wiki, its "ru"
160
+ # version, specifically).
161
+ #
162
+ # @overload wikia(*domains, options)
163
+ # @param *domains same as above
164
+ # @param options just last of params, if it is hash
165
+ # (see {wiki} for list of options)
166
+ #
167
+ # @return [MediaWiki]
168
+ def wikia(*domains)
169
+ options = domains.last.is_a?(Hash) ? domains.pop : {}
170
+ wiki(WIKIA_API_URL % domains.reverse.join('.'), options)
171
+ end
172
+
173
+ # Sets user agent string globally. Default user agent is
174
+ # {MediaWiki::UA}.
175
+ #
176
+ # User agent can also be rewriten as an option to {wiki} method (and
177
+ # its shortcuts like {wikipedia}), or by using {MediaWiki#initialize}
178
+ # explicitly.
179
+ #
180
+ def user_agent=(ua)
181
+ MediaWiki.user_agent = ua
182
+ end
183
+ end
184
+ end
185
+
186
+ require_relative 'infoboxer/version'
187
+ require_relative 'infoboxer/core_ext'
188
+
189
+ require_relative 'infoboxer/tree'
190
+ require_relative 'infoboxer/parser'
191
+ require_relative 'infoboxer/navigation'
192
+ require_relative 'infoboxer/templates'
193
+
194
+ require_relative 'infoboxer/media_wiki'
195
+
196
+ require_relative 'infoboxer/definitions/en.wikipedia.org'
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ # @private
3
+ class Object
4
+ # Unfortunately, not in backports gem still :(
5
+ if RUBY_VERSION < '2.2.0'
6
+ def itself
7
+ self
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,355 @@
1
+ # encoding: utf-8
2
+ module Infoboxer
3
+ MediaWiki::Traits.for('en.wikipedia.org') do
4
+ templates do
5
+ # https://en.wikipedia.org/wiki/Category:Wikipedia_character-substitution_templates
6
+ # ---------------------------------------------------------------------------------
7
+ # Extracted semi-automatically
8
+ # TODO: fully automatical extraction
9
+ literal(
10
+ '&',
11
+ ';',
12
+ '=',
13
+ '?',
14
+ '—',
15
+ '1/2',
16
+ '1/3',
17
+ '1/4',
18
+ '2/3',
19
+ '3/4',
20
+ )
21
+ replace(
22
+ '!!' => '||',
23
+ '!(' => '[',
24
+ '!((' => '[[',
25
+ '!-' => '|-',
26
+ '!:' => ':',
27
+ '&' => '&',
28
+ "'" => " '",
29
+ "''" => '″',
30
+ "'s" => "'‍s",
31
+ '(' => '{',
32
+ '((' => '{{',
33
+ '(((' => '{{{',
34
+ ')' => '}',
35
+ ')!' => ']',
36
+ '))' => '}}',
37
+ '))!' => ']]',
38
+ ')))' => '}}}',
39
+ 'Asterisk' => '*',
40
+ 'Colon' => ':',
41
+ 'Em dash' => '—',
42
+ 'Gc' => "†",
43
+ 'Ibeam' => 'I',
44
+ 'Long dash' => ' ——— ',
45
+ 'Nbhyph' => '‑',
46
+ 'Number sign' => '#',
47
+ 'Shy' => '­', # soft hyphen
48
+ 'Single space' => "' ",
49
+ 'Space single' => " '",
50
+ 'Spaced ndash' => ' – ',
51
+ 'Square bracket close' => ']',
52
+ 'Square bracket open' => '[',
53
+ 'Zwsp' => '',
54
+ '\\' => ' / ',
55
+ '`' => "'",
56
+ '·' => ' · ',
57
+ '‘' => '‘',
58
+ '•' => ' • ',
59
+ )
60
+
61
+ # https://en.wikipedia.org/wiki/Category:Line-handling_templates
62
+ # ------------------------------------------------------------------
63
+ replace(
64
+ '-' => "\n",
65
+ 'Break' => "\n", # FIXME: in fact, break has optional parameter "how many breaks"
66
+ 'Crlf' => "\n", # FIXME: in fact, alias for break, should have DSL syntax for it!
67
+ 'Crlf2' => "\n",
68
+
69
+ )
70
+ show(
71
+ 'Allow wrap',
72
+ 'Nowrap',
73
+ 'j', 'nobr', 'nobreak', # aliases for Nowrap
74
+ 'nowraplinks',
75
+ )
76
+ # inflow_template('Normalwraplink') # TODO: tricky
77
+
78
+ # https://en.wikipedia.org/wiki/Category:List_formatting_and_function_templates
79
+ # -----------------------------------------------------------------------------
80
+ # NB: it's enough for most cases to have all list-representing templates
81
+ # just navigable inside and rendered as space-separated list of entries
82
+ show(
83
+ 'Br separated entries',
84
+ 'Bulleted list',
85
+ 'Collapsible list',
86
+ 'Comma separated entries',
87
+ 'Hlist',
88
+ 'Flatlist',
89
+ 'Flowlist',
90
+ 'Pagelist',
91
+ 'Ordered list',
92
+ 'Plainlist',
93
+ 'Space separated entries',
94
+ 'Toolbar',
95
+ )
96
+
97
+ # https://en.wikipedia.org/wiki/Category:Wikipedia_XHTML_tag-replacing_templates
98
+ # ------------------------------------------------------------------------------
99
+
100
+ show(
101
+ # Font size
102
+ 'Small',
103
+ 'Smaller',
104
+ 'Midsize',
105
+ 'Larger',
106
+ 'Big',
107
+ 'Large',
108
+ 'Huge',
109
+
110
+ # Align
111
+ 'left',
112
+ 'Center',
113
+ 'Right',
114
+
115
+ # Simple style
116
+ 'Em',
117
+ 'Kbd',
118
+ 'Var',
119
+ 'Varserif',
120
+ 'Samp',
121
+ 'Strikethrough',
122
+ 'Strong',
123
+ 'Sub',
124
+ 'Sup',
125
+ 'Underline',
126
+
127
+ # FIXME: should do something wiser
128
+ 'Pre',
129
+ 'Pre2',
130
+ 'Code'
131
+ )
132
+
133
+ template 'Abbr' do
134
+ def children
135
+ fetch('1')
136
+ end
137
+ end
138
+ # TODO: has aliases: {{Define}}, {{Explain}}, {{Tooltip}}
139
+
140
+ template 'Align' do
141
+ def children
142
+ fetch('2')
143
+ end
144
+ end
145
+
146
+ template 'Dfn' do
147
+ def children
148
+ fetch('1')
149
+ end
150
+ end
151
+
152
+ template 'Resize' do
153
+ def children
154
+ unnamed_variables.count < 2 ? fetch('1') : fetch('2')
155
+ end
156
+ end
157
+
158
+ template 'Font' do
159
+ def children
160
+ res = fetch('text')
161
+ res.empty? ? fetch('1') : res
162
+ end
163
+ end
164
+
165
+ # https://en.wikipedia.org/wiki/Category:Text_color_templates
166
+ show(
167
+ 'white', 'silver (color)', 'gray', 'black', 'pink', 'red', 'darkred',
168
+ 'maroon', 'brown', 'orange (color)', 'gold (color)', 'yellow', 'olive',
169
+ 'lime', 'green', 'aqua (color)', 'cyan', 'teal', 'blue', 'navy (color)',
170
+ 'purple', 'fuchsia', 'magenta'
171
+ )
172
+
173
+ # Some most popular templates, without categorical splitting
174
+ # https://en.wikipedia.org/wiki/Wikipedia:Database_reports/Templates_transcluded_on_the_most_pages
175
+ # ------------------------------------------------------------------------------------------------
176
+ # Currently scanned by eyes up to 250-th line, which is used in 130549 articles, according to the
177
+ # page - which, though, is dramatically outdated.
178
+
179
+ template 'Stub', match: /-stub$/ do
180
+ def stub?
181
+ true
182
+ end
183
+ end
184
+
185
+ template 'Infobox', match: /^Infobox/i do
186
+ def infobox?
187
+ true
188
+ end
189
+ end
190
+
191
+ template 'Coord' do
192
+ def model
193
+ @model ||= begin
194
+ npos = lookup_children(text: /^N|S$/).first.index rescue nil
195
+ case npos
196
+ when 1
197
+ :decimal
198
+ when 2
199
+ :min
200
+ when 3
201
+ :sec
202
+ else
203
+ :decimal_sign
204
+ end
205
+ end
206
+ end
207
+
208
+ def lat
209
+ case model
210
+ when :decimal
211
+ '%s°%s′%s' % fetch('1', '2').map(&:text)
212
+ when :decimal_sign
213
+ fetch('1').text
214
+ when :min
215
+ '%s°%s′%s' % fetch('1', '2', '3').map(&:text)
216
+ when :sec
217
+ '%s°%s′%s″%s' % fetch('1', '2', '3', '4').map(&:text)
218
+ end
219
+ end
220
+
221
+ def lng
222
+ case model
223
+ when :decimal, :decimal_sign
224
+ fetch('1').text
225
+ when :min
226
+ '%s°%s′%s' % fetch('1', '2', '3').map(&:text)
227
+ when :sec
228
+ '%s°%s′%s″%s' % fetch('1', '2', '3', '4').map(&:text)
229
+ end
230
+ end
231
+ end
232
+
233
+ template 'Convert' do
234
+ def value1
235
+ fetch('1').text
236
+ end
237
+
238
+ ALLOW_BETWEEN = ['-;', '–',
239
+ 'and', '&', 'and(-)', ', and',
240
+ 'or', ', or',
241
+ 'to', 'to(-)', 'to about',
242
+ '+/-', '±', '+',
243
+ 'by', 'x', '×', 'x',
244
+ ]
245
+
246
+ def between
247
+ ALLOW_BETWEEN.include?(fetch('2').text) ? fetch('2').text : nil
248
+ end
249
+
250
+ def value2
251
+ between ? fetch('3').text : nil
252
+ end
253
+
254
+ def measure_from
255
+ between ? fetch('4').text : fetch('2').text
256
+ end
257
+
258
+ def measure_to
259
+ between ? fetch('5').text : fetch('3').text
260
+ end
261
+
262
+ def text
263
+ [value1, between, value2, measure_from].compact.join(' ')
264
+ end
265
+ end
266
+
267
+ template 'Age' do
268
+ def from
269
+ fetch_date('1', '2', '3')
270
+ end
271
+
272
+ def to
273
+ fetch_date('4', '5', '6') || Date.today
274
+ end
275
+
276
+ def value
277
+ (to - from).to_i / 365 # FIXME: obviously
278
+ end
279
+
280
+ def text
281
+ "#{value} years"
282
+ end
283
+ end
284
+
285
+ template 'Birth date and age' do
286
+ def date
287
+ fetch_date('1', '2', '3')
288
+ end
289
+
290
+ def text
291
+ date.to_s
292
+ end
293
+ end
294
+ # TODO: aliased as bda
295
+
296
+ template 'Birth date' do
297
+ def date
298
+ fetch_date('1', '2', '3')
299
+ end
300
+
301
+ def text
302
+ date.to_s
303
+ end
304
+ end
305
+ # TODO: aliased as dob
306
+
307
+ template 'Time ago' do
308
+ def text
309
+ str = fetch('1').text
310
+ begin
311
+ date = Date.parse(str)
312
+ "#{(Date.today - date).to_i} days ago" # not trying complext time_distance_in_words formatting here
313
+ rescue ArgumentError
314
+ str
315
+ end
316
+ end
317
+ end
318
+
319
+ template 'Flagcountry' do # very popular instead of country name
320
+ def children
321
+ fetch('1')
322
+ end
323
+ end
324
+
325
+ template 'Flag' do # very popular instead of country name
326
+ def children
327
+ fetch('1')
328
+ end
329
+ end
330
+
331
+ show 'Plural'
332
+
333
+ template 'URL' do
334
+ def children
335
+ unnamed_variables.count > 1 ? fetch('2') : fetch('1')
336
+ end
337
+ end
338
+
339
+ # TODO: extremely popular:
340
+ # Str left - https://en.wikipedia.org/wiki/Category:String_manipulation_templates
341
+ # Rnd - https://en.wikipedia.org/wiki/Category:Mathematical_function_templates
342
+
343
+ # TODO: useful categories
344
+ # https://en.wikipedia.org/wiki/Category:Date_mathematics_templates
345
+ # https://en.wikipedia.org/wiki/Category:Mathematical_function_templates
346
+ # https://en.wikipedia.org/wiki/Category:Wikipedia_formatting_and_function_templates
347
+ # https://en.wikipedia.org/wiki/Category:Semantic_markup_templates
348
+ # https://en.wikipedia.org/wiki/Category:Quotation_templates
349
+ # https://en.wikipedia.org/wiki/Category:Typing-aid_templates
350
+ # https://en.wikipedia.org/wiki/Category:Inline_spacing_templates
351
+ # https://en.wikipedia.org/wiki/Category:Sorting_templates
352
+ # https://en.wikipedia.org/wiki/Wikipedia:Database_reports/Templates_transcluded_on_the_most_pages
353
+ end
354
+ end
355
+ end