tag_uri 1.0.1 → 2.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: 24aedc1ef59817936be23c8bd7a0d11c96b02251
4
- data.tar.gz: a5c2c2a78131e12b451317ff03a30025b6a2387e
2
+ SHA256:
3
+ metadata.gz: f1f7613a274c36cb5de4cb1105e0af41db251bf2fa0f16bdd31c2eeb7d8a5bdb
4
+ data.tar.gz: 8cdd72e27fdd464ecbb36f65a3c6f5ee60e0a762ac73270058827cf2724d0eb0
5
5
  SHA512:
6
- metadata.gz: eb905bff1541a2df1c0ddc83e9c851ae43d4cae802d201450ed7e375f22475130bba0a8bb79c73d7996c738eb8d362b488a072e55d8a4624a6f95804da5974fa
7
- data.tar.gz: 3b6aac238508687f5c616295e0342454bddb1bdd52a9bc996d62088528e47a945aff2b16ac5d7533de0e47009bc339d6b3ee0f68aefd3d0474e9fc1e99c7891d
6
+ metadata.gz: af684a9e4ce533c01ed5600b730959551a4dfbca805c2e5e2f2f6d3da2462a9365b856cb03c3e358a54cde88339699f043f02ceb9f3379124bf9a00cd9a9f49e
7
+ data.tar.gz: f802572ff78c7a1e2d965370019cae2e046ae93f250e4ed9c23e10992236d2ce5a39f55f4c42ff86666d979f65b5f9f30f6f9c58f30b8ca8ce015e7c7d1fcba5
Binary file
Binary file
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.0
4
- - 2.2.2
3
+ - ruby-2.5.2
5
4
  - rbx
6
5
  - ruby-head
7
6
  - jruby-head
data/CHANGES.md CHANGED
@@ -1,27 +1,62 @@
1
1
  # CH CH CH CHANGES #
2
2
 
3
- ## Sunday the 14th of June, 2015 ##
3
+ ## Otherwise known as the changelog
4
4
 
5
- ### v1.0.1 ###
5
+ All notable changes to this project will be documented in this file.
6
6
 
7
- * Improved the docs.
7
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
8
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
8
9
 
9
- ----
10
10
 
11
- ### v1.0.0 ###
11
+ ## Unreleased
12
12
 
13
- * Updated to use Ruby v2's keywords.
14
- * Bumped to v1.0.0 as a semver release.
15
13
 
16
- ----
14
+ ## [v2.0.1] - Tuesday the 15th of January, 2019
17
15
 
18
- ### v0.0.3 ###
16
+ ### Added
19
17
 
20
- * Since the Github repo is called tag-uri (because a hypen is clearer in a URL) I've added tag-uri.rb and taguri.rb to the lib to require the library in case anyone uses the wrong name.
18
+ - Support for a more secure installation via MediumSecurity and HighSecurity options.
21
19
 
22
- ### 27th of February, 2013 v0.0.2 ###
20
+ ### Changed
23
21
 
24
- * Changed to be a class method, as if it's mixed in to a model then the model will likely want to use that name for the field.
25
- * Changed the module name, it should all be uppercase so now it is.
22
+ - Updated the README to reflect the changes.
26
23
 
27
- ----
24
+
25
+ ## [v2.0.0] - Tuesday the 15th of January, 2019
26
+
27
+ ### Added
28
+
29
+ - Started using [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
30
+
31
+ ### Changed
32
+
33
+ - Expanded the use of the library beyond just atom.
34
+ - Added lots more tests.
35
+ - The API now adheres more to the terms used in the RFC.
36
+ - Tried to keep the laziness factor available.
37
+ - Removed the old `TagURI.create` API (the major version change means it's a breaking change).
38
+ - Tried to get TagURI::URI closer to the Ruby stdlib's URI API. More could probably be done here.
39
+ - Improved the docs by adding specs that mirror the examples given.
40
+ - Git tags will now be signed by GPG too (look in my gists for Keybase or go to [http://keybase.io/iainb](http://keybase.io/iainb) to get the key).
41
+
42
+
43
+ ## [v1.0.1] - Sunday the 14th of June, 2015
44
+
45
+ - Improved the docs.
46
+
47
+
48
+ ## [v1.0.0] - Sunday the 14th of June, 2015
49
+
50
+ - Updated to use Ruby v2's keywords.
51
+ - Bumped to v1.0.0 as a semver release.
52
+
53
+
54
+ ## [v0.0.3] - Wednesday the 27th of February, 2013
55
+
56
+ - Since the Github repo is called tag-uri (because a hypen is clearer in a URL) I've added tag-uri.rb and taguri.rb to the lib to require the library in case anyone uses the wrong name.
57
+
58
+
59
+ ## [v0.0.2] - Wednesday the 27th of February, 2013
60
+
61
+ - Changed to be a class method, as if it's mixed in to a model then the model will likely want to use that name for the field.
62
+ - Changed the module name, it should all be uppercase so now it is.
data/Gemfile CHANGED
@@ -11,11 +11,14 @@ group :development do
11
11
  gem "maruku"
12
12
  unless RUBY_ENGINE == 'jruby' || RUBY_ENGINE == "rbx"
13
13
  gem "pry-byebug"
14
+ gem "rb-readline"
14
15
  end
15
16
  end
16
17
 
17
18
  group :test do
18
19
  gem "rspec"
19
20
  gem "rspec-its"
21
+ gem "rspec-given"
20
22
  gem "simplecov"
23
+ gem "timecop"
21
24
  end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # TagUri
1
+ # TagURI
2
2
 
3
- An implementation of tag URI's.
3
+ An implementation of tag URIs.
4
4
  See http://tools.ietf.org/html/rfc4151
5
5
 
6
6
  ### Build status ###
@@ -10,7 +10,7 @@ Master branch:
10
10
 
11
11
  ## Why? ##
12
12
 
13
- Because every Atom entry must have a globally unique ID, in the `id` element.
13
+ I originally wrote this because every Atom entry must have a globally unique ID, in the `id` element, and I was writing an atom feed.
14
14
 
15
15
  * The ID must be a valid URI, as defined by RFC 2396.
16
16
  * The ID must be globally unique, across all Atom feeds, everywhere, for all time. This part is actually easier than it sounds.
@@ -27,23 +27,69 @@ You don't have to just use it with Atom, it's also useful anywhere that a non-ti
27
27
  > Tag URIs finally let URIs do what they were meant to do: identify without implying any sort of location or behavior that they don't have. They're easy to create, they're human legible, they work with existing systems, they're an open standard, and they don't have any backward compatibility issues. What's not to like?
28
28
 
29
29
 
30
- ## Installation
30
+ ## Usage
31
31
 
32
- Add this line to your application's Gemfile:
32
+ require 'tag_uri'
33
33
 
34
- gem 'tag_uri'
34
+ ### THE MOST BASIC WAY
35
35
 
36
- And then execute:
36
+ tag_uri = TagURI::URI.new authority_name: "helpful-iain@theprintedbird.com",
37
+ date: "2019-01-09",
38
+ specific: "My slippers"
37
39
 
38
- $ bundle
40
+ tag_uri.to_s
41
+ # => "tag:helpful-iain@theprintedbird.com,2019-01-09:My%20slippers"
42
+ tag.authority_name
43
+ # => "helpful-iain@theprintedbird.com"
44
+ tag.date
45
+ # => 2019-01-09 00:00:00 +0900 # You get a Time object back
46
+ tag.specific "My slippers"
39
47
 
40
- Or install it yourself as:
48
+ ### ANOTHER MOST BASIC WAY
41
49
 
42
- $ gem install tag_uri
50
+ TagURI::URI.new email: "helpful-iain@theprintedbird.com",
51
+ date: "2019-01-09",
52
+ specific: "My slippers"
43
53
 
44
- ## Usage
54
+ tag_uri.to_s
55
+ # => "tag:helpful-iain@theprintedbird.com,2019-01-09:My%20slippers"
56
+ tag.authority_name
57
+ # => "helpful-iain@theprintedbird.com"
58
+ tag.date
59
+ # => 2019-01-09 00:00:00 +0900
60
+ tag.specific "My slippers"
45
61
 
46
- require 'tag_uri'
62
+ ### (NOT TO FLOG A DEAD HORSE BUT) ANOTHER MOST BASIC WAY
63
+
64
+ TagURI::URI.new domain: "theprintedbird.com",
65
+ date: "2019-01-09",
66
+ specific: "My slippers"
67
+
68
+ tag_uri.to_s
69
+ # => "tag:theprintedbird.com,2019-01-09:My%20slippers"
70
+ tag.authority_name
71
+ # => "theprintedbird.com"
72
+ tag.date
73
+ # => 2019-01-09 00:00:00 +0900
74
+ tag.specific "My slippers"
75
+
76
+
77
+ ### YOU HAVE A WEB LINK TO AN ARTICLE ABOUT BEESWAX (WHY NOT?) AND YOU'RE FEELING LAZY
78
+
79
+ Don't be this lazy as you'll be letting a computer and my programming try to guess what you wanted. But…
80
+
81
+ # Imagine it's the 2018-03-11 today, because today is the day that'll be
82
+ # chosen for your tag date.
83
+ tag_uri = TagURI::URI.new uri: "http://www.example.com/posts/beeswax#bees"
84
+
85
+ tag_uri.to_s
86
+ # => "tag:www.example.com,2018-03-11:/posts/beeswax#bees"
87
+ tag_uri.authority_name
88
+ # => "www.example.com"
89
+ tag_uri.specific
90
+ # => "/posts/beeswax"
91
+ tag_uri.fragment # yes, you get fragments too!
92
+ # => "bees"
47
93
 
48
94
  Given a model:
49
95
 
@@ -55,16 +101,49 @@ Given a model:
55
101
  # => "howto-atom-linkblog"
56
102
  post.created_at
57
103
  # => 2004-05-27 00:00:00 0100
58
-
59
- TagURI.create prefix: "/archives/2004/05/27", host: "diveintomark.org", slug: post.slug, created_at: post.created_at
60
- # => "tag:diveintomark.org,2013-02-26:/archives/2004/05/27/howto-atom-linkblog"
104
+ post.prefix
105
+ # => "/archives/2004/05/27/" # Why? It's up to you.
61
106
 
62
- Although you'll probably do something more like this:
107
+ tag_uri = TagURI::URI.new authority_name: request.host,
108
+ date: post.created_at,
109
+ specific: "#{post.prefix}#{slug}"
63
110
 
64
- TagURI.create slug: post.slug, created_at: post.created_at prefix: prefix, host: request.host
111
+ tag_uri.to_s
112
+ # => "tag:diveintomark.org,2013-02-26:/archives/2004/05/27/howto-atom-linkblog"
65
113
 
66
114
  or something like that.
67
115
 
116
+
117
+ ## Installation
118
+
119
+ Add this line to your application's Gemfile:
120
+
121
+ gem 'tag_uri'
122
+
123
+ And then execute:
124
+
125
+ $ bundle
126
+
127
+ Or install it yourself as:
128
+
129
+ $ gem install tag_uri
130
+
131
+ ## Even better installation
132
+
133
+ I'm trying to be a [responsible citizen regarding security](https://keybase.io/iainb) so I've followed the [instructions here](https://guides.rubygems.org/security/) and created a [public certicate](https://gist.github.com/yb66/0fb0e3007de4d4279aeaf162e0ced40a#file-yb66-pem) and signed the gem, so you can install it via:
134
+
135
+ gem cert --add <(curl -Ls https://gist.githubusercontent.com/yb66/0fb0e3007de4d4279aeaf162e0ced40a/raw/49466a801e1fd237fffe4658143a96c6cca6c961/yb66.pem)
136
+
137
+ gem install tag_uri -P MediumSecurity
138
+
139
+ The MediumSecurity trust profile will verify signed gems, but allow the installation of unsigned dependencies.
140
+
141
+ If all of TagURI’s dependencies are signed you can use HighSecurity.
142
+
143
+ gem install tag_uri -P HighSecurity
144
+
145
+ It's just one more [good reason](https://cfoc.org/rubygems-vulnerability-can-compel-installing-malware/) to get on to gem authors and ask them to sign their gems, and ask the Rubygems authors to be [proactive with security measures](https://github.com/rubygems/rubygems/issues/2496).
146
+
68
147
  ## Versioning ##
69
148
 
70
149
  This library uses [semver](http://semver.org).
@@ -0,0 +1,26 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEbjCCAtagAwIBAgIBATANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDDCVoZWxw
3
+ ZnVsLWlhaW4vREM9dGhlcHJpbnRlZGJpcmQvREM9Y29tMB4XDTE5MDExNTA3MjAw
4
+ OVoXDTIwMDExNTA3MjAwOVowMDEuMCwGA1UEAwwlaGVscGZ1bC1pYWluL0RDPXRo
5
+ ZXByaW50ZWRiaXJkL0RDPWNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoC
6
+ ggGBALhp1KlrdriWAuhXhM3I0oZblbOUAgk8UZSyI6vLQ4oK8uHWmdBkrzUublq4
7
+ 7cU1T0IIFeKOzjN2aXS660q2Ev7Bpwt1oBjMVqLMZYJM4gixwzXW9labQhnjefEy
8
+ CTWRa/i4gL8NbwOg/UeX5rHiCy/xaqyxj//24E7m5e72JrpK11ZZ5/4TUvxDfOJr
9
+ w+16BAxH3ELBRjXoOXnlb7SzA2ohNnwuoom5gi9Ju6z0ooSa9cegqauHBbme8wgO
10
+ 5bPwGi+MbiLKoMDcnakuUoKqWL6qA+/QofNnrmtgBmMe08dd9/ermztT/dBdNQiE
11
+ eOXDR+sM5ardxl+5TdAcGuheMgZBiBVqaMVowUp1VPV1f/sY8RsfYqFVBg/I+jcu
12
+ uulV50CkaLYmZVa0sWiCNg/pkKROpVktwfkRo3EKCllckMc29qPts64g0UkyBi1q
13
+ stO7Yk/0PmhHcWHHv8Lfuin0Cmpt01AuKi3ToOBJHAvLWkORlOw1mIC9mdOR3c9Y
14
+ jeBbawIDAQABo4GSMIGPMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
15
+ BBSyOPfHSTgay7iGZ94b0JDrrcaBDTAqBgNVHREEIzAhgR9oZWxwZnVsLWlhaW5A
16
+ dGhlcHJpbnRlZGJpcmQuY29tMCoGA1UdEgQjMCGBH2hlbHBmdWwtaWFpbkB0aGVw
17
+ cmludGVkYmlyZC5jb20wDQYJKoZIhvcNAQELBQADggGBAAoYHPvpy84kUzvM1tMF
18
+ AMUFH6V/hkBdcTRS3mE+8lpMHBiPluByk1/vfUTlo9kGFtEEXd1ginKqMozLKFrr
19
+ 5yRAi08zsRA0pSDuOJsX95x4Rr5GnAUKeVOXJHry0Kae3btQdJ59ZqvFPyNiXKEB
20
+ SUIa4GUcWFaIl2yL7epcCNsyhEqvnRPq0zvfY0IGT3AcHxchCWbnurkci32eAiqW
21
+ TESqr8zDJzsH7HSyOHlNdvWQRrYfhh8p+JsbRqJ4rChBPYnZM6fnlFtvPUNbBaRr
22
+ cw7FROiP0G0E7GAd7loZ78WoQEM6regiCibP3LPehIl94P3K2+CCOI148rNlyXBE
23
+ ATDB99qMn3ZgZEE0i5jxxVOHbMQWcvN3oElPuVVq6gLhqnZn50DW2B6wf3s4MMMd
24
+ ILghhrKlF+3IGSo6pOtgZB3Y84IgtvmYyo3Unv8VkRqZ22ZSxz7GFy+X7SABSGxU
25
+ ewk/WBT8wib1dm745Y+U42Icj8FgHqKkq1mDIcMcyLqxLA==
26
+ -----END CERTIFICATE-----
@@ -1,6 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  require 'addressable/uri'
4
+ require 'time'
4
5
 
5
6
  # Implementation of tag URI's.
6
7
  # @see http://tools.ietf.org/html/rfc4151
@@ -9,26 +10,273 @@ module TagURI
9
10
  class Error < StandardError; end
10
11
  class ArgumentError < Error; end
11
12
 
12
- # @param [Hash] opts
13
- # @option opts [String] host The host portion e.g. http://example.com. If the host portion is not given then it is assumed that `self` will provide it.
14
- # @option opts [String] slug The slugged name e.g. this-is-my-first-post. If a slug is not given then it is assumed that `self` will provide it.
15
- # @option opts [String] prefix Anything you wish to tack on before the slug in the path e.g. for /posts/this-is-my-first-post pass in "prefix". If a prefix is not given then it will not be added to the string.
16
- # @option opts [Time] created_at The time the resource was created. If a created_at time is not given then it is assumed that `self` will provide it.
17
- # @return [String]
18
- # @example
19
- # class Posts < Sequel::Model # or whatever ORM you're using.
20
- # end
21
- # post = Post.create #…
22
- # post.slug # => "this-is-my-first-post"
23
- # TagURI.create host: "http://example.com", prefix: "posts", slug: post.slug, created_at: post.created_at
24
- def self.create( created_at: Time.now, prefix:"", slug:, host: )
25
- fail ArgumentError if host.nil? || host.empty?
26
- fail ArgumentError if slug.nil? || slug.empty?
27
-
28
- host = "https://#{host}" unless host =~ %r{^.+\://.+$}
29
- uri = Addressable::URI.parse File.join( host, prefix, slug )
30
- uri.scheme = "tag"
31
- uri.host = "#{uri.host},#{created_at.strftime "%F"}:"
32
- uri.to_s.sub(%r{://}, ":")
13
+
14
+ # From the RFC @see https://tools.ietf.org/html/rfc4151#section-2.1
15
+ # The general syntax of a tag URI, in ABNF [2], is:
16
+ #
17
+ # tagURI = "tag:" taggingEntity ":" specific [ "#" fragment ]
18
+ #
19
+ # Where:
20
+ #
21
+ # taggingEntity = authorityName "," date
22
+ # authorityName = DNSname / emailAddress
23
+ # date = year ["-" month ["-" day]]
24
+ # year = 4DIGIT
25
+ # month = 2DIGIT
26
+ # day = 2DIGIT
27
+ # DNSname = DNScomp *( "." DNScomp ) ; see RFC 1035 [3]
28
+ # DNScomp = alphaNum [*(alphaNum /"-") alphaNum]
29
+ # emailAddress = 1*(alphaNum /"-"/"."/"_") "@" DNSname
30
+ # alphaNum = DIGIT / ALPHA
31
+ # specific = *( pchar / "/" / "?" ) ; pchar from RFC 3986 [1]
32
+ # fragment = *( pchar / "/" / "?" ) ; same as RFC 3986 [1]
33
+ # pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
34
+ # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
35
+ # pct-encoded = "%" HEXDIG HEXDIG
36
+ # sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
37
+ class URI
38
+ # To match the terminology of the RFC I've put straightforward regex into
39
+ # constants.
40
+
41
+ # No underscores, only alphanums.
42
+ ALPHANUM = /[0-9a-zA-Z]/
43
+ # No percent encoding here for hexnums.
44
+ HEXDIG = /[0-9a-fA-F]/
45
+ # This is where the percent encodings are checked, e.g. %20.
46
+ PCT_ENCODED = /% #{HEXDIG} #{HEXDIG}/x
47
+ # Magic markers here.
48
+ SUB_DELIMS = /[\!\$\&'\(\)\*\+,\;\=]/x
49
+ # The uncarved block.
50
+ UNRESERVED = /[\w\-\.\~]/
51
+ # (Possibly percent-encoded) characters
52
+ PCHAR = /#{UNRESERVED} | #{PCT_ENCODED} | #{SUB_DELIMS} | \: | @/x
53
+ # The thing really being tagged.
54
+ SPECIFIC = %r< (?: #{PCHAR} | / | \? )+ >x
55
+ # fragment = *( pchar / "/" / "?" ) ; same as RFC 3986 [1]
56
+ # Even more specific.
57
+ FRAGMENT = /(?<=\#)#{SPECIFIC}/x
58
+ # DNScomp = alphaNum [*(alphaNum /"-") alphaNum]
59
+
60
+ # Don't get too hung up on validating it's a domain name,
61
+ # just do enough.
62
+ DNSNAME = /
63
+ \b
64
+ (?:
65
+ (?=[a-z0-9-]{1,63}\.)
66
+ (?: xn--)?
67
+ [a-z0-9]+
68
+ (?: -[a-z0-9]+)*
69
+ \.)+
70
+ [a-z]{2,63}
71
+ \b
72
+ /x
73
+
74
+ # It's not worth validating the email address beyond this either.
75
+ EMAIL = /(?<email_id>[^,]+)@(?<email_domain>[^,@]+)/ # yes, anything goes
76
+
77
+ # ISO8601 date
78
+ YYYY_MM_DD = /\d{4}-\d\d-\d\d/
79
+ OTHER_DATES = %r<\d{4}(?<separator>[\-\_/])\d\d[\-\_/]\d\d>
80
+
81
+ # One scheme to rule them all, at least in this module.
82
+ TAG_SCHEME = /(?<scheme>tag)\:/
83
+
84
+ # Be tolerant
85
+ ANY_SCHEME = /(?<scheme>#{ALPHANUM}+)\:/
86
+
87
+ # I have the authoritay!
88
+ AUTHORITY_NAME = /(?<authority_name>
89
+ (?: #{DNSNAME} )
90
+ |
91
+ (?: #{EMAIL} )
92
+ )/x
93
+
94
+ # The whole pattern to capture a tag uri.
95
+ TAG = /\A
96
+ #{ANY_SCHEME}
97
+ #{AUTHORITY_NAME}
98
+ ,
99
+ (?<date>#{YYYY_MM_DD})
100
+ \:
101
+ (?<specific> #{SPECIFIC} )
102
+ (?<fragment> #{FRAGMENT} )?
103
+ \z/x
104
+
105
+
106
+ # Should be slightly faster than the other version.
107
+ VALIDATE_TAG = /\A
108
+ #{TAG_SCHEME}
109
+ #{AUTHORITY_NAME}
110
+ ,
111
+ #{YYYY_MM_DD}
112
+ \:
113
+ #{SPECIFIC}
114
+ (?: #{FRAGMENT} )?
115
+ \z/x
116
+
117
+ TIME_FORMAT="%Y-%m-%d"
118
+
119
+
120
+ # @param uri [#to_s]
121
+ # @param authority_name [String]
122
+ # @param date [String,Time,#to_time]
123
+ # @param specific [String]
124
+ # @param fragment [String]
125
+ # @param email [String]
126
+ # @param domain [String]
127
+ def initialize( uri: nil,
128
+ authority_name: nil,
129
+ date: nil,
130
+ specific: nil,
131
+ fragment: nil,
132
+ email: nil,
133
+ domain: nil
134
+ )
135
+ @scheme = "tag"
136
+ if uri
137
+ # handle TagURI::URI object
138
+ if (uri.respond_to? :authority_name and
139
+ uri.respond_to? :date and
140
+ uri.respond_to? :specific)
141
+ @authority_name = uri.authority_name
142
+ @date = uri.date
143
+ @specific = uri.specific
144
+ return
145
+ else
146
+ uri = uri.to_s
147
+ # handle something that looks very like a TagURI::URI object
148
+ if ::URI.regexp.match uri and
149
+ (md = TAG.match uri) and
150
+ md[:scheme] == "tag"
151
+ @authority_name = md[:authority_name]
152
+ @date = Time.strptime md[:date], TIME_FORMAT
153
+ @specific = md[:specific]
154
+ self.fragment = md[:fragment]
155
+ return
156
+ else # see what we can salvage from the uri
157
+ extra_uri = Addressable::URI.parse uri
158
+ end
159
+ end
160
+ end
161
+
162
+ @date =
163
+ if date
164
+ if date.respond_to? :to_time
165
+ date
166
+ elsif date.to_s =~ /\A#{YYYY_MM_DD}$/
167
+ Time.strptime date.to_s, TIME_FORMAT
168
+ else
169
+ fail ArgumentError, "Date should be a valid time/date/string that conforms to YYYY-MM-DD"
170
+ end
171
+ elsif uri and (md = /\A[^,]+,(?<date>#{YYYY_MM_DD})/.match uri )
172
+ Time.strptime md[:date], TIME_FORMAT
173
+ elsif extra_uri and (md = OTHER_DATES.match extra_uri.path)
174
+ Time.strptime md[0], "%Y#{md[:separator]}%m#{md[:separator]}%d"
175
+ else
176
+ Time.now
177
+ end
178
+
179
+ @authority_name =
180
+ if authority_name
181
+ if (md = AUTHORITY_NAME.match authority_name)
182
+ md[0]
183
+ else
184
+ fail ArgumentError, "Authority name must be a domain name or email address"
185
+ end
186
+ elsif email
187
+ if (md = EMAIL.match email)
188
+ md[0]
189
+ else
190
+ fail ArgumentError, "email given was invalid"
191
+ end
192
+ elsif domain
193
+ if (md = DNSNAME.match domain)
194
+ md[0]
195
+ else
196
+ fail ArgumentError, "domain given was invalid"
197
+ end
198
+ elsif extra_uri and extra_uri.normalized_authority
199
+ extra_uri.normalized_authority
200
+ elsif extra_uri and extra_uri.normalized_path and (md = AUTHORITY_NAME.match(extra_uri.normalized_path))
201
+ md[:authority_name]
202
+ elsif uri and (md = AUTHORITY_NAME.match uri)
203
+ md[0]
204
+ # else what?
205
+ end
206
+
207
+
208
+ @specific =
209
+ if specific
210
+ specific
211
+ elsif extra_uri and (md = /,[\d\-]+\:(?<specific>#{SPECIFIC})/.match extra_uri.normalized_path )
212
+ md[:specific]
213
+ elsif uri and (md = /,[\d\-]+\:(?<specific>#{SPECIFIC})/.match uri )
214
+ md[:specific]
215
+ elsif extra_uri
216
+ extra_uri.normalized_path
217
+ end
218
+
219
+ self.fragment =
220
+ if fragment
221
+ fragment
222
+ elsif extra_uri and (md = /,[\d\-]+\:[^\#]+#(?<fragment>#{FRAGMENT})/.match extra_uri.normalized_path)
223
+ md[:fragment]
224
+ elsif uri and (md = /,[\d\-]+\:[^\#]+#(?<fragment>#{FRAGMENT})/.match uri )
225
+ md[:fragment]
226
+ elsif extra_uri
227
+ extra_uri.normalized_fragment
228
+ end
229
+
230
+ end
231
+
232
+
233
+ # @!attribute [r] scheme
234
+ # @return [String] Have a guess what it will be… (`"tag"`;)
235
+ attr_reader :scheme
236
+
237
+ # @!attribute [r] authority_name
238
+ # @return [String]
239
+ # @!attribute [r] date
240
+ # @return [String]
241
+ # @!attribute [r] specific
242
+ # @return [String]
243
+ attr_accessor :authority_name, :date, :specific
244
+
245
+
246
+ def fragment
247
+ @fragment || ""
248
+ end
249
+
250
+
251
+ def fragment=( frag )
252
+ @fragment = if frag
253
+ frag.start_with?("#") ?
254
+ frag.sub(/#/, "") :
255
+ frag
256
+ else
257
+ ""
258
+ end
259
+ @fragment
260
+ end
261
+
262
+
263
+ def tagging_entity
264
+ %Q!#{@authority_name},#{@date.strftime "%F"}!
265
+ end
266
+
267
+
268
+ def to_s
269
+ s = %Q!#{self.scheme}:#{self.tagging_entity}:#{self.specific.gsub(/\s/, "%20")}!
270
+ unless @fragment.nil? or @fragment.empty?
271
+ s << "##{self.fragment}"
272
+ end
273
+ s
274
+ end
275
+
276
+
277
+ def valid?
278
+ !!(VALIDATE_TAG =~ self.to_s)
279
+ end
280
+
33
281
  end
34
282
  end
@@ -1,3 +1,6 @@
1
1
  module TagURI
2
- VERSION = "1.0.1"
2
+
3
+ # Library version, adheres to semver
4
+ # @see https://semver.org/spec/v2.0.0.html
5
+ VERSION = "2.0.1"
3
6
  end
@@ -2,14 +2,13 @@
2
2
 
3
3
  require 'rspec'
4
4
  require 'rspec/its'
5
- Spec_dir = File.expand_path( File.dirname __FILE__ )
5
+ require 'rspec/given'
6
+ require 'timecop'
7
+ Spec_dir = Pathname( __dir__ )
6
8
 
7
- unless Kernel.respond_to?(:require_relative)
8
- module Kernel
9
- def require_relative(path)
10
- require File.join(File.dirname(caller[0]), path.to_str)
11
- end
12
- end
9
+ if ENV["DEBUG"]
10
+ require 'pry-byebug'
11
+ binding.pry
13
12
  end
14
13
 
15
14
  # code coverage
@@ -18,6 +17,7 @@ SimpleCov.start do
18
17
  add_filter "/vendor.noindex/"
19
18
  add_filter "/coverage/"
20
19
  add_filter "/bin/"
20
+ add_filter "/spec/"
21
21
  end
22
22
 
23
23
 
@@ -25,5 +25,14 @@ Dir[ File.join( Spec_dir, "/support/**/*.rb")].each do |f|
25
25
  require f
26
26
  end
27
27
 
28
- # RSpec.configure do |config|
29
- # end
28
+ TIME_NOW = Time.parse "2018-03-11T06:49:16+00:00"
29
+ RSpec.configure do |config|
30
+
31
+ config.before(:each, :time_sensitive => true) do
32
+ Timecop.freeze TIME_NOW
33
+ end
34
+
35
+ config.after(:each, :time_sensitive => true) do
36
+ Timecop.return
37
+ end
38
+ end
@@ -0,0 +1,82 @@
1
+ SHOULD MATCH:
2
+
3
+ j.mp
4
+ 1337.net
5
+ a.b-c.de
6
+ xn--bcher-kva.tld
7
+ shouldfail.com
8
+ foo.com
9
+
10
+ END
11
+
12
+ SHOULD NOT MATCH:
13
+
14
+ 223.255.255.254
15
+ 0.0.0.0
16
+ 10.1.1.0
17
+ 10.1.1.255
18
+ 224.1.1.1
19
+ 10.1.1.1
20
+ 1.1.1.1.1
21
+ 123.123.123
22
+ a.b--c.de/
23
+ foo.bar/
24
+ 142.42.1.1/
25
+ foo.bar/foo(bar)baz quux
26
+ foo.bar/baz
27
+ foo.bar/?q=Test%20URL-encoded%20stuff
28
+ foo.com/unicode_(✪)_in_parens
29
+ foo.bar?q=Spaces should be encoded
30
+ 142.42.1.1:8080/
31
+ foo.com/blah_(wikipedia)#cite-1
32
+ foo.com/blah_(wikipedia)_blah#cite-1
33
+ foo.com/(something)?after=parens
34
+ code.google.com/events/#&product=browser
35
+ foo.com/blah_blah
36
+ foo.com/blah_blah/
37
+ foo.com/blah_blah_(wikipedia)
38
+ foo.com/blah_blah_(wikipedia)_(again)
39
+ www.example.com/wpstyle/?p=364
40
+ www.example.com/foo/?bar=baz&inga=42&quux
41
+ userid@example.com
42
+ userid@example.com/
43
+ userid@example.com:8080
44
+ userid@example.com:8080/
45
+ ✪df.ws/123
46
+ bücher.tld
47
+ ☺.damowmow.com/
48
+ userid:password@example.com
49
+ userid:password@example.com/
50
+ userid:password@example.com:8080
51
+ userid:password@example.com:8080/
52
+ مثال.إختبار
53
+ 例子.测试
54
+ उदाहरण.परीक्षा
55
+ ➡.ws/䨹
56
+ ⌘.ws
57
+ ⌘.ws/
58
+ -.~_!$&'()*+,;=:%40:80%2f::::::@example.com
59
+ .
60
+ ..
61
+ ../
62
+ ?
63
+ ??
64
+ ??/
65
+ #
66
+ ##
67
+ ##/
68
+ //
69
+ //a
70
+ ///a
71
+ ///
72
+ /a
73
+ 1234
74
+ h://test
75
+ should fail
76
+ -error-.invalid/
77
+ -a.b.co
78
+ a.b-.co
79
+ 3628126748
80
+ .www.foo.bar/
81
+ www.foo.bar./
82
+ .www.foo.bar./
@@ -2,27 +2,339 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'time'
5
- require 'ostruct'
6
5
  require_relative "../lib/tag_uri.rb"
7
6
 
8
- describe "Generating a tag uri" do
9
- let(:url) { "http://diveintomark.org/archives/2004/05/27/howto-atom-linkblog" }
10
- let(:slug) { "howto-atom-linkblog" }
11
- let(:created_at) { Time.parse "2004/05/27" }
12
- let(:host) { "diveintomark.org" }
13
- let(:prefix) { "/archives/2004/05/27" }
14
- let(:expected) { "tag:diveintomark.org,2004-05-27:/archives/2004/05/27/howto-atom-linkblog" }
15
- let(:model) { OpenStruct.new created_at: created_at, slug: slug }
16
-
17
- context "Given arguments" do
18
- context "That are valid" do
19
- subject { TagURI.create prefix: prefix, host: host, created_at: model.created_at, slug: model.slug }
20
- it { should == expected }
7
+ describe "Generating a tag uri", :time_sensitive do
8
+
9
+ context "THE MOST BASIC WAY" do
10
+ When(:tag_uri) {
11
+ TagURI::URI.new authority_name: "helpful-iain@theprintedbird.com",
12
+ date: "2019-01-09",
13
+ specific: "My slippers"
14
+ }
15
+ Then { tag_uri.to_s == "tag:helpful-iain@theprintedbird.com,2019-01-09:My%20slippers"}
16
+ end
17
+
18
+
19
+ context "ANOTHER MOST BASIC WAY" do
20
+ When(:tag_uri) {
21
+ TagURI::URI.new email: "helpful-iain@theprintedbird.com",
22
+ date: "2019-01-09",
23
+ specific: "My slippers"
24
+ }
25
+ Then { tag_uri.to_s == "tag:helpful-iain@theprintedbird.com,2019-01-09:My%20slippers"}
26
+ end
27
+
28
+ context "(NOT TO FLOG A DEAD HORSE BUT) ANOTHER MOST BASIC WAY" do
29
+ When(:tag_uri) {
30
+ TagURI::URI.new domain: "theprintedbird.com",
31
+ date: "2019-01-09",
32
+ specific: "My slippers"
33
+ }
34
+ Then { tag_uri.to_s == "tag:theprintedbird.com,2019-01-09:My%20slippers"}
35
+ end
36
+
37
+ context "YOU HAVE A WEB LINK TO AN ARTICLE ABOUT BEESWAX (WHY NOT?) AND YOU'RE FEELING LAZY", :time_sensitive do
38
+ When(:tag_uri) {
39
+ TagURI::URI.new uri: "http://www.example.com/posts/beeswax#bees"
40
+ }
41
+ Then { tag_uri.to_s == "tag:www.example.com,2018-03-11:/posts/beeswax#bees"}
42
+ And { tag_uri.scheme == "tag" }
43
+ And { tag_uri.authority_name == "www.example.com" }
44
+ And { tag_uri.date == TIME_NOW }
45
+ And { tag_uri.specific == "/posts/beeswax" }
46
+ And { tag_uri.fragment == "bees" }
47
+ end
48
+
49
+ context "Some of the examples on the internet" do
50
+ context "diveintomark atom tag" do
51
+ Given(:url) { "http://diveintomark.org/archives/2004/05/27/howto-atom-linkblog" }
52
+ Given(:specific) { "/archives/2004/05/27/howto-atom-linkblog" }
53
+ Given(:date) { Time.strptime "2004/05/27", "%Y/%m/%d" }
54
+ Given(:authority_name) { "diveintomark.org" }
55
+ Given(:prefix) { "/archives/2004/05/27" }
56
+ Given(:expected) { "tag:diveintomark.org,2004-05-27:/archives/2004/05/27/howto-atom-linkblog" }
57
+ Given(:fragment) { "" }
58
+ context "identity" do
59
+ context "by string" do
60
+ When(:tag_uri) { TagURI::URI.new uri: expected }
61
+ Then { tag_uri.to_s == expected }
62
+ And { tag_uri.scheme == "tag" }
63
+ And { tag_uri.authority_name == authority_name }
64
+ And { tag_uri.date == date }
65
+ And { tag_uri.specific == specific }
66
+ And { tag_uri.fragment == fragment }
67
+ end
68
+ context "by uri" do
69
+ When(:tag_uri) { TagURI::URI.new uri: TagURI::URI.new(uri: expected) }
70
+ Then { tag_uri.to_s == expected }
71
+ And { tag_uri.scheme == "tag" }
72
+ And { tag_uri.authority_name == authority_name }
73
+ And { tag_uri.date == date }
74
+ And { tag_uri.specific == specific }
75
+ And { tag_uri.fragment == fragment }
76
+ end
77
+ end
78
+ context "authority_name given" do
79
+ context "That is valid" do
80
+ When(:tag_uri) { TagURI::URI.new uri: url,
81
+ authority_name: authority_name }
82
+ Then { tag_uri.to_s == expected }
83
+ And { tag_uri.scheme == "tag" }
84
+ And { tag_uri.authority_name == authority_name }
85
+ And { tag_uri.date == date }
86
+ And { tag_uri.specific == specific }
87
+ And { tag_uri.fragment == fragment }
88
+ end
89
+ context "That is not valid" do
90
+ it "should fail, tagged by TagURI" do
91
+ expect { TagURI::URI.new uri: url,
92
+ authority_name: "NOT_A_DOMAIN_NAME"
93
+ }.to raise_error TagURI::ArgumentError
94
+ end
95
+ end
96
+ end
97
+ context "date given" do
98
+ context "That is valid" do
99
+ When(:tag_uri) { TagURI::URI.new uri: url,
100
+ date: date }
101
+ Then { tag_uri.to_s == expected }
102
+ And { tag_uri.scheme == "tag" }
103
+ And { tag_uri.authority_name == authority_name }
104
+ And { tag_uri.date == date }
105
+ And { tag_uri.specific == specific }
106
+ And { tag_uri.fragment == fragment }
107
+ end
108
+
109
+ context "That is not valid" do
110
+ date = "Not a date"
111
+ it "should throw an error (tagged by the library)" do
112
+ expect { TagURI::URI.new uri: url, date: date }.to raise_error TagURI::ArgumentError
113
+ end
114
+ end
115
+ end
116
+ context "specific given" do
117
+ When(:tag_uri) { TagURI::URI.new uri: url,
118
+ specific: specific }
119
+ Then { tag_uri.to_s == expected }
120
+ And { tag_uri.scheme == "tag" }
121
+ And { tag_uri.authority_name == authority_name }
122
+ And { tag_uri.date == date }
123
+ And { tag_uri.specific == specific }
124
+ And { tag_uri.fragment == fragment }
125
+ end
126
+ context "email given" do
127
+ context "That is valid" do
128
+ Given(:email) { "alice@example.org" }
129
+ When(:tag_uri) { TagURI::URI.new uri: url,
130
+ email: email }
131
+ Then { tag_uri.to_s == expected.sub(authority_name, email) }
132
+ And { tag_uri.scheme == "tag" }
133
+ And { tag_uri.authority_name == email }
134
+ And { tag_uri.date == date }
135
+ And { tag_uri.specific == specific }
136
+ And { tag_uri.fragment == fragment }
137
+ end
138
+ context "That is not valid" do
139
+ it "should fail, tagged by TagURI" do
140
+ expect { TagURI::URI.new uri: url,
141
+ email: "NOT_AN_EMAIL_ADDRESS"
142
+ }.to raise_error TagURI::ArgumentError
143
+ end
144
+ end
145
+ end
146
+
147
+ context "domain given" do
148
+ context "That is valid" do
149
+ Given(:domain) { "diveintomark.org" }
150
+ When(:tag_uri) { TagURI::URI.new uri: url,
151
+ domain: domain }
152
+ Then { tag_uri.to_s == expected }
153
+ And { tag_uri.scheme == "tag" }
154
+ And { tag_uri.authority_name == domain }
155
+ And { tag_uri.date == date }
156
+ And { tag_uri.specific == specific }
157
+ And { tag_uri.fragment == fragment }
158
+ end
159
+ context "That is not valid" do
160
+ it "should fail, tagged by TagURI" do
161
+ expect { TagURI::URI.new uri: url,
162
+ domain: "NOT_A_DOMAIN_NAME"
163
+ }.to raise_error TagURI::ArgumentError
164
+ end
165
+ end
166
+ end
167
+
168
+ context "No authority_name or domain or email given" do
169
+ context "But the URI has valid one of those" do
170
+ When(:tag_uri) { TagURI::URI.new uri: url }
171
+ Then { tag_uri.to_s == expected }
172
+ And { tag_uri.scheme == "tag" }
173
+ And { tag_uri.authority_name == authority_name }
174
+ And { tag_uri.date == date }
175
+ And { tag_uri.specific == specific }
176
+ And { tag_uri.fragment == fragment }
177
+ end
178
+ end
179
+ end
180
+ context "Sandro's dog tag" do
181
+ Given(:url) { "sandro@hawke.org" }
182
+ Given(:authority_name) { "sandro@hawke.org" }
183
+ Given(:specific) { "Taiko" }
184
+ Given(:date) { Time.parse "2001-06-05" }
185
+ Given(:expected) { "tag:sandro@hawke.org,2001-06-05:Taiko" }
186
+ Given(:fragment) { "" }
187
+ context "identity" do
188
+ When(:tag_uri) { TagURI::URI.new uri: expected }
189
+ Then { tag_uri.to_s == expected }
190
+ And { tag_uri.scheme == "tag" }
191
+ And { tag_uri.authority_name == authority_name }
192
+ And { tag_uri.date == date }
193
+ And { tag_uri.specific == specific }
194
+ And { tag_uri.fragment == fragment }
195
+ end
196
+ context "authority_name given" do
197
+ When(:tag_uri) { TagURI::URI.new uri: url,
198
+ authority_name: authority_name }
199
+ Given(:expected) { "tag:sandro@hawke.org,2018-03-11:sandro@hawke.org" }
200
+ Then { tag_uri.to_s == expected }
201
+ And { tag_uri.scheme == "tag" }
202
+ And { tag_uri.authority_name == authority_name }
203
+ And { tag_uri.date == TIME_NOW }
204
+ And { tag_uri.specific == authority_name }
205
+ And { tag_uri.fragment == fragment }
206
+ end
207
+ context "date given" do
208
+ When(:tag_uri) { TagURI::URI.new uri: url,
209
+ date: date }
210
+ Given(:expected) { "tag:sandro@hawke.org,2001-06-05:sandro@hawke.org" }
211
+ Then { tag_uri.to_s == expected }
212
+ And { tag_uri.scheme == "tag" }
213
+ And { tag_uri.authority_name == authority_name }
214
+ And { tag_uri.date == date }
215
+ And { tag_uri.specific == authority_name }
216
+ And { tag_uri.fragment == fragment }
217
+ end
218
+ context "specific given" do
219
+ When(:tag_uri) { TagURI::URI.new uri: url,
220
+ specific: specific }
221
+ Given(:expected) { "tag:sandro@hawke.org,2018-03-11:Taiko" }
222
+ Then { tag_uri.to_s == expected }
223
+ And { tag_uri.scheme == "tag" }
224
+ And { tag_uri.authority_name == authority_name }
225
+ And { tag_uri.date == TIME_NOW }
226
+ And { tag_uri.specific == specific }
227
+ And { tag_uri.fragment == fragment }
228
+ end
229
+ context "No authority_name or domain or email given" do
230
+ context "But the URI has valid one of those" do
231
+ When(:tag_uri) { TagURI::URI.new uri: url, specific: specific, date: date }
232
+ Then { tag_uri.to_s == expected }
233
+ And { tag_uri.scheme == "tag" }
234
+ And { tag_uri.authority_name == authority_name }
235
+ And { tag_uri.date == date }
236
+ And { tag_uri.specific == specific }
237
+ And { tag_uri.fragment == fragment }
238
+ end
239
+ end
21
240
  end
22
- context "That are not valid" do
23
- it "raises" do
24
- expect { TagURI.create prefix: prefix, host: nil, created_at: model.created_at, slug: model.slug }.to raise_error TagURI::ArgumentError
241
+ end
242
+ context "And one I made up because I was listening to Beeswax by Nirvana at the time" do
243
+ context "Beeswax" do
244
+ Given(:url) { "http://example.com/2019-01-09/beeswax#bees" }
245
+ Given(:specific) { "beeswax" }
246
+ Given(:date) { Time.parse "2019-01-08" }
247
+ Given(:authority_name) { "example.com" }
248
+ Given(:expected) { "tag:example.com,2019-01-08:beeswax#bees" }
249
+ Given(:fragment) { "bees" }
250
+ context "identity" do
251
+ When(:tag_uri) { TagURI::URI.new uri: expected }
252
+ Then { tag_uri.to_s == expected }
253
+ And { tag_uri.scheme == "tag" }
254
+ And { tag_uri.authority_name == authority_name }
255
+ And { tag_uri.date == date }
256
+ And { tag_uri.specific == specific }
257
+ And { tag_uri.fragment == fragment }
258
+ end
259
+ context "authority_name given" do
260
+ When(:tag_uri) { TagURI::URI.new uri: url,
261
+ authority_name: authority_name }
262
+ Given(:expected) { "tag:example.com,2019-01-09:/2019-01-09/beeswax#bees" }
263
+ Then { tag_uri.to_s == expected }
264
+ And { tag_uri.scheme == "tag" }
265
+ And { tag_uri.authority_name == authority_name }
266
+ And { tag_uri.date == Time.parse("2019-01-09") }
267
+ And { tag_uri.specific == "/2019-01-09/beeswax" }
268
+ And { tag_uri.fragment == fragment }
269
+ end
270
+ context "date given" do
271
+ When(:tag_uri) { TagURI::URI.new uri: url,
272
+ date: date }
273
+ Given(:expected) { "tag:example.com,2019-01-08:/2019-01-09/beeswax#bees" }
274
+ Then { tag_uri.to_s == expected }
275
+ And { tag_uri.scheme == "tag" }
276
+ And { tag_uri.authority_name == authority_name }
277
+ And { tag_uri.date == date }
278
+ And { tag_uri.specific == "/2019-01-09/beeswax" }
279
+ And { tag_uri.fragment == fragment }
25
280
  end
281
+ context "fragment given" do
282
+ When(:tag_uri) { TagURI::URI.new uri: url,
283
+ fragment: "bees" }
284
+ Given(:expected) { "tag:example.com,2019-01-09:/2019-01-09/beeswax#bees" }
285
+ Then { tag_uri.to_s == expected }
286
+ And { tag_uri.scheme == "tag" }
287
+ And { tag_uri.authority_name == authority_name }
288
+ And { tag_uri.date == Time.parse("2019-01-09") }
289
+ And { tag_uri.specific == "/2019-01-09/beeswax" }
290
+ And { tag_uri.fragment == fragment }
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+ describe "Validating a tag" do
297
+ context "A valid tag" do
298
+ Given(:a_tag) { "tag:diveintomark.org,2004-05-27:/archives/2004/05/27/howto-atom-linkblog" }
299
+ When(:tag_uri) { TagURI::URI.new uri: a_tag }
300
+ Then { tag_uri.valid? }
301
+ end
302
+ context "An invalid tag" do
303
+ Given(:a_tag) { "tag:,2004-05-27:/archives/2004/05/27/howto-atom-linkblog" }
304
+ When(:tag_uri) { TagURI::URI.new uri: a_tag }
305
+ Then { !tag_uri.valid? }
306
+ end
307
+ end
308
+
309
+
310
+ SHOULD = []
311
+ SHOULD_NOT = []
312
+ pn = Spec_dir.join("support/fixtures/urls.txt")
313
+
314
+ pn.each_line do |line|
315
+ line.chomp!
316
+ next if line.nil? or line.empty?
317
+ if ~ /^SHOULD MATCH\:/ ... ~ /^END/ # flip flop be bop
318
+ SHOULD << line unless $~ or ~ /^SHOULD MATCH\:/
319
+ else
320
+ SHOULD_NOT << line unless ~ /^SHOULD NOT MATCH\:/
321
+ end
322
+ end
323
+
324
+
325
+ describe "TagURI::URI::DNSNAME" do
326
+
327
+ SHOULD.each do |uri|
328
+ context "#{uri}" do
329
+ When(:match) { /^#{TagURI::URI::DNSNAME}$/ =~ uri }
330
+ Then { match }
331
+ end
332
+ end
333
+
334
+ SHOULD_NOT.each do |uri|
335
+ context "#{uri}" do
336
+ When(:match) { /^#{TagURI::URI::DNSNAME}$/ =~ uri }
337
+ Then { !match }
26
338
  end
27
339
  end
28
340
  end
@@ -7,10 +7,10 @@ Gem::Specification.new do |gem|
7
7
  gem.name = "tag_uri"
8
8
  gem.version = TagURI::VERSION
9
9
  gem.authors = ["Iain Barnett"]
10
- gem.email = ["iainspeed@gmail.com"]
10
+ gem.email = ["helpful-iain@theprintedbird.com"]
11
11
  gem.description = %q{An implementation of tag URI's.
12
12
  See http://tools.ietf.org/html/rfc4151}
13
- gem.summary = %q{Instead of using a permalink as the id for an Atom feed entry, use a tag URI.}
13
+ gem.summary = %q{Instead of using a permalink as the id for an Atom feed entry (or anything else you'd use a permalink for), use a tag URI.}
14
14
  gem.homepage = "https://github.com/yb66/tag-uri"
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
@@ -19,4 +19,6 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
  gem.add_dependency("addressable")
21
21
  gem.required_ruby_version = '~> 2.0'
22
+ gem.cert_chain = ['certs/yb66.pem']
23
+ gem.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
22
24
  end
metadata CHANGED
@@ -1,14 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tag_uri
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iain Barnett
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain: []
11
- date: 2015-06-14 00:00:00.000000000 Z
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEbjCCAtagAwIBAgIBATANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDDCVoZWxw
14
+ ZnVsLWlhaW4vREM9dGhlcHJpbnRlZGJpcmQvREM9Y29tMB4XDTE5MDExNTA3MjAw
15
+ OVoXDTIwMDExNTA3MjAwOVowMDEuMCwGA1UEAwwlaGVscGZ1bC1pYWluL0RDPXRo
16
+ ZXByaW50ZWRiaXJkL0RDPWNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoC
17
+ ggGBALhp1KlrdriWAuhXhM3I0oZblbOUAgk8UZSyI6vLQ4oK8uHWmdBkrzUublq4
18
+ 7cU1T0IIFeKOzjN2aXS660q2Ev7Bpwt1oBjMVqLMZYJM4gixwzXW9labQhnjefEy
19
+ CTWRa/i4gL8NbwOg/UeX5rHiCy/xaqyxj//24E7m5e72JrpK11ZZ5/4TUvxDfOJr
20
+ w+16BAxH3ELBRjXoOXnlb7SzA2ohNnwuoom5gi9Ju6z0ooSa9cegqauHBbme8wgO
21
+ 5bPwGi+MbiLKoMDcnakuUoKqWL6qA+/QofNnrmtgBmMe08dd9/ermztT/dBdNQiE
22
+ eOXDR+sM5ardxl+5TdAcGuheMgZBiBVqaMVowUp1VPV1f/sY8RsfYqFVBg/I+jcu
23
+ uulV50CkaLYmZVa0sWiCNg/pkKROpVktwfkRo3EKCllckMc29qPts64g0UkyBi1q
24
+ stO7Yk/0PmhHcWHHv8Lfuin0Cmpt01AuKi3ToOBJHAvLWkORlOw1mIC9mdOR3c9Y
25
+ jeBbawIDAQABo4GSMIGPMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
26
+ BBSyOPfHSTgay7iGZ94b0JDrrcaBDTAqBgNVHREEIzAhgR9oZWxwZnVsLWlhaW5A
27
+ dGhlcHJpbnRlZGJpcmQuY29tMCoGA1UdEgQjMCGBH2hlbHBmdWwtaWFpbkB0aGVw
28
+ cmludGVkYmlyZC5jb20wDQYJKoZIhvcNAQELBQADggGBAAoYHPvpy84kUzvM1tMF
29
+ AMUFH6V/hkBdcTRS3mE+8lpMHBiPluByk1/vfUTlo9kGFtEEXd1ginKqMozLKFrr
30
+ 5yRAi08zsRA0pSDuOJsX95x4Rr5GnAUKeVOXJHry0Kae3btQdJ59ZqvFPyNiXKEB
31
+ SUIa4GUcWFaIl2yL7epcCNsyhEqvnRPq0zvfY0IGT3AcHxchCWbnurkci32eAiqW
32
+ TESqr8zDJzsH7HSyOHlNdvWQRrYfhh8p+JsbRqJ4rChBPYnZM6fnlFtvPUNbBaRr
33
+ cw7FROiP0G0E7GAd7loZ78WoQEM6regiCibP3LPehIl94P3K2+CCOI148rNlyXBE
34
+ ATDB99qMn3ZgZEE0i5jxxVOHbMQWcvN3oElPuVVq6gLhqnZn50DW2B6wf3s4MMMd
35
+ ILghhrKlF+3IGSo6pOtgZB3Y84IgtvmYyo3Unv8VkRqZ22ZSxz7GFy+X7SABSGxU
36
+ ewk/WBT8wib1dm745Y+U42Icj8FgHqKkq1mDIcMcyLqxLA==
37
+ -----END CERTIFICATE-----
38
+ date: 2019-01-15 00:00:00.000000000 Z
12
39
  dependencies:
13
40
  - !ruby/object:Gem::Dependency
14
41
  name: addressable
@@ -28,7 +55,7 @@ description: |-
28
55
  An implementation of tag URI's.
29
56
  See http://tools.ietf.org/html/rfc4151
30
57
  email:
31
- - iainspeed@gmail.com
58
+ - helpful-iain@theprintedbird.com
32
59
  executables: []
33
60
  extensions: []
34
61
  extra_rdoc_files: []
@@ -40,11 +67,13 @@ files:
40
67
  - LICENCE.txt
41
68
  - README.md
42
69
  - Rakefile
70
+ - certs/yb66.pem
43
71
  - lib/tag-uri.rb
44
72
  - lib/tag_uri.rb
45
73
  - lib/tag_uri/version.rb
46
74
  - lib/taguri.rb
47
75
  - spec/spec_helper.rb
76
+ - spec/support/fixtures/urls.txt
48
77
  - spec/tag_uri_spec.rb
49
78
  - tag_uri.gemspec
50
79
  homepage: https://github.com/yb66/tag-uri
@@ -66,11 +95,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
95
  version: '0'
67
96
  requirements: []
68
97
  rubyforge_project:
69
- rubygems_version: 2.4.5
98
+ rubygems_version: 2.7.3
70
99
  signing_key:
71
100
  specification_version: 4
72
- summary: Instead of using a permalink as the id for an Atom feed entry, use a tag
73
- URI.
101
+ summary: Instead of using a permalink as the id for an Atom feed entry (or anything
102
+ else you'd use a permalink for), use a tag URI.
74
103
  test_files:
75
104
  - spec/spec_helper.rb
105
+ - spec/support/fixtures/urls.txt
76
106
  - spec/tag_uri_spec.rb
Binary file