jekyll-readme-index 0.3.0 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5bd74269cd40c7051ee807361769d9a049977d4270ee22d0c59db95adb98fea
4
- data.tar.gz: 3b02a03d7b5a5184d0cb3743cf1e778302fb843f16acfaa898a9c7f1870db6a1
3
+ metadata.gz: a962fee2eeeb3f2afc21c0e7a4d99d50db52e11750358d7ea13a1cfc76ea5b01
4
+ data.tar.gz: ed15d139b9f068004a0a7e36defdc56bcfd2fc289299f404548531724b18dad5
5
5
  SHA512:
6
- metadata.gz: 698899c2dd728705703b01002c82854e18b49728eef9f0761caab3e179f05693322579a0fcfdcfb1e6625f0a6ca0afe14220386f6e263daf6b2b11d0e5f04d19
7
- data.tar.gz: 51953c2dd58f121c858b6ff20e712ba20093c35936a517e3f3ebe4369162086daf792fd6ac3db8ae8689507a891f55976947ecf93c552441456880253d3c9b91
6
+ metadata.gz: 259e6eabc8d4b5ea02b77377f331099ec70413fede4d8dc4d2d9ef5ae9ca120d8cdb7892f17b54d00745f48277a0edd976e770d2a6eabba27940fefdedf36a85
7
+ data.tar.gz: d3770314f5f85253a15ad8b471f13ae6fe265f1b6eac759fd56cd62cff09ccd5fd8a8665ed644a5fb68e790ee717f806f1dca3f71fc3b7e54b54f6591d3429a6
@@ -1,8 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
3
5
  module JekyllReadmeIndex
4
6
  class Generator < Jekyll::Generator
5
- INDEX_REGEX = %r!$|index\.(html?|xhtml|xml)$!i.freeze
7
+ # Captures the directory a URL is the index of, e.g. "/a/" for "/a/" or "/a/index.html"
8
+ INDEX_URL_REGEX = %r!\A(.*/)(?:index\.(?:html?|xhtml|xml))?\z!i.freeze
9
+ GITHUB_DIR = "/.github"
10
+ DOCS_DIR = "/docs"
11
+ SPECIAL_DIRS = [GITHUB_DIR, DOCS_DIR].freeze
12
+ GITHUB_README_PATTERN = %r!^/\.github/readme!i.freeze
13
+ DOCS_README_PATTERN = %r!^/docs/readme!i.freeze
14
+ ROOT_README_PATTERN = %r!^/readme!i.freeze
6
15
 
7
16
  attr_accessor :site
8
17
 
@@ -13,6 +22,7 @@ module JekyllReadmeIndex
13
22
  ENABLED_KEY = "enabled"
14
23
  CLEANUP_KEY = "remove_originals"
15
24
  FRONTMATTER_KEY = "with_frontmatter"
25
+ PATTERN_KEY = "readme_pattern"
16
26
 
17
27
  def initialize(site)
18
28
  @site = site
@@ -20,12 +30,15 @@ module JekyllReadmeIndex
20
30
 
21
31
  def generate(site)
22
32
  @site = site
33
+ @index_dirs = nil
23
34
  return if disabled?
24
35
 
25
36
  readmes.each do |readme|
26
37
  next unless should_be_index?(readme)
27
38
 
28
- site.pages << readme.to_page
39
+ page = to_page(readme)
40
+ site.pages << page
41
+ add_index_dir(page.url)
29
42
  site.static_files.delete(readme) if cleanup?
30
43
  end
31
44
 
@@ -33,7 +46,7 @@ module JekyllReadmeIndex
33
46
  readmes_with_frontmatter.each do |readme|
34
47
  next unless should_be_index?(readme)
35
48
 
36
- readme.update_permalink
49
+ add_index_dir(update_permalink(readme))
37
50
  end
38
51
  end
39
52
  end
@@ -42,32 +55,133 @@ module JekyllReadmeIndex
42
55
 
43
56
  # Returns an array of all READMEs as StaticFiles
44
57
  def readmes
45
- site.static_files.select { |file| file.relative_path =~ readme_regex }
58
+ candidates = site.static_files.select { |file| file.relative_path =~ readme_regex }
59
+ prioritize_readmes(candidates)
46
60
  end
47
61
 
48
62
  def readmes_with_frontmatter
49
- site.pages.select { |file| ("/" + file.path) =~ readme_regex }
63
+ candidates = site.pages.select { |file| ("/" + file.path) =~ readme_regex }
64
+ prioritize_readmes(candidates)
65
+ end
66
+
67
+ # Prioritize READMEs according to GitHub's order: .github > root > docs
68
+ # For each target directory, keep only the highest priority README
69
+ def prioritize_readmes(candidates)
70
+ grouped = candidates.group_by do |file|
71
+ # Get the directory that would become the index
72
+ # READMEs in .github and docs should serve as index for parent directory
73
+ # Note: file_path returns Jekyll-normalized paths without query strings
74
+ dir = File.dirname(file_path(file))
75
+
76
+ # If the README is in .github or docs subdirectory at root,
77
+ # it should be the index for root
78
+ if SPECIAL_DIRS.include?(dir)
79
+ "/"
80
+ else
81
+ dir
82
+ end
83
+ end
84
+
85
+ grouped.flat_map do |_dir, files|
86
+ # Sort by priority: .github first, then root, then docs, then others
87
+ files.min_by do |file|
88
+ case readme_path(file)
89
+ when GITHUB_README_PATTERN then 0
90
+ when ROOT_README_PATTERN then 1
91
+ when DOCS_README_PATTERN then 2
92
+ else 3
93
+ end
94
+ end
95
+ end.compact
96
+ end
97
+
98
+ # Convert a README StaticFile to a Page that serves as its directory's index
99
+ def to_page(static_file)
100
+ # StaticFile doesn't expose its base, dir, or name (the last only since
101
+ # Jekyll 4), so read them the same way jekyll-optional-front-matter does.
102
+ base = static_file.instance_variable_get(:@base)
103
+ dir = static_file.instance_variable_get(:@dir)
104
+ name = static_file.instance_variable_get(:@name)
105
+ page = Jekyll::Page.new(site, base, dir, name)
106
+
107
+ page.data["permalink"] = target_dir(static_file)
108
+ page
109
+ end
110
+
111
+ # Point a README Page's permalink at its directory
112
+ def update_permalink(page)
113
+ # If URL already ends with '/', it's a directory URL and should be used as-is
114
+ url = page.url
115
+ page.data["permalink"] = url.end_with?("/") ? url : target_dir(page)
116
+ # Page#url is memoized; drop it so it's rebuilt from the new permalink
117
+ page.instance_variable_set(:@url, nil)
118
+ page.url
119
+ end
120
+
121
+ # The directory a README should be the index for
122
+ def target_dir(file)
123
+ # For READMEs in .github or docs at root level, they should be the root index
124
+ return "/" if special_readme?(file)
125
+
126
+ File.join(File.dirname(file.url), "/")
127
+ end
128
+
129
+ # Check if this is a README in a special directory (.github or docs)
130
+ def special_readme?(file)
131
+ path = readme_path(file)
132
+ path =~ GITHUB_README_PATTERN || path =~ DOCS_README_PATTERN
133
+ end
134
+
135
+ # The file's path relative to the site source, with a leading slash.
136
+ #
137
+ # StaticFile#relative_path starts with "/", but Page#relative_path doesn't
138
+ # on Jekyll 4 (or for root pages on Jekyll 3), so the priority patterns
139
+ # never matched READMEs with front matter.
140
+ def readme_path(file)
141
+ path = file.relative_path
142
+ path.start_with?("/") ? path : "/#{path}"
50
143
  end
51
144
 
52
145
  # Should the given readme be the containing directory's index?
53
146
  def should_be_index?(readme)
54
147
  return false unless readme
55
148
 
56
- !dir_has_index? File.dirname(readme.url)
149
+ !dir_has_index? target_dir(readme)
57
150
  end
58
151
 
59
152
  # Does the given directory have an index?
60
153
  #
61
154
  # relative_path - the directory path relative to the site root
62
155
  def dir_has_index?(relative_path)
63
- relative_path << "/" unless relative_path.end_with? "/"
64
- regex = %r!^#{Regexp.escape(relative_path)}#{INDEX_REGEX}!i
65
- (site.pages + site.static_files).any? { |file| file.url =~ regex }
156
+ relative_path = File.join(relative_path, "/") unless relative_path.end_with?("/")
157
+ index_dirs.include?(relative_path.downcase)
158
+ end
159
+
160
+ # The (downcased) directories that already have an index page or file.
161
+ # Built once per generate instead of scanning every file for every README.
162
+ def index_dirs
163
+ @index_dirs ||= Set.new.tap do |dirs|
164
+ site.pages.each { |page| add_index_dir(page.url, dirs) }
165
+ site.static_files.each { |file| add_index_dir(file.url, dirs) }
166
+ end
167
+ end
168
+
169
+ def add_index_dir(url, dirs = index_dirs)
170
+ match = INDEX_URL_REGEX.match(url)
171
+ dirs << match[1].downcase if match
66
172
  end
67
173
 
68
174
  # Regexp to match a file path against to detect if the given file is a README
69
175
  def readme_regex
70
- @readme_regex ||= %r!/readme(#{Regexp.union(markdown_converter.extname_list)})$!i
176
+ # Allow custom pattern override via configuration
177
+ @readme_regex ||= if (custom_pattern = option(PATTERN_KEY))
178
+ Regexp.new(custom_pattern, Regexp::IGNORECASE)
179
+ else
180
+ # Match README in any directory, including .github, docs subdirectories
181
+ # The pattern ensures .github and docs are only matched at path boundaries
182
+ extensions = Regexp.union(markdown_converter.extname_list)
183
+ %r!/(?:\.github/|docs/)?readme(#{extensions})$!i
184
+ end
71
185
  end
72
186
 
73
187
  def markdown_converter
@@ -89,5 +203,10 @@ module JekyllReadmeIndex
89
203
  def with_frontmatter?
90
204
  option(FRONTMATTER_KEY) == true
91
205
  end
206
+
207
+ # Helper method to get the file path (URL or path) for a file object
208
+ def file_path(file)
209
+ file.respond_to?(:url) ? file.url : "/" + file.path
210
+ end
92
211
  end
93
212
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllReadmeIndex
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "jekyll"
4
4
  require "jekyll-readme-index/generator"
5
- require_relative "./jekyll/static_file_ext"
6
5
 
7
6
  module JekyllReadmeIndex
8
7
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-readme-index
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Balter
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-11-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: jekyll
@@ -30,77 +29,146 @@ dependencies:
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
31
  version: '5.0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: kramdown-parser-gfm
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '1.1'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '1.1'
33
46
  - !ruby/object:Gem::Dependency
34
47
  name: rspec
35
48
  requirement: !ruby/object:Gem::Requirement
36
49
  requirements:
37
50
  - - "~>"
38
51
  - !ruby/object:Gem::Version
39
- version: '3.5'
52
+ version: '3.13'
40
53
  type: :development
41
54
  prerelease: false
42
55
  version_requirements: !ruby/object:Gem::Requirement
43
56
  requirements:
44
57
  - - "~>"
45
58
  - !ruby/object:Gem::Version
46
- version: '3.5'
59
+ version: '3.13'
47
60
  - !ruby/object:Gem::Dependency
48
61
  name: rubocop
49
62
  requirement: !ruby/object:Gem::Requirement
50
63
  requirements:
51
64
  - - "~>"
52
65
  - !ruby/object:Gem::Version
53
- version: '0.40'
66
+ version: '1.57'
54
67
  type: :development
55
68
  prerelease: false
56
69
  version_requirements: !ruby/object:Gem::Requirement
57
70
  requirements:
58
71
  - - "~>"
59
72
  - !ruby/object:Gem::Version
60
- version: '0.40'
73
+ version: '1.57'
61
74
  - !ruby/object:Gem::Dependency
62
75
  name: rubocop-jekyll
63
76
  requirement: !ruby/object:Gem::Requirement
64
77
  requirements:
65
78
  - - "~>"
66
79
  - !ruby/object:Gem::Version
67
- version: 0.10.0
80
+ version: '0.14'
68
81
  type: :development
69
82
  prerelease: false
70
83
  version_requirements: !ruby/object:Gem::Requirement
71
84
  requirements:
72
85
  - - "~>"
73
86
  - !ruby/object:Gem::Version
74
- version: 0.10.0
87
+ version: '0.14'
75
88
  - !ruby/object:Gem::Dependency
76
89
  name: rubocop-performance
77
90
  requirement: !ruby/object:Gem::Requirement
78
91
  requirements:
79
92
  - - "~>"
80
93
  - !ruby/object:Gem::Version
81
- version: '1.5'
94
+ version: '1.23'
82
95
  type: :development
83
96
  prerelease: false
84
97
  version_requirements: !ruby/object:Gem::Requirement
85
98
  requirements:
86
99
  - - "~>"
87
100
  - !ruby/object:Gem::Version
88
- version: '1.5'
101
+ version: '1.23'
89
102
  - !ruby/object:Gem::Dependency
90
103
  name: rubocop-rspec
91
104
  requirement: !ruby/object:Gem::Requirement
92
105
  requirements:
93
106
  - - "~>"
94
107
  - !ruby/object:Gem::Version
95
- version: '1.3'
108
+ version: '3.0'
96
109
  type: :development
97
110
  prerelease: false
98
111
  version_requirements: !ruby/object:Gem::Requirement
99
112
  requirements:
100
113
  - - "~>"
101
114
  - !ruby/object:Gem::Version
102
- version: '1.3'
103
- description:
115
+ version: '3.0'
116
+ - !ruby/object:Gem::Dependency
117
+ name: base64
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ - !ruby/object:Gem::Dependency
131
+ name: benchmark
132
+ requirement: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ type: :development
138
+ prerelease: false
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ - !ruby/object:Gem::Dependency
145
+ name: ostruct
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: tsort
160
+ requirement: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ type: :development
166
+ prerelease: false
167
+ version_requirements: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
104
172
  email:
105
173
  - ben.balter@github.com
106
174
  executables: []
@@ -110,12 +178,10 @@ files:
110
178
  - lib/jekyll-readme-index.rb
111
179
  - lib/jekyll-readme-index/generator.rb
112
180
  - lib/jekyll-readme-index/version.rb
113
- - lib/jekyll/static_file_ext.rb
114
181
  homepage: https://github.com/benbalter/jekyll-readme-index
115
182
  licenses:
116
183
  - MIT
117
184
  metadata: {}
118
- post_install_message:
119
185
  rdoc_options: []
120
186
  require_paths:
121
187
  - lib
@@ -123,15 +189,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
189
  requirements:
124
190
  - - ">="
125
191
  - !ruby/object:Gem::Version
126
- version: '0'
192
+ version: '3.0'
127
193
  required_rubygems_version: !ruby/object:Gem::Requirement
128
194
  requirements:
129
195
  - - ">="
130
196
  - !ruby/object:Gem::Version
131
197
  version: '0'
132
198
  requirements: []
133
- rubygems_version: 3.0.6
134
- signing_key:
199
+ rubygems_version: 3.6.9
135
200
  specification_version: 4
136
201
  summary: A Jekyll plugin to render a project's README as the site's index.
137
202
  test_files: []
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- class StaticFile
5
- # Convert this static file to a Page
6
- def to_page
7
- page = Jekyll::Page.new(@site, @base, @dir, @name)
8
- page.data["permalink"] = File.dirname(url) + "/"
9
- page
10
- end
11
- end
12
-
13
- class Page
14
- def update_permalink
15
- data["permalink"] = File.dirname(url) + "/"
16
- @url = URL.new(
17
- :template => template,
18
- :placeholders => url_placeholders,
19
- :permalink => permalink
20
- ).to_s
21
- end
22
- end
23
- end