linkify-it-rb 2.0.3 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 176768c4d108c26b13260d1e62c1cb30cd0491f5
4
- data.tar.gz: a47bd97acdf25582ce67d65551a1d94678d56aa3
2
+ SHA256:
3
+ metadata.gz: 68c5de781544ec81b757b1099b8c24643449e121546d03cdda5da57d6b033afb
4
+ data.tar.gz: 9534d8d1a44ec68d531dea91df209b391d46aee363b04f2d0c30969debd77bf7
5
5
  SHA512:
6
- metadata.gz: 1cbcc4a1e42a24df990484e927b1049a81ff87a8bd0a53f43d32f9d0687ec2bcfb2ec81778e1fbd4a33e11c9e41796e4787d84b8f3f55461ed853dfe4b40c05e
7
- data.tar.gz: 5b25b74826e53b4257fdc2b4ea1b0422659d44c9ec69e877ee37b396d9597654db71811d2593193552785cdb8a71258485d4a57a6447b2036cbf324386d0380f
6
+ metadata.gz: 96664d9ffb34ac85e7038394dd9e1504625ae4ce87e5498ec62c0b698cb9ddbcae780a3f966a0c77abeca1c533ef5ce1984195d1d1e14b54bfcb563b7972255d
7
+ data.tar.gz: 4194118a1da63b10a827aca05f57254debee07759a06b25a5b0b71d1928be0669c92416afb76950c85fa85455ef944b0b2008d789254ad04ac254052a8805b34
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # linkify-it-rb
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/linkify-it-rb.svg)](http://badge.fury.io/rb/linkify-it-rb)
4
- [![Build Status](https://travis-ci.org/digitalmoksha/linkify-it-rb.svg?branch=master)](https://travis-ci.org/digitalmoksha/linkify-it-rb)
4
+ [![Build Status](https://github.com/digitalmoksha/linkify-it-rb/actions/workflows/ci.yml/badge.svg)](https://github.com/digitalmoksha/linkify-it-rb/actions/workflows/ci.yml)
5
5
 
6
6
  This gem is a port of the [linkify-it javascript package](https://github.com/markdown-it/linkify-it) by Vitaly Puzrin, that is used for the [markdown-it](https://github.com/markdown-it/markdown-it) package.
7
7
 
8
- _Currently synced with linkify-it 2.0.3_
8
+ _Currently synced with linkify-it 4.0.1_
9
9
 
10
10
  ---
11
11
 
@@ -53,8 +53,8 @@ linkify = Linkify.new
53
53
 
54
54
  # Reload full tlds list & add unofficial `.onion` domain.
55
55
  linkify.tlds('onion', true) # Add unofficial `.onion` domain
56
- linkify.add('git:', 'http:') # Add `git:` ptotocol as "alias"
57
- linkify.add('ftp:', null) # Disable `ftp:` ptotocol
56
+ linkify.add('git:', 'http:') # Add `git:` protocol as "alias"
57
+ linkify.add('ftp:', null) # Disable `ftp:` protocol
58
58
  linkify.set({fuzzyIP: true}) # Enable IPs in fuzzy links (without schema)
59
59
 
60
60
  linkify.test('Site github.com!'))
@@ -106,8 +106,11 @@ By default understands:
106
106
  - __value__ - rule to check tail after link prefix
107
107
  - _String_ - just alias to existing rule
108
108
  - _Hash_
109
- - _validate_ - validator block (should return matched length on success),
110
- or `RegExp`.
109
+ - _validate_ - either a `RegExp (start with `^`, and don't include the
110
+ link prefix itself), or a validator block which, given arguments,
111
+ _text_, _pos_, and _self_, returns the length of a match in _text_
112
+ starting at index _pos_. _pos_ is the index right after the link prefix.
113
+ _self_ can be used to access the linkify object to cache data.
111
114
  - _normalize_ - optional block to normalize text & url of matched result
112
115
  (for example, for twitter mentions).
113
116
 
@@ -152,6 +155,11 @@ Each match has:
152
155
  - __text__ - normalized text
153
156
  - __url__ - link, generated from matched text
154
157
 
158
+ ### .matchAtStart(text)
159
+
160
+ Checks if a match exists at the start of the string. Returns `Match`
161
+ (see docs for `match(text)`) or nil if no URL is at the start.
162
+ Doesn't work with fuzzy links.
155
163
 
156
164
  ### .tlds(list[, keepOld])
157
165
 
@@ -162,12 +170,15 @@ to avoid false positives. By default this algorithm uses:
162
170
  - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф are ok.
163
171
  - encoded (`xn--...`) root zones are ok.
164
172
 
165
- If that's not enougth, you can reload defaults with more detailed zones list.
173
+ If that's not enough, you can reload defaults with more detailed zones list.
166
174
 
167
- ### .add(schema, definition)
175
+ ### .add(key, value)
168
176
 
169
- Add new rule with `schema` prefix. For definition details see constructor
170
- description. To disable existing rule use `.add(name, nil)`
177
+ Add a new schema to the schemas object. As described in the constructor
178
+ definition, `key` is a link prefix (`skype:`, for example), and `value`
179
+ is a String to alias to another schema, or an Object with `validate` and
180
+ optionally `normalize` definitions. To disable an existing rule, use
181
+ `.add(key, null)`.
171
182
 
172
183
  ### .set(options)
173
184
 
@@ -204,12 +204,14 @@ class Linkify
204
204
  slist = @__compiled__.select {|name, val| name.length > 0 && !val.nil? }.keys.map {|str| escapeRE(str)}.join('|')
205
205
 
206
206
  # (?!_) cause 1.5x slowdown
207
- @re[:schema_test] = Regexp.new('(^|(?!_)(?:[><\uff5c]|' + @re[:src_XPCc] + '))(' + slist + ')', 'i')
208
- @re[:schema_search] = Regexp.new('(^|(?!_)(?:[><\uff5c]|' + @re[:src_XPCc] + '))(' + slist + ')', 'ig')
207
+ @re[:schema_test] = Regexp.new('(^|(?!_)(?:[><\uff5c]|' + @re[:src_XPCc] + '))(' + slist + ')', 'i')
208
+ @re[:schema_search] = Regexp.new('(^|(?!_)(?:[><\uff5c]|' + @re[:src_XPCc] + '))(' + slist + ')', 'i')
209
+ @re[:schema_at_start] = Regexp.new('^' + @re[:schema_search].source, 'i')
209
210
 
210
- @re[:pretest] = Regexp.new(
211
- '(' + @re[:schema_test].source + ')|' +
212
- '(' + @re[:host_fuzzy_test].source + ')|' + '@', 'i')
211
+ @re[:pretest] = Regexp.new(
212
+ '(' + @re[:schema_test].source + ')|(' + @re[:host_fuzzy_test].source + ')|@',
213
+ 'i'
214
+ )
213
215
 
214
216
  #
215
217
  # Cleanup
@@ -505,6 +507,30 @@ class Linkify
505
507
  return nil
506
508
  end
507
509
 
510
+ # LinkifyIt#matchAtStart(text) -> Match|null
511
+ #
512
+ # Returns fully-formed (not fuzzy) link if it starts at the beginning
513
+ # of the string, and null otherwise.
514
+ #------------------------------------------------------------------------------
515
+ def matchAtStart(text)
516
+ # Reset scan cache
517
+ @__text_cache__ = text
518
+ @__index__ = -1
519
+
520
+ return unless text.length
521
+
522
+ m = @re[:schema_at_start].match(text)
523
+ return nil unless m
524
+
525
+ len = testSchemaAt(text, m[2], m[0].length)
526
+ return nil unless len > 0
527
+
528
+ @__schema__ = m[2];
529
+ @__index__ = m.begin(0) + m[1].length
530
+ @__last_index__ = m.begin(0) + m[0].length + len
531
+
532
+ return Match.createMatch(self, 0)
533
+ end
508
534
 
509
535
  # chainable
510
536
  # LinkifyIt#tlds(list [, keepOld]) -> this
@@ -561,4 +587,4 @@ class Linkify
561
587
  def onCompile
562
588
  end
563
589
 
564
- end
590
+ end
@@ -32,11 +32,13 @@ module LinkifyRe
32
32
 
33
33
  SRC_PORT = '(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?'
34
34
 
35
- SRC_HOST_TERMINATOR = '(?=$|' + TEXT_SEPARATORS + '|' + SRC_Z_P_CC + ')(?!-|_|:\\d|\\.-|\\.(?!$|' + SRC_Z_P_CC + '))'
35
+ # moved SRC_HOST_TERMINATOR into re_src_host_terminator
36
36
 
37
37
  # moved SRC_PATH into re_src_path
38
38
 
39
- SRC_EMAIL_NAME = '[\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]+'
39
+ # Allow anything in markdown spec, forbid quote (") at the first position
40
+ # because emails enclosed in quotes are far more common
41
+ SRC_EMAIL_NAME = '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*'
40
42
  SRC_XN = 'xn--[a-z0-9\\-]{1,59}'
41
43
 
42
44
  # More to read about domain names
@@ -56,10 +58,7 @@ module LinkifyRe
56
58
  '|' +
57
59
  '(?:' + SRC_PSEUDO_LETTER + ')' +
58
60
  '|' +
59
- # don't allow `--` in domain names, because:
60
- # - that can conflict with markdown &mdash; / &ndash;
61
- # - nobody use those anyway
62
- '(?:' + SRC_PSEUDO_LETTER + '(?:-(?!-)|' + SRC_PSEUDO_LETTER + '){0,61}' + SRC_PSEUDO_LETTER + ')' +
61
+ '(?:' + SRC_PSEUDO_LETTER + '(?:-|' + SRC_PSEUDO_LETTER + '){0,61}' + SRC_PSEUDO_LETTER + ')' +
63
62
  ')'
64
63
 
65
64
  SRC_HOST =
@@ -80,23 +79,16 @@ module LinkifyRe
80
79
  TPL_HOST_NO_IP_FUZZY =
81
80
  '(?:(?:(?:' + SRC_DOMAIN + ')\\.)+(?:%TLDS%))'
82
81
 
83
- SRC_HOST_STRICT = SRC_HOST + SRC_HOST_TERMINATOR
84
- TPL_HOST_FUZZY_STRICT = TPL_HOST_FUZZY + SRC_HOST_TERMINATOR
85
- SRC_HOST_PORT_STRICT = SRC_HOST + SRC_PORT + SRC_HOST_TERMINATOR
86
- TPL_HOST_PORT_FUZZY_STRICT = TPL_HOST_FUZZY + SRC_PORT + SRC_HOST_TERMINATOR
87
- TPL_HOST_PORT_NO_IP_FUZZY_STRICT = TPL_HOST_NO_IP_FUZZY + SRC_PORT + SRC_HOST_TERMINATOR
88
-
89
82
  #------------------------------------------------------------------------------
90
83
  # Main rules
91
84
 
92
85
  # Rude test fuzzy links by host, for quick deny
93
86
  TPL_HOST_FUZZY_TEST = 'localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:' + SRC_Z_P_CC + '|>|$))'
94
- TPL_EMAIL_FUZZY = '(^|' + TEXT_SEPARATORS + '|\\(|' +SRC_Z_CC + ')(' + SRC_EMAIL_NAME + '@' + TPL_HOST_FUZZY_STRICT + ')'
95
87
 
96
88
  # moved TPL_LINK_FUZZY and TPL_LINK_NO_IP_FUZZY into build_re
97
89
 
98
90
  #------------------------------------------------------------------------------
99
- def build_re(opts)
91
+ def build_re(opts = {})
100
92
  re = {
101
93
  src_Any: SRC_ANY,
102
94
  src_Cc: SRC_CC,
@@ -108,7 +100,7 @@ module LinkifyRe
108
100
  src_ip4: SRC_IP4,
109
101
  src_auth: SRC_AUTH,
110
102
  src_port: SRC_PORT,
111
- src_host_terminator: SRC_HOST_TERMINATOR,
103
+ src_host_terminator: re_src_host_terminator(opts),
112
104
  src_path: re_src_path(opts),
113
105
  src_email_name: SRC_EMAIL_NAME,
114
106
  src_xn: SRC_XN,
@@ -118,60 +110,72 @@ module LinkifyRe
118
110
 
119
111
  tpl_host_fuzzy: TPL_HOST_FUZZY,
120
112
  tpl_host_no_ip_fuzzy: TPL_HOST_NO_IP_FUZZY,
121
- src_host_strict: SRC_HOST_STRICT,
122
- tpl_host_fuzzy_strict: TPL_HOST_FUZZY_STRICT,
123
- src_host_port_strict: SRC_HOST_PORT_STRICT,
124
- tpl_host_port_fuzzy_strict: TPL_HOST_PORT_FUZZY_STRICT,
125
- tpl_host_port_no_ip_fuzzy_strict: TPL_HOST_PORT_NO_IP_FUZZY_STRICT,
126
-
127
- tpl_host_fuzzy_test: TPL_HOST_FUZZY_TEST,
128
- tpl_email_fuzzy: TPL_EMAIL_FUZZY
113
+ src_host_strict: SRC_HOST + re_src_host_terminator(opts),
114
+ tpl_host_fuzzy_strict: TPL_HOST_FUZZY + re_src_host_terminator(opts),
115
+ src_host_port_strict: SRC_HOST + SRC_PORT + re_src_host_terminator(opts),
116
+ tpl_host_port_fuzzy_strict: TPL_HOST_FUZZY + SRC_PORT + re_src_host_terminator(opts),
117
+ tpl_host_port_no_ip_fuzzy_strict: TPL_HOST_NO_IP_FUZZY + SRC_PORT + re_src_host_terminator(opts),
118
+
119
+ tpl_host_fuzzy_test: TPL_HOST_FUZZY_TEST
129
120
  }
130
121
 
122
+ re[:tpl_email_fuzzy] =
123
+ '(^|' + TEXT_SEPARATORS + '|"|\\(|' + SRC_Z_CC + ')' +
124
+ '(' + SRC_EMAIL_NAME + '@' + re[:tpl_host_fuzzy_strict] + ')'
125
+
131
126
  # Fuzzy link can't be prepended with .:/\- and non punctuation.
132
127
  # but can start with > (markdown blockquote)
133
128
  re[:tpl_link_fuzzy] =
134
129
  '(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + SRC_Z_P_CC + '))' +
135
- '((?![$+<=>^`|\uff5c])' + TPL_HOST_PORT_FUZZY_STRICT + re[:src_path] + ')'
130
+ '((?![$+<=>^`|\uff5c])' + re[:tpl_host_port_fuzzy_strict] + re[:src_path] + ')'
136
131
 
137
132
  # Fuzzy link can't be prepended with .:/\- and non punctuation.
138
133
  # but can start with > (markdown blockquote)
139
134
  re[:tpl_link_no_ip_fuzzy] =
140
135
  '(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + SRC_Z_P_CC + '))' +
141
- '((?![$+<=>^`|\uff5c])' + TPL_HOST_PORT_NO_IP_FUZZY_STRICT + re[:src_path] + ')'
136
+ '((?![$+<=>^`|\uff5c])' + re[:tpl_host_port_no_ip_fuzzy_strict] + re[:src_path] + ')'
142
137
 
143
138
  return re
144
139
  end
145
140
 
146
141
  #------------------------------------------------------------------------------
147
- def re_src_path(opts = nil)
142
+ def re_src_path(opts = {})
148
143
  '(?:' +
149
144
  '[/?#]' +
150
145
  '(?:' +
151
- '(?!' + SRC_Z_CC + '|' + TEXT_SEPARATORS + '|[()\\[\\]{}.,"\'?!\\-]).|' +
146
+ '(?!' + SRC_Z_CC + '|' + TEXT_SEPARATORS + '|[()\\[\\]{}.,"\'?!\\-;]).|' +
152
147
  '\\[(?:(?!' + SRC_Z_CC + '|\\]).)*\\]|' +
153
148
  '\\((?:(?!' + SRC_Z_CC + '|[)]).)*\\)|' +
154
149
  '\\{(?:(?!' + SRC_Z_CC + '|[}]).)*\\}|' +
155
150
  '\\"(?:(?!' + SRC_Z_CC + '|["]).)+\\"|' +
156
151
  "\\'(?:(?!" + SRC_Z_CC + "|[']).)+\\'|" +
157
- "\\'(?=" + SRC_PSEUDO_LETTER + '|[-]).|' + # allow `I'm_king` if no pair found
158
- '\\.{2,3}[a-zA-Z0-9%/]|' + # github has ... in commit range links. Restrict to
152
+ "\\'(?=" + SRC_PSEUDO_LETTER + '|[-])|' + # allow `I'm_king` if no pair found
153
+ '\\.{2,}[a-zA-Z0-9%/&]|' + # google has many dots in "google search" links (#66, #81).
154
+ # github has ... in commit range links,
155
+ # Restrict to
159
156
  # - english
160
157
  # - percent-encoded
161
158
  # - parts of file path
159
+ # - params separator
162
160
  # until more examples found.
163
- '\\.(?!' + SRC_Z_CC + '|[.]).|' +
161
+ '\\.(?!' + SRC_Z_CC + '|[.]|$)|' +
164
162
  (opts && opts[:'---'] ?
165
163
  '\\-(?!--(?:[^-]|$))(?:-*)|' # `---` => long dash, terminate
166
164
  :
167
165
  '\\-+|'
168
166
  ) +
169
- '\\,(?!' + SRC_Z_CC + ').|' + # allow `,,,` in paths
170
- '\\!(?!' + SRC_Z_CC + '|[!]).|' +
171
- '\\?(?!' + SRC_Z_CC + '|[?]).' +
167
+ '\\,(?!' + SRC_Z_CC + '|$)|' + # allow `,,,` in paths
168
+ '\\;(?!' + SRC_Z_CC + '|$)|' + # allow `;` if not followed by space-like char
169
+ '\\!+(?!' + SRC_Z_CC + '|[!]|$)|' + # allow `!!!` in paths, but not at the end
170
+ '\\?(?!' + SRC_Z_CC + '|[?]|$)' +
172
171
  ')+' +
173
172
  '|\\/' +
174
173
  ')?'
175
- end
174
+ end
176
175
 
177
- end
176
+ #------------------------------------------------------------------------------
177
+ def re_src_host_terminator(opts = {})
178
+ '(?=$|' + TEXT_SEPARATORS + '|' + SRC_Z_P_CC + ')' +
179
+ '(?!' + (opts['---'] ? '-(?!--)|' : '-|') + '_|:\\d|\\.-|\\.(?!$|' + SRC_Z_P_CC + '))'
180
+ end
181
+ end
@@ -1,5 +1,3 @@
1
1
  module LinkifyIt
2
-
3
- VERSION = '2.0.3'
4
-
2
+ VERSION = '4.0.1'
5
3
  end
@@ -273,5 +273,39 @@ describe 'API' do
273
273
  l = Linkify.new(nil, { '---': true })
274
274
 
275
275
  expect(l.match('http://e.com/foo---bar')[0].text).to eq 'http://e.com/foo'
276
+ expect(l.match('text@example.com---foo')).to be_empty
277
+ end
278
+
279
+ #------------------------------------------------------------------------------
280
+ it 'should find a match at the start' do
281
+ l = Linkify.new
282
+
283
+ l.set({ fuzzyLink: true })
284
+
285
+ expect(l.matchAtStart('http://google.com 123').text).to eq 'http://google.com'
286
+ expect(l.matchAtStart('google.com 123')).to be_nil
287
+ expect(l.matchAtStart(' http://google.com 123')).to be_nil
288
+ end
289
+
290
+ #------------------------------------------------------------------------------
291
+ it 'matchAtStart should not interfere with normal match' do
292
+ l = Linkify.new
293
+
294
+ str = 'http://google.com http://google.com'
295
+ expect(l.matchAtStart(str)).not_to be_nil
296
+ expect(l.match(str).length).to eq 2
297
+
298
+ str = 'aaa http://google.com http://google.com'
299
+ expect(l.matchAtStart(str)).to be_nil
300
+ expect(l.match(str).length).to eq 2
301
+ end
302
+
303
+ #------------------------------------------------------------------------------
304
+ it 'should not match incomplete links' do
305
+ # regression test for https://github.com/markdown-it/markdown-it/issues/868
306
+ l = Linkify.new
307
+
308
+ expect(l.matchAtStart('http://')).to be_nil
309
+ expect(l.matchAtStart('https://')).to be_nil
276
310
  end
277
311
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linkify-it-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Walker
8
8
  - Vitaly Puzrin
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-04-02 00:00:00.000000000 Z
12
+ date: 2023-01-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: uc.micro-rb
@@ -26,19 +26,19 @@ dependencies:
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.0'
28
28
  - !ruby/object:Gem::Dependency
29
- name: bacon-expect
29
+ name: motion-expect
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '1.0'
34
+ version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: '1.0'
41
+ version: '0'
42
42
  description: Ruby version of linkify-it for motion-markdown-it, for Ruby and RubyMotion
43
43
  email: github@digitalmoksha.com
44
44
  executables: []
@@ -56,7 +56,7 @@ homepage: https://github.com/digitalmoksha/linkify-it-rb
56
56
  licenses:
57
57
  - MIT
58
58
  metadata: {}
59
- post_install_message:
59
+ post_install_message:
60
60
  rdoc_options: []
61
61
  require_paths:
62
62
  - lib
@@ -71,9 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
71
  - !ruby/object:Gem::Version
72
72
  version: '0'
73
73
  requirements: []
74
- rubyforge_project:
75
- rubygems_version: 2.6.8
76
- signing_key:
74
+ rubygems_version: 3.1.4
75
+ signing_key:
77
76
  specification_version: 4
78
77
  summary: linkify-it for motion-markdown-it in Ruby
79
78
  test_files: