motion-markdown-it 0.4.0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +243 -0
  3. data/lib/motion-markdown-it.rb +71 -0
  4. data/lib/motion-markdown-it/common/entities.rb +1084 -0
  5. data/lib/motion-markdown-it/common/html_blocks.rb +60 -0
  6. data/lib/motion-markdown-it/common/html_re.rb +28 -0
  7. data/lib/motion-markdown-it/common/string.rb +14 -0
  8. data/lib/motion-markdown-it/common/url_schemas.rb +173 -0
  9. data/lib/motion-markdown-it/common/utils.rb +216 -0
  10. data/lib/motion-markdown-it/helpers/parse_link_destination.rb +75 -0
  11. data/lib/motion-markdown-it/helpers/parse_link_label.rb +51 -0
  12. data/lib/motion-markdown-it/helpers/parse_link_title.rb +48 -0
  13. data/lib/motion-markdown-it/index.rb +507 -0
  14. data/lib/motion-markdown-it/parser_block.rb +113 -0
  15. data/lib/motion-markdown-it/parser_core.rb +46 -0
  16. data/lib/motion-markdown-it/parser_inline.rb +121 -0
  17. data/lib/motion-markdown-it/presets/commonmark.rb +76 -0
  18. data/lib/motion-markdown-it/presets/default.rb +42 -0
  19. data/lib/motion-markdown-it/presets/zero.rb +59 -0
  20. data/lib/motion-markdown-it/renderer.rb +286 -0
  21. data/lib/motion-markdown-it/ruler.rb +327 -0
  22. data/lib/motion-markdown-it/rules_block/blockquote.rb +138 -0
  23. data/lib/motion-markdown-it/rules_block/code.rb +35 -0
  24. data/lib/motion-markdown-it/rules_block/fence.rb +94 -0
  25. data/lib/motion-markdown-it/rules_block/heading.rb +56 -0
  26. data/lib/motion-markdown-it/rules_block/hr.rb +45 -0
  27. data/lib/motion-markdown-it/rules_block/html_block.rb +73 -0
  28. data/lib/motion-markdown-it/rules_block/lheading.rb +54 -0
  29. data/lib/motion-markdown-it/rules_block/list.rb +242 -0
  30. data/lib/motion-markdown-it/rules_block/paragraph.rb +51 -0
  31. data/lib/motion-markdown-it/rules_block/reference.rb +161 -0
  32. data/lib/motion-markdown-it/rules_block/state_block.rb +184 -0
  33. data/lib/motion-markdown-it/rules_block/table.rb +161 -0
  34. data/lib/motion-markdown-it/rules_core/block.rb +20 -0
  35. data/lib/motion-markdown-it/rules_core/inline.rb +20 -0
  36. data/lib/motion-markdown-it/rules_core/linkify.rb +138 -0
  37. data/lib/motion-markdown-it/rules_core/normalize.rb +44 -0
  38. data/lib/motion-markdown-it/rules_core/replacements.rb +90 -0
  39. data/lib/motion-markdown-it/rules_core/smartquotes.rb +158 -0
  40. data/lib/motion-markdown-it/rules_core/state_core.rb +20 -0
  41. data/lib/motion-markdown-it/rules_inline/autolink.rb +74 -0
  42. data/lib/motion-markdown-it/rules_inline/backticks.rb +51 -0
  43. data/lib/motion-markdown-it/rules_inline/emphasis.rb +172 -0
  44. data/lib/motion-markdown-it/rules_inline/entity.rb +51 -0
  45. data/lib/motion-markdown-it/rules_inline/escape.rb +55 -0
  46. data/lib/motion-markdown-it/rules_inline/html_inline.rb +49 -0
  47. data/lib/motion-markdown-it/rules_inline/image.rb +158 -0
  48. data/lib/motion-markdown-it/rules_inline/link.rb +153 -0
  49. data/lib/motion-markdown-it/rules_inline/newline.rb +47 -0
  50. data/lib/motion-markdown-it/rules_inline/state_inline.rb +57 -0
  51. data/lib/motion-markdown-it/rules_inline/strikethrough.rb +130 -0
  52. data/lib/motion-markdown-it/rules_inline/text.rb +94 -0
  53. data/lib/motion-markdown-it/token.rb +134 -0
  54. data/lib/motion-markdown-it/version.rb +5 -0
  55. data/spec/motion-markdown-it/bench_mark_spec.rb +44 -0
  56. data/spec/motion-markdown-it/commonmark_spec.rb +16 -0
  57. data/spec/motion-markdown-it/markdown_it_spec.rb +18 -0
  58. data/spec/motion-markdown-it/misc_spec.rb +277 -0
  59. data/spec/motion-markdown-it/ruler_spec.rb +153 -0
  60. data/spec/motion-markdown-it/testgen_helper.rb +68 -0
  61. data/spec/motion-markdown-it/token_spec.rb +17 -0
  62. data/spec/motion-markdown-it/utils_spec.rb +82 -0
  63. data/spec/spec_helper.rb +6 -0
  64. metadata +158 -0
@@ -0,0 +1,60 @@
1
+ # List of valid html blocks names, accorting to commonmark spec
2
+ # http://jgm.github.io/CommonMark/spec.html#html-blocks
3
+ #------------------------------------------------------------------------------
4
+ module MarkdownIt
5
+ HTML_BLOCKS = {}
6
+
7
+ [
8
+ 'article',
9
+ 'aside',
10
+ 'button',
11
+ 'blockquote',
12
+ 'body',
13
+ 'canvas',
14
+ 'caption',
15
+ 'col',
16
+ 'colgroup',
17
+ 'dd',
18
+ 'div',
19
+ 'dl',
20
+ 'dt',
21
+ 'embed',
22
+ 'fieldset',
23
+ 'figcaption',
24
+ 'figure',
25
+ 'footer',
26
+ 'form',
27
+ 'h1',
28
+ 'h2',
29
+ 'h3',
30
+ 'h4',
31
+ 'h5',
32
+ 'h6',
33
+ 'header',
34
+ 'hgroup',
35
+ 'hr',
36
+ 'iframe',
37
+ 'li',
38
+ 'map',
39
+ 'object',
40
+ 'ol',
41
+ 'output',
42
+ 'p',
43
+ 'pre',
44
+ 'progress',
45
+ 'script',
46
+ 'section',
47
+ 'style',
48
+ 'table',
49
+ 'tbody',
50
+ 'td',
51
+ 'textarea',
52
+ 'tfoot',
53
+ 'th',
54
+ 'tr',
55
+ 'thead',
56
+ 'ul',
57
+ 'video'
58
+ ].each { |name| HTML_BLOCKS[name] = true }
59
+
60
+ end
@@ -0,0 +1,28 @@
1
+ # Regexps to match html elements
2
+ #------------------------------------------------------------------------------
3
+ module MarkdownIt
4
+ module Common
5
+ module HtmlRe
6
+ ATTR_NAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*'
7
+
8
+ UNQUOTED = '[^"\'=<>`\\x00-\\x20]+'
9
+ SINGLE_QUOTED = "'[^']*'"
10
+ DOUBLE_QUOTED = '"[^"]*"';
11
+
12
+ ATTR_VALUE = '(?:' + UNQUOTED + '|' + SINGLE_QUOTED + '|' + DOUBLE_QUOTED + ')'
13
+
14
+ ATTRIBUTE = '(?:\\s+' + ATTR_NAME + '(?:\\s*=\\s*' + ATTR_VALUE + ')?)'
15
+
16
+ OPEN_TAG = '<[A-Za-z][A-Za-z0-9\\-]*' + ATTRIBUTE + '*\\s*\\/?>'
17
+
18
+ CLOSE_TAG = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>'
19
+ COMMENT = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->'
20
+ PROCESSING = '<[?].*?[?]>'
21
+ DECLARATION = '<![A-Z]+\\s+[^>]*>'
22
+ CDATA = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>'
23
+
24
+ HTML_TAG_RE = Regexp.new('^(?:' + OPEN_TAG + '|' + CLOSE_TAG + '|' + COMMENT +
25
+ '|' + PROCESSING + '|' + DECLARATION + '|' + CDATA + ')')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ class String
2
+
3
+ # grab the remainder of the string starting at 'start'
4
+ #------------------------------------------------------------------------------
5
+ def slice_to_end(start)
6
+ self.slice(start...self.length)
7
+ end
8
+
9
+ # port of Javascript function charCodeAt
10
+ #------------------------------------------------------------------------------
11
+ def charCodeAt(ch)
12
+ self[ch].ord unless self[ch].nil?
13
+ end
14
+ end
@@ -0,0 +1,173 @@
1
+ # List of valid url schemas, accorting to commonmark spec
2
+ # http://jgm.github.io/CommonMark/spec.html#autolinks
3
+ #------------------------------------------------------------------------------
4
+ module MarkdownIt
5
+
6
+ URL_SCHEMAS = [
7
+ 'coap',
8
+ 'doi',
9
+ 'javascript',
10
+ 'aaa',
11
+ 'aaas',
12
+ 'about',
13
+ 'acap',
14
+ 'cap',
15
+ 'cid',
16
+ 'crid',
17
+ 'data',
18
+ 'dav',
19
+ 'dict',
20
+ 'dns',
21
+ 'file',
22
+ 'ftp',
23
+ 'geo',
24
+ 'go',
25
+ 'gopher',
26
+ 'h323',
27
+ 'http',
28
+ 'https',
29
+ 'iax',
30
+ 'icap',
31
+ 'im',
32
+ 'imap',
33
+ 'info',
34
+ 'ipp',
35
+ 'iris',
36
+ 'iris.beep',
37
+ 'iris.xpc',
38
+ 'iris.xpcs',
39
+ 'iris.lwz',
40
+ 'ldap',
41
+ 'mailto',
42
+ 'mid',
43
+ 'msrp',
44
+ 'msrps',
45
+ 'mtqp',
46
+ 'mupdate',
47
+ 'news',
48
+ 'nfs',
49
+ 'ni',
50
+ 'nih',
51
+ 'nntp',
52
+ 'opaquelocktoken',
53
+ 'pop',
54
+ 'pres',
55
+ 'rtsp',
56
+ 'service',
57
+ 'session',
58
+ 'shttp',
59
+ 'sieve',
60
+ 'sip',
61
+ 'sips',
62
+ 'sms',
63
+ 'snmp',
64
+ 'soap.beep',
65
+ 'soap.beeps',
66
+ 'tag',
67
+ 'tel',
68
+ 'telnet',
69
+ 'tftp',
70
+ 'thismessage',
71
+ 'tn3270',
72
+ 'tip',
73
+ 'tv',
74
+ 'urn',
75
+ 'vemmi',
76
+ 'ws',
77
+ 'wss',
78
+ 'xcon',
79
+ 'xcon-userid',
80
+ 'xmlrpc.beep',
81
+ 'xmlrpc.beeps',
82
+ 'xmpp',
83
+ 'z39.50r',
84
+ 'z39.50s',
85
+ 'adiumxtra',
86
+ 'afp',
87
+ 'afs',
88
+ 'aim',
89
+ 'apt',
90
+ 'attachment',
91
+ 'aw',
92
+ 'beshare',
93
+ 'bitcoin',
94
+ 'bolo',
95
+ 'callto',
96
+ 'chrome',
97
+ 'chrome-extension',
98
+ 'com-eventbrite-attendee',
99
+ 'content',
100
+ 'cvs',
101
+ 'dlna-playsingle',
102
+ 'dlna-playcontainer',
103
+ 'dtn',
104
+ 'dvb',
105
+ 'ed2k',
106
+ 'facetime',
107
+ 'feed',
108
+ 'finger',
109
+ 'fish',
110
+ 'gg',
111
+ 'git',
112
+ 'gizmoproject',
113
+ 'gtalk',
114
+ 'hcp',
115
+ 'icon',
116
+ 'ipn',
117
+ 'irc',
118
+ 'irc6',
119
+ 'ircs',
120
+ 'itms',
121
+ 'jar',
122
+ 'jms',
123
+ 'keyparc',
124
+ 'lastfm',
125
+ 'ldaps',
126
+ 'magnet',
127
+ 'maps',
128
+ 'market',
129
+ 'message',
130
+ 'mms',
131
+ 'ms-help',
132
+ 'msnim',
133
+ 'mumble',
134
+ 'mvn',
135
+ 'notes',
136
+ 'oid',
137
+ 'palm',
138
+ 'paparazzi',
139
+ 'platform',
140
+ 'proxy',
141
+ 'psyc',
142
+ 'query',
143
+ 'res',
144
+ 'resource',
145
+ 'rmi',
146
+ 'rsync',
147
+ 'rtmp',
148
+ 'secondlife',
149
+ 'sftp',
150
+ 'sgn',
151
+ 'skype',
152
+ 'smb',
153
+ 'soldat',
154
+ 'spotify',
155
+ 'ssh',
156
+ 'steam',
157
+ 'svn',
158
+ 'teamspeak',
159
+ 'things',
160
+ 'udp',
161
+ 'unreal',
162
+ 'ut2004',
163
+ 'ventrilo',
164
+ 'view-source',
165
+ 'webcal',
166
+ 'wtai',
167
+ 'wyciwyg',
168
+ 'xfire',
169
+ 'xri',
170
+ 'ymsgr'
171
+ ]
172
+
173
+ end
@@ -0,0 +1,216 @@
1
+ module MarkdownIt
2
+ module Common
3
+ module Utils
4
+
5
+ # Merge multiple hashes
6
+ #------------------------------------------------------------------------------
7
+ def assign(obj, *args)
8
+ raise(ArgumentError, "#{obj} must be a Hash") if !obj.is_a?(Hash)
9
+
10
+ args.each do |source|
11
+ next if source.nil?
12
+ raise(ArgumentError, "#{source} must be a Hash") if !source.is_a?(Hash)
13
+ obj.merge!(source)
14
+ end
15
+
16
+ return obj
17
+ end
18
+
19
+ # Remove element from array and put another array at those position.
20
+ # Useful for some operations with tokens
21
+ #------------------------------------------------------------------------------
22
+ def arrayReplaceAt(src, pos, newElements)
23
+ return [].concat([src.slice(0...pos), newElements, src.slice_to_end(pos + 1)])
24
+ end
25
+
26
+ #------------------------------------------------------------------------------
27
+ def isValidEntityCode(c)
28
+ # broken sequence
29
+ return false if (c >= 0xD800 && c <= 0xDFFF)
30
+
31
+ # never used
32
+ return false if (c >= 0xFDD0 && c <= 0xFDEF)
33
+ return false if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE)
34
+
35
+ # control codes
36
+ return false if (c >= 0x00 && c <= 0x08)
37
+ return false if (c === 0x0B)
38
+ return false if (c >= 0x0E && c <= 0x1F)
39
+ return false if (c >= 0x7F && c <= 0x9F)
40
+
41
+ # out of range
42
+ return false if (c > 0x10FFFF)
43
+
44
+ return true
45
+ end
46
+
47
+ #------------------------------------------------------------------------------
48
+ def fromCodePoint(c)
49
+ c.chr(Encoding::UTF_8)
50
+ end
51
+
52
+
53
+ UNESCAPE_MD_RE = /\\([\!\"\#\$\%\&\'\(\)\*\+\,\-.\/:;<=>?@\[\\\]^_`{|}~])/
54
+
55
+ ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/i
56
+ UNESCAPE_ALL_RE = Regexp.new(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'i')
57
+
58
+ DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i
59
+
60
+ #------------------------------------------------------------------------------
61
+ def replaceEntityPattern(match, name)
62
+ code = 0
63
+
64
+ return HTMLEntities::MAPPINGS[name].chr(Encoding::UTF_8) if HTMLEntities::MAPPINGS[name]
65
+
66
+ if (name.charCodeAt(0) == 0x23 && DIGITAL_ENTITY_TEST_RE =~ name) # '#'
67
+ code = name[1].downcase == 'x' ? name.slice_to_end(2).to_i(16) : name.slice_to_end(1).to_i
68
+ if (isValidEntityCode(code))
69
+ return fromCodePoint(code)
70
+ end
71
+ end
72
+
73
+ return match
74
+ end
75
+
76
+ # not used
77
+ #------------------------------------------------------------------------------
78
+ # def replaceEntities(str)
79
+ # return str if str.index('&').nil?
80
+ # return str.gsub(ENTITY_RE, replaceEntityPattern)
81
+ # end
82
+
83
+ #------------------------------------------------------------------------------
84
+ def unescapeMd(str)
85
+ return str if !str.include?('\\')
86
+ return str.gsub(UNESCAPE_MD_RE, '\1')
87
+ end
88
+
89
+ #------------------------------------------------------------------------------
90
+ def unescapeAll(str)
91
+ return str if (str.index('\\').nil? && str.index('&').nil?)
92
+
93
+ return str.gsub(UNESCAPE_ALL_RE) do |match|
94
+ next $1 if ($1)
95
+ next replaceEntityPattern(match, $2)
96
+ end
97
+ end
98
+
99
+
100
+ HTML_ESCAPE_TEST_RE = /[&<>"]/
101
+ HTML_ESCAPE_REPLACE_RE = /[&<>"]/
102
+ HTML_REPLACEMENTS = {
103
+ '&' => '&amp;',
104
+ '<' => '&lt;',
105
+ '>' => '&gt;',
106
+ '"' => '&quot;'
107
+ }
108
+
109
+ #------------------------------------------------------------------------------
110
+ def escapeHtml(str)
111
+ if HTML_ESCAPE_TEST_RE =~ str
112
+ return str.gsub(HTML_ESCAPE_REPLACE_RE, HTML_REPLACEMENTS)
113
+ end
114
+ return str
115
+ end
116
+
117
+ REGEXP_ESCAPE_RE = /[.?*+^$\[\]\\(){}|-]/
118
+
119
+ #------------------------------------------------------------------------------
120
+ def escapeRE(str)
121
+ str.gsub(REGEXP_ESCAPE_RE) {|s| '\\' + s}
122
+ end
123
+
124
+
125
+ # Zs (unicode class) || [\t\f\v\r\n]
126
+ #------------------------------------------------------------------------------
127
+ def isWhiteSpace(code)
128
+ return true if (code >= 0x2000 && code <= 0x200A)
129
+ case code
130
+ when 0x09, # \t
131
+ 0x0A, # \n
132
+ 0x0B, # \v
133
+ 0x0C, # \f
134
+ 0x0D, # \r
135
+ 0x20,
136
+ 0xA0,
137
+ 0x1680,
138
+ 0x202F,
139
+ 0x205F,
140
+ 0x3000
141
+ return true
142
+ end
143
+ return false
144
+ end
145
+
146
+ # from file uc.micro/categories/P/regex in github project
147
+ # https://github.com/markdown-it/uc.micro
148
+ # UNICODE_PUNCT_RE = /[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDE38-\uDE3D]|\uD805[\uDCC6\uDDC1-\uDDC9\uDE41-\uDE43]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F/
149
+ # was unable to get abouve to work TODO
150
+ UNICODE_PUNCT_RE = /[!-#%-\*,-\/:;\?@\[-\]_\{\}]/
151
+
152
+ # Currently without astral characters support.
153
+ #------------------------------------------------------------------------------
154
+ def isPunctChar(char)
155
+ return UNICODE_PUNCT_RE =~ char
156
+ end
157
+
158
+
159
+ # Markdown ASCII punctuation characters.
160
+ #
161
+ # !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
162
+ # http://spec.commonmark.org/0.15/#ascii-punctuation-character
163
+ #
164
+ # Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.
165
+ #------------------------------------------------------------------------------
166
+ def isMdAsciiPunct(ch)
167
+ case ch
168
+ when 0x21, # !
169
+ 0x22, # "
170
+ 0x23, # #
171
+ 0x24, # $
172
+ 0x25, # %
173
+ 0x26, # &
174
+ 0x27, # '
175
+ 0x28, # (
176
+ 0x29, # )
177
+ 0x2A, # *
178
+ 0x2B, # +
179
+ 0x2C, # ,
180
+ 0x2D, # -
181
+ 0x2E, # .
182
+ 0x2F, # /
183
+ 0x3A, # :
184
+ 0x3B, # ;
185
+ 0x3C, # <
186
+ 0x3D, # =
187
+ 0x3E, # >
188
+ 0x3F, # ?
189
+ 0x40, # @
190
+ 0x5B, # [
191
+ 0x5C, # \
192
+ 0x5D, # ]
193
+ 0x5E, # ^
194
+ 0x5F, # _
195
+ 0x60, # `
196
+ 0x7B, # {
197
+ 0x7C, # |
198
+ 0x7D, # }
199
+ 0x7E # ~
200
+ return true
201
+ else
202
+ return false
203
+ end
204
+ end
205
+
206
+ # Hepler to unify [reference labels].
207
+ #------------------------------------------------------------------------------
208
+ def normalizeReference(str)
209
+ # use .toUpperCase() instead of .toLowerCase()
210
+ # here to avoid a conflict with Object.prototype
211
+ # members (most notably, `__proto__`)
212
+ return str.strip.gsub(/\s+/, ' ').upcase
213
+ end
214
+ end
215
+ end
216
+ end