licensee 9.13.0 → 9.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/bin/licensee +2 -2
  4. data/lib/licensee.rb +4 -4
  5. data/lib/licensee/commands/detect.rb +3 -5
  6. data/lib/licensee/commands/diff.rb +3 -5
  7. data/lib/licensee/content_helper.rb +41 -44
  8. data/lib/licensee/hash_helper.rb +1 -1
  9. data/lib/licensee/license.rb +29 -15
  10. data/lib/licensee/matchers.rb +1 -0
  11. data/lib/licensee/matchers/cabal.rb +1 -1
  12. data/lib/licensee/matchers/cargo.rb +1 -1
  13. data/lib/licensee/matchers/copyright.rb +3 -8
  14. data/lib/licensee/matchers/cran.rb +1 -1
  15. data/lib/licensee/matchers/dice.rb +2 -2
  16. data/lib/licensee/matchers/dist_zilla.rb +1 -1
  17. data/lib/licensee/matchers/gemspec.rb +4 -4
  18. data/lib/licensee/matchers/npm_bower.rb +5 -2
  19. data/lib/licensee/matchers/nuget.rb +43 -0
  20. data/lib/licensee/matchers/spdx.rb +1 -1
  21. data/lib/licensee/project_files/license_file.rb +29 -22
  22. data/lib/licensee/project_files/package_manager_file.rb +3 -2
  23. data/lib/licensee/project_files/project_file.rb +3 -4
  24. data/lib/licensee/project_files/readme_file.rb +1 -1
  25. data/lib/licensee/projects/fs_project.rb +8 -5
  26. data/lib/licensee/projects/git_project.rb +6 -4
  27. data/lib/licensee/projects/github_project.rb +1 -1
  28. data/lib/licensee/projects/project.rb +11 -10
  29. data/lib/licensee/version.rb +1 -1
  30. data/licensee.gemspec +7 -8
  31. data/spec/fixture_spec.rb +3 -3
  32. data/spec/fixtures/bom/LICENSE.txt +21 -0
  33. data/spec/fixtures/bsd-3-authorowner/LICENSE +27 -0
  34. data/spec/fixtures/bsd-3-noendorseslash/LICENSE +30 -0
  35. data/spec/fixtures/cc-by-sa-mdlinks/License.md +173 -0
  36. data/spec/fixtures/cc-by-sa-nocclicensor/License.md +425 -0
  37. data/spec/fixtures/crlf-bsd/LICENSE.md +27 -0
  38. data/spec/fixtures/detect.json +16 -22
  39. data/spec/fixtures/eupl-cal2017/LICENSE.txt +274 -0
  40. data/spec/fixtures/fixtures.yml +68 -20
  41. data/spec/fixtures/license-hashes.json +39 -37
  42. data/spec/fixtures/markdown-artistic/LICENSE.md +192 -0
  43. data/spec/fixtures/multiple-arrs/LICENSE +30 -0
  44. data/spec/fixtures/pixar-modified-apache/LICENSE.txt +174 -0
  45. data/spec/fixtures/readme-invalid-encoding/README.md +24 -0
  46. data/spec/fixtures/vim/LICENSE +78 -0
  47. data/spec/integration_spec.rb +104 -9
  48. data/spec/licensee/commands/detect_spec.rb +2 -2
  49. data/spec/licensee/content_helper_spec.rb +17 -21
  50. data/spec/licensee/hash_helper_spec.rb +22 -22
  51. data/spec/licensee/license_meta_spec.rb +5 -11
  52. data/spec/licensee/license_spec.rb +14 -10
  53. data/spec/licensee/matchers/dice_matcher_spec.rb +4 -11
  54. data/spec/licensee/matchers/matcher_spec.rb +6 -6
  55. data/spec/licensee/matchers/npm_bower_matcher_spec.rb +9 -0
  56. data/spec/licensee/matchers/nu_get_matcher_spec.rb +91 -0
  57. data/spec/licensee/project_files/license_file_spec.rb +35 -28
  58. data/spec/licensee/project_files/package_info_spec.rb +8 -0
  59. data/spec/licensee/project_spec.rb +1 -3
  60. data/spec/licensee/rule_spec.rb +1 -1
  61. data/spec/licensee_spec.rb +1 -1
  62. data/spec/spec_helper.rb +3 -3
  63. data/spec/vendored_license_spec.rb +2 -2
  64. data/vendor/choosealicense.com/_data/meta.yml +1 -1
  65. data/vendor/choosealicense.com/_data/rules.yml +13 -13
  66. data/vendor/choosealicense.com/_licenses/0bsd.txt +3 -3
  67. data/vendor/choosealicense.com/_licenses/apache-2.0.txt +4 -4
  68. data/vendor/choosealicense.com/_licenses/artistic-2.0.txt +1 -1
  69. data/vendor/choosealicense.com/_licenses/bsd-2-clause.txt +3 -3
  70. data/vendor/choosealicense.com/_licenses/bsd-3-clause.txt +3 -3
  71. data/vendor/choosealicense.com/_licenses/bsd-4-clause.txt +3 -3
  72. data/vendor/choosealicense.com/_licenses/bsl-1.0.txt +4 -3
  73. data/vendor/choosealicense.com/_licenses/cc-by-4.0.txt +16 -16
  74. data/vendor/choosealicense.com/_licenses/cc-by-sa-4.0.txt +16 -16
  75. data/vendor/choosealicense.com/_licenses/cc0-1.0.txt +4 -4
  76. data/vendor/choosealicense.com/_licenses/cecill-2.1.txt +6 -6
  77. data/vendor/choosealicense.com/_licenses/ecl-2.0.txt +4 -4
  78. data/vendor/choosealicense.com/_licenses/epl-1.0.txt +3 -3
  79. data/vendor/choosealicense.com/_licenses/epl-2.0.txt +5 -5
  80. data/vendor/choosealicense.com/_licenses/eupl-1.2.txt +77 -60
  81. data/vendor/choosealicense.com/_licenses/gpl-2.0.txt +3 -3
  82. data/vendor/choosealicense.com/_licenses/gpl-3.0.txt +4 -4
  83. data/vendor/choosealicense.com/_licenses/isc.txt +3 -3
  84. data/vendor/choosealicense.com/_licenses/lgpl-3.0.txt +0 -1
  85. data/vendor/choosealicense.com/_licenses/lppl-1.3c.txt +1 -1
  86. data/vendor/choosealicense.com/_licenses/mit-0.txt +45 -0
  87. data/vendor/choosealicense.com/_licenses/mit.txt +3 -3
  88. data/vendor/choosealicense.com/_licenses/mpl-2.0.txt +3 -3
  89. data/vendor/choosealicense.com/_licenses/ncsa.txt +24 -24
  90. data/vendor/choosealicense.com/_licenses/odbl-1.0.txt +3 -3
  91. data/vendor/choosealicense.com/_licenses/ofl-1.1.txt +4 -4
  92. data/vendor/choosealicense.com/_licenses/osl-3.0.txt +3 -3
  93. data/vendor/choosealicense.com/_licenses/postgresql.txt +5 -5
  94. data/vendor/choosealicense.com/_licenses/unlicense.txt +3 -3
  95. data/vendor/choosealicense.com/_licenses/upl-1.0.txt +4 -4
  96. data/vendor/choosealicense.com/_licenses/vim.txt +111 -0
  97. data/vendor/choosealicense.com/_licenses/zlib.txt +3 -3
  98. data/vendor/license-list-XML/src/0BSD.xml +21 -0
  99. data/vendor/license-list-XML/src/AFL-3.0.xml +212 -0
  100. data/vendor/license-list-XML/src/AGPL-3.0.xml +852 -0
  101. data/vendor/license-list-XML/src/Apache-2.0.xml +223 -0
  102. data/vendor/license-list-XML/src/Artistic-2.0.xml +238 -0
  103. data/vendor/license-list-XML/src/BSD-2-Clause.xml +42 -0
  104. data/vendor/license-list-XML/src/BSD-3-Clause-Clear.xml +59 -0
  105. data/vendor/license-list-XML/src/BSD-3-Clause.xml +46 -0
  106. data/vendor/license-list-XML/src/BSD-4-Clause.xml +59 -0
  107. data/vendor/license-list-XML/src/BSL-1.0.xml +30 -0
  108. data/vendor/license-list-XML/src/CC-BY-4.0.xml +444 -0
  109. data/vendor/license-list-XML/src/CC-BY-SA-4.0.xml +475 -0
  110. data/vendor/license-list-XML/src/CC0-1.0.xml +153 -0
  111. data/vendor/license-list-XML/src/CECILL-2.1.xml +669 -0
  112. data/vendor/license-list-XML/src/ECL-2.0.xml +242 -0
  113. data/vendor/license-list-XML/src/EPL-1.0.xml +255 -0
  114. data/vendor/license-list-XML/src/EPL-2.0.xml +639 -0
  115. data/vendor/license-list-XML/src/EUPL-1.1.xml +337 -0
  116. data/vendor/license-list-XML/src/EUPL-1.2.xml +502 -0
  117. data/vendor/license-list-XML/src/GPL-2.0.xml +474 -0
  118. data/vendor/license-list-XML/src/GPL-3.0.xml +858 -0
  119. data/vendor/license-list-XML/src/ISC.xml +29 -0
  120. data/vendor/license-list-XML/src/LGPL-2.1.xml +662 -0
  121. data/vendor/license-list-XML/src/LGPL-3.0.xml +260 -0
  122. data/vendor/license-list-XML/src/LPPL-1.3c.xml +380 -0
  123. data/vendor/license-list-XML/src/MIT-0.xml +40 -0
  124. data/vendor/license-list-XML/src/MIT.xml +32 -0
  125. data/vendor/license-list-XML/src/MPL-2.0.xml +438 -0
  126. data/vendor/license-list-XML/src/MS-PL.xml +89 -0
  127. data/vendor/license-list-XML/src/MS-RL.xml +97 -0
  128. data/vendor/license-list-XML/src/NCSA.xml +60 -0
  129. data/vendor/license-list-XML/src/ODbL-1.0.xml +660 -0
  130. data/vendor/license-list-XML/src/OFL-1.1.xml +94 -0
  131. data/vendor/license-list-XML/src/OSL-3.0.xml +209 -0
  132. data/vendor/license-list-XML/src/PostgreSQL.xml +32 -0
  133. data/vendor/license-list-XML/src/UPL-1.0.xml +46 -0
  134. data/vendor/license-list-XML/src/Unlicense.xml +27 -0
  135. data/vendor/license-list-XML/src/Vim.xml +124 -0
  136. data/vendor/license-list-XML/src/WTFPL.xml +30 -0
  137. data/vendor/license-list-XML/src/Zlib.xml +38 -0
  138. metadata +97 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7aeb33320898c7e64f31f6ea15708f4e4c23a6856e10c54e004054ee6997200a
4
- data.tar.gz: dcbac4f8b08ff1d55e0ac7de2b603c67ce4f9a2b7d9486fbfccae3fa0dc6d304
3
+ metadata.gz: 63f3f7938e9e0c58907e71bcf9de72e69d2d494d2dbbba6c71e150b44190eda3
4
+ data.tar.gz: 51583db05dee9239fb50e373f3dc4c79dfa4515a5461facc2722dabe5ee0fb9a
5
5
  SHA512:
6
- metadata.gz: d92bb1d7662b504e92ad6a2fa3f0c8fa23716fa3825715333f8483085a8662d94d61032ec2e4155ae93b9bc0e71627f9e841268e1c7b2229078f13da216d0394
7
- data.tar.gz: 364fe3f78e38f703a1e7c9317453b598e4a4bc0b8db773efd4e6e701e7f3a730426698c3a4561e34ba09e839a35a24d4526d87595de31f687a7e83c932bf4ae2
6
+ metadata.gz: 87b8a85992cec7c2e7c30fab5b96e33a0fdd4271df34a99ca2b99584f1f94cdcb70c5663d9a584ccf1164fd10eca2b1e7b26f09bb7b43a81a8c3705dc6341666
7
+ data.tar.gz: b261c2cf6a2b40fd5b4b10bd4644d179dda3e35686b6f6361af4177dcda852eb45c22bf0dafc43291824a2c48b30f1297c2f933a7786f12dbefbb0bde6dfb83b
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2014-2017 Ben Balter
3
+ Copyright (c) 2014-2021 Ben Balter and Licensee contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/bin/licensee CHANGED
@@ -19,7 +19,7 @@ class LicenseeCLI < Thor
19
19
  args.first || Dir.pwd
20
20
  else
21
21
  "https://github.com/#{args.first}"
22
- end
22
+ end
23
23
  end
24
24
 
25
25
  def project
@@ -33,6 +33,6 @@ class LicenseeCLI < Thor
33
33
  end
34
34
 
35
35
  commands_dir = File.expand_path '../lib/licensee/commands/', __dir__
36
- Dir["#{commands_dir}/*.rb"].each { |c| require(c) }
36
+ Dir["#{commands_dir}/*.rb"].sort.each { |c| require(c) }
37
37
 
38
38
  LicenseeCLI.start(ARGV)
data/lib/licensee.rb CHANGED
@@ -37,13 +37,13 @@ module Licensee
37
37
  end
38
38
 
39
39
  def project(path, **args)
40
- if path =~ %r{\Ahttps://github.com}
41
- Licensee::Projects::GitHubProject.new(path, args)
40
+ if %r{\Ahttps://github.com}.match?(path)
41
+ Licensee::Projects::GitHubProject.new(path, **args)
42
42
  else
43
- Licensee::Projects::GitProject.new(path, args)
43
+ Licensee::Projects::GitProject.new(path, **args)
44
44
  end
45
45
  rescue Licensee::Projects::GitProject::InvalidRepository
46
- Licensee::Projects::FSProject.new(path, args)
46
+ Licensee::Projects::FSProject.new(path, **args)
47
47
  end
48
48
 
49
49
  def confidence_threshold
@@ -28,11 +28,9 @@ class LicenseeCLI < Thor
28
28
  ['Licenses:', project.licenses.map(&:spdx_id)]
29
29
  else
30
30
  ['License:', set_color('None', :red)]
31
- end
31
+ end
32
32
 
33
- unless project.matched_files.empty?
34
- rows << ['Matched files:', project.matched_files.map(&:filename).join(', ')]
35
- end
33
+ rows << ['Matched files:', project.matched_files.map(&:filename).join(', ')] unless project.matched_files.empty?
36
34
 
37
35
  print_table rows
38
36
 
@@ -88,7 +86,7 @@ class LicenseeCLI < Thor
88
86
  when :confidence
89
87
  Licensee::ContentHelper.format_percent(value)
90
88
  when :method
91
- value.to_s.tr('_', ' ').capitalize + ':'
89
+ "#{value.to_s.tr('_', ' ').capitalize}:"
92
90
  else
93
91
  value
94
92
  end
@@ -41,17 +41,15 @@ class LicenseeCLI < Thor
41
41
 
42
42
  def license_to_diff
43
43
  return options[:license_to_diff] if options[:license_to_diff]
44
- return project.license_file if remote? || STDIN.tty? && project.license_file
44
+ return project.license_file if remote? || $stdin.tty? && project.license_file
45
45
 
46
46
  @license_to_diff ||= begin
47
- Licensee::ProjectFiles::LicenseFile.new(STDIN.read, 'LICENSE')
47
+ Licensee::ProjectFiles::LicenseFile.new($stdin.read, 'LICENSE')
48
48
  end
49
49
  end
50
50
 
51
51
  def expected_license
52
- if options[:license]
53
- @expected_license ||= Licensee::License.find options[:license]
54
- end
52
+ @expected_license ||= Licensee::License.find options[:license] if options[:license]
55
53
  return @expected_license if @expected_license
56
54
 
57
55
  if options[:license]
@@ -7,23 +7,24 @@ module Licensee
7
7
  module ContentHelper
8
8
  DIGEST = Digest::SHA1
9
9
  START_REGEX = /\A\s*/.freeze
10
- END_OF_TERMS_REGEX = /^[\s#*_]*end of terms and conditions\s*$/i.freeze
10
+ END_OF_TERMS_REGEX = /^[\s#*_]*end of terms and conditions[\s#*_]*$/i.freeze
11
11
  REGEXES = {
12
- hrs: /^\s*[=\-\*]{3,}\s*$/,
12
+ bom: /#{START_REGEX}\xEF\xBB\xBF/,
13
+ hrs: /^\s*[=\-*]{3,}\s*$/,
13
14
  all_rights_reserved: /#{START_REGEX}all rights reserved\.?$/i,
14
15
  whitespace: /\s+/,
15
- markdown_headings: /#{START_REGEX}#+/,
16
+ markdown_headings: /^\s*#+/,
16
17
  version: /#{START_REGEX}version.*$/i,
17
18
  span_markup: /[_*~]+(.*?)[_*~]+/,
18
19
  link_markup: /\[(.+?)\]\(.+?\)/,
19
20
  block_markup: /^\s*>/,
20
- border_markup: /^[\*-](.*?)[\*-]$/,
21
- comment_markup: %r{^\s*?[/\*]{1,2}},
21
+ border_markup: /^[*-](.*?)[*-]$/,
22
+ comment_markup: %r{^\s*?[/*]{1,2}},
22
23
  url: %r{#{START_REGEX}https?://[^ ]+\n},
23
- bullet: /\n\n\s*(?:[*-]|\(?[\da-z]{1,2}[)\.])\s+/i,
24
+ bullet: /\n\n\s*(?:[*-]|\(?[\da-z]{1,2}[).])\s+/i,
24
25
  developed_by: /#{START_REGEX}developed by:.*?\n\n/im,
25
- quote_begin: /[`'"‘“]/,
26
- quote_end: /[`'"’”]/,
26
+ cc_dedication: /The\s+text\s+of\s+the\s+Creative\s+Commons.*?Public\s+Domain\s+Dedication./im,
27
+ cc_wiki: /wiki.creativecommons.org/i,
27
28
  cc_legal_code: /^\s*Creative Commons Legal Code\s*$/i,
28
29
  cc0_info: /For more information, please see\s*\S+zero\S+/im,
29
30
  cc0_disclaimer: /CREATIVE COMMONS CORPORATION.*?\n\n/im,
@@ -35,10 +36,7 @@ module Licensee
35
36
  https: { from: /http:/, to: 'https:' },
36
37
  ampersands: { from: '&', to: 'and' },
37
38
  dashes: { from: /(?<!^)([—–-]+)(?!$)/, to: '-' },
38
- quotes: {
39
- from: /#{REGEXES[:quote_begin]}+([\w -]*?\w)#{REGEXES[:quote_end]}+/,
40
- to: '"\1"'
41
- }
39
+ quote: { from: /[`'"‘“’”]/, to: "'" }
42
40
  }.freeze
43
41
 
44
42
  # Legally equivalent words that schould be ignored for comparison
@@ -88,10 +86,10 @@ module Licensee
88
86
  'owner' => 'holder'
89
87
  }.freeze
90
88
  STRIP_METHODS = %i[
89
+ bom
90
+ cc_optional
91
91
  cc0_optional
92
92
  unlicense_optional
93
- hrs
94
- markdown_headings
95
93
  borders
96
94
  title
97
95
  version
@@ -99,9 +97,6 @@ module Licensee
99
97
  copyright
100
98
  title
101
99
  block_markup
102
- span_markup
103
- link_markup
104
- all_rights_reserved
105
100
  developed_by
106
101
  end_of_terms
107
102
  whitespace
@@ -110,35 +105,30 @@ module Licensee
110
105
 
111
106
  # A set of each word in the license, without duplicates
112
107
  def wordset
113
- @wordset ||= content_normalized&.scan(/(?:\w(?:'s|(?<=s)')?)+/)&.to_set
108
+ @wordset ||= content_normalized&.scan(%r{(?:[\w/-](?:'s|(?<=s)')?)+})&.to_set
114
109
  end
115
110
 
116
- # Number of characteres in the normalized content
111
+ # Number of characters in the normalized content
117
112
  def length
118
113
  return 0 unless content_normalized
119
114
 
120
115
  content_normalized.length
121
116
  end
122
117
 
123
- # Number of characters that could be added/removed to still be
124
- # considered a potential match
125
- def max_delta
126
- @max_delta ||= fields_normalized.size * 10 +
127
- (length * Licensee.inverse_confidence_threshold).to_i
128
- end
129
-
130
118
  # Given another license or project file, calculates the difference in length
131
119
  def length_delta(other)
132
120
  (length - other.length).abs
133
121
  end
134
122
 
135
123
  # Given another license or project file, calculates the similarity
136
- # as a percentage of words in common
124
+ # as a percentage of words in common, minus a tiny penalty that
125
+ # increases with size difference between licenses so that false
126
+ # positives for long licnses are ruled out by this score alone.
137
127
  def similarity(other)
138
128
  overlap = (wordset_fieldless & other.wordset).size
139
129
  total = wordset_fieldless.size + other.wordset.size -
140
130
  fields_normalized_set.size
141
- 100.0 * (overlap * 2.0 / total)
131
+ (overlap * 200.0) / (total + variation_adjusted_length_delta(other) / 4)
142
132
  end
143
133
 
144
134
  # SHA1 of the normalized content
@@ -153,7 +143,7 @@ module Licensee
153
143
  def content_without_title_and_version
154
144
  @content_without_title_and_version ||= begin
155
145
  @_content = nil
156
- ops = %i[html hrs comments markdown_headings title version]
146
+ ops = %i[html hrs comments markdown_headings link_markup title version]
157
147
  ops.each { |op| strip(op) }
158
148
  _content
159
149
  end
@@ -163,7 +153,7 @@ module Licensee
163
153
  @content_normalized ||= begin
164
154
  @_content = content_without_title_and_version.downcase
165
155
 
166
- (NORMALIZATIONS.keys + %i[spelling bullets]).each { |op| normalize(op) }
156
+ (NORMALIZATIONS.keys + %i[spelling span_markup bullets]).each { |op| normalize(op) }
167
157
  STRIP_METHODS.each { |op| strip(op) }
168
158
 
169
159
  _content
@@ -191,12 +181,10 @@ module Licensee
191
181
  text.gsub!(/([^\n])\n([^\n])/, '\1 \2')
192
182
 
193
183
  text = text.split("\n").collect do |line|
194
- if line =~ REGEXES[:hrs]
184
+ if line =~ REGEXES[:hrs] || line.length <= line_width
195
185
  line
196
- elsif line.length > line_width
197
- line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
198
186
  else
199
- line
187
+ line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
200
188
  end
201
189
  end * "\n"
202
190
 
@@ -238,9 +226,7 @@ module Licensee
238
226
  meth = "strip_#{regex_or_sym}"
239
227
  return send(meth) if respond_to?(meth, true)
240
228
 
241
- unless REGEXES[regex_or_sym]
242
- raise ArgumentError, "#{regex_or_sym} is an invalid regex reference"
243
- end
229
+ raise ArgumentError, "#{regex_or_sym} is an invalid regex reference" unless REGEXES[regex_or_sym]
244
230
 
245
231
  regex_or_sym = REGEXES[regex_or_sym]
246
232
  end
@@ -249,9 +235,7 @@ module Licensee
249
235
  end
250
236
 
251
237
  def strip_title
252
- while _content =~ ContentHelper.title_regex
253
- strip(ContentHelper.title_regex)
254
- end
238
+ strip(ContentHelper.title_regex) while _content =~ ContentHelper.title_regex
255
239
  end
256
240
 
257
241
  def strip_borders
@@ -267,7 +251,7 @@ module Licensee
267
251
  end
268
252
 
269
253
  def strip_copyright
270
- regex = Matchers::Copyright::REGEX
254
+ regex = Regexp.union(Matchers::Copyright::REGEX, REGEXES[:all_rights_reserved])
271
255
  strip(regex) while _content =~ regex
272
256
  end
273
257
 
@@ -279,6 +263,13 @@ module Licensee
279
263
  strip(REGEXES[:cc0_disclaimer])
280
264
  end
281
265
 
266
+ def strip_cc_optional
267
+ return unless _content.include? 'creative commons'
268
+
269
+ strip(REGEXES[:cc_dedication])
270
+ strip(REGEXES[:cc_wiki])
271
+ end
272
+
282
273
  def strip_unlicense_optional
283
274
  return unless _content.include? 'unlicense'
284
275
 
@@ -290,7 +281,7 @@ module Licensee
290
281
  @_content = body
291
282
  end
292
283
 
293
- def strip_span_markup
284
+ def normalize_span_markup
294
285
  normalize(REGEXES[:span_markup], '\1')
295
286
  end
296
287
 
@@ -300,7 +291,7 @@ module Licensee
300
291
 
301
292
  def strip_html
302
293
  return unless respond_to?(:filename) && filename
303
- return unless File.extname(filename) =~ /\.html?/i
294
+ return unless /\.html?/i.match?(File.extname(filename))
304
295
 
305
296
  require 'reverse_markdown'
306
297
  @_content = ReverseMarkdown.convert(_content, unknown_tags: :bypass)
@@ -324,7 +315,7 @@ module Licensee
324
315
  end
325
316
 
326
317
  def normalize_bullets
327
- normalize(REGEXES[:bullet], "\n\n* ")
318
+ normalize(REGEXES[:bullet], "\n\n- ")
328
319
  normalize(/\)\s+\(/, ')(')
329
320
  end
330
321
 
@@ -341,5 +332,11 @@ module Licensee
341
332
  def fields_normalized_set
342
333
  @fields_normalized_set ||= fields_normalized.to_set
343
334
  end
335
+
336
+ def variation_adjusted_length_delta(other)
337
+ delta = length_delta(other)
338
+ adjusted_delta = delta - [fields_normalized.size, spdx_alt_segments].max * 4
339
+ adjusted_delta.positive? ? adjusted_delta : 0
340
+ end
344
341
  end
345
342
  end
@@ -13,7 +13,7 @@ module Licensee
13
13
  value.to_h
14
14
  else
15
15
  value
16
- end
16
+ end
17
17
  end
18
18
 
19
19
  hash
@@ -4,6 +4,7 @@ require 'uri'
4
4
 
5
5
  module Licensee
6
6
  class InvalidLicense < ArgumentError; end
7
+
7
8
  class License
8
9
  @all = {}
9
10
  @keys_licenses = {}
@@ -26,9 +27,11 @@ module Licensee
26
27
  output.reject!(&:hidden?) unless options[:hidden]
27
28
  output.reject!(&:pseudo_license?) unless options[:pseudo]
28
29
  output.sort_by!(&:key)
29
- return output if options[:featured].nil?
30
-
31
- output.select { |l| l.featured? == options[:featured] }
30
+ if options[:featured].nil?
31
+ output
32
+ else
33
+ output.select { |l| l.featured? == options[:featured] }
34
+ end
32
35
  end
33
36
  end
34
37
 
@@ -53,14 +56,17 @@ module Licensee
53
56
  end
54
57
 
55
58
  def license_dir
56
- dir = ::File.dirname(__FILE__)
57
- ::File.expand_path '../../vendor/choosealicense.com/_licenses', dir
59
+ ::File.expand_path '../../vendor/choosealicense.com/_licenses', __dir__
58
60
  end
59
61
 
60
62
  def license_files
61
63
  @license_files ||= Dir.glob("#{license_dir}/*.txt")
62
64
  end
63
65
 
66
+ def spdx_dir
67
+ ::File.expand_path '../../vendor/license-list-XML/src', __dir__
68
+ end
69
+
64
70
  private
65
71
 
66
72
  def licenses
@@ -82,7 +88,7 @@ module Licensee
82
88
  # `other` - The project had a license, but we were not able to detect it
83
89
  # `no-license` - The project is not licensed (e.g., all rights reserved)
84
90
  #
85
- # Note: A lack of detected license will be a nil license
91
+ # NOTE: A lack of detected license will be a nil license
86
92
  PSEUDO_LICENSES = %w[other no-license].freeze
87
93
 
88
94
  # Default options to use when retrieving licenses via #all
@@ -93,7 +99,7 @@ module Licensee
93
99
  }.freeze
94
100
 
95
101
  SOURCE_PREFIX = %r{https?://(?:www\.)?}i.freeze
96
- SOURCE_SUFFIX = %r{(?:\.html?|\.txt|\/)(?:\?[^\s]*)?}i.freeze
102
+ SOURCE_SUFFIX = %r{(?:\.html?|\.txt|/)(?:\?[^\s]*)?}i.freeze
97
103
 
98
104
  HASH_METHODS = %i[
99
105
  key spdx_id meta url rules fields other? gpl? lgpl? cc?
@@ -154,9 +160,7 @@ module Licensee
154
160
  key_regex = Regexp.new string, 'i'
155
161
 
156
162
  parts = [title_regex, key_regex]
157
- if meta.nickname
158
- parts.push Regexp.new meta.nickname.sub(/\bGNU /i, '(?:GNU )?')
159
- end
163
+ parts.push Regexp.new meta.nickname.sub(/\bGNU /i, '(?:GNU )?') if meta.nickname
160
164
 
161
165
  @title_regex = Regexp.union parts
162
166
  end
@@ -173,8 +177,8 @@ module Licensee
173
177
  return @source_regex if defined? @source_regex
174
178
  return unless meta.source
175
179
 
176
- source = meta.source.dup.sub(/\A#{SOURCE_PREFIX}/, '')
177
- source = source.sub(/#{SOURCE_SUFFIX}\z/, '')
180
+ source = meta.source.dup.sub(/\A#{SOURCE_PREFIX}/o, '')
181
+ source = source.sub(/#{SOURCE_SUFFIX}\z/o, '')
178
182
 
179
183
  escaped_source = Regexp.escape(source)
180
184
  @source_regex = /#{SOURCE_PREFIX}#{escaped_source}(?:#{SOURCE_SUFFIX})?/i
@@ -244,9 +248,7 @@ module Licensee
244
248
  # Raw content of license file, including YAML front matter
245
249
  def raw_content
246
250
  return if pseudo_license?
247
- unless File.exist?(path)
248
- raise Licensee::InvalidLicense, "'#{key}' is not a valid license key"
249
- end
251
+ raise Licensee::InvalidLicense, "'#{key}' is not a valid license key" unless File.exist?(path)
250
252
 
251
253
  @raw_content ||= File.read(path, encoding: 'utf-8')
252
254
  end
@@ -260,5 +262,17 @@ module Licensee
260
262
  def yaml
261
263
  @yaml ||= parts[1] if parts
262
264
  end
265
+
266
+ def spdx_alt_segments
267
+ @spdx_alt_segments ||= begin
268
+ path = File.expand_path "#{spdx_id}.xml", Licensee::License.spdx_dir
269
+ raw_xml = File.read(path, encoding: 'utf-8')
270
+ text = raw_xml.match(%r{<text>(.*)</text>}m)[1]
271
+ text.gsub!(%r{<copyrightText>.*?</copyrightText>}m, '')
272
+ text.gsub!(%r{<titleText>.*?</titleText>}m, '')
273
+ text.gsub!(%r{<optional.*?>.*?</optional>}m, '')
274
+ text.scan(/<alt .*?>/m).size
275
+ end
276
+ end
263
277
  end
264
278
  end
@@ -12,6 +12,7 @@ module Licensee
12
12
  autoload :Exact, 'licensee/matchers/exact'
13
13
  autoload :Gemspec, 'licensee/matchers/gemspec'
14
14
  autoload :NpmBower, 'licensee/matchers/npm_bower'
15
+ autoload :NuGet, 'licensee/matchers/nuget'
15
16
  autoload :Package, 'licensee/matchers/package'
16
17
  autoload :Reference, 'licensee/matchers/reference'
17
18
  autoload :Spdx, 'licensee/matchers/spdx'