infoboxer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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