jekyll-documents 0.7.3 → 0.7.4
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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +1 -0
- data/lib/jekyll/documents/tag_helpers.rb +53 -0
- data/lib/jekyll/documents/tags/doc_category.rb +3 -43
- data/lib/jekyll/documents/tags/doc_link.rb +3 -43
- data/lib/jekyll/documents/tags/document_icon.rb +1 -9
- data/lib/jekyll/documents/tags/latest_documents.rb +15 -19
- data/lib/jekyll/documents/version.rb +1 -1
- data/lib/jekyll-documents.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c690ba4e56790f19326b49d3476839028784f9da66b4d46d5a18680cac0ba927
|
|
4
|
+
data.tar.gz: 6007f855de36ef230b789fdab081877f19c9be15c583a342e669eaa811898317
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ecc1cbd701f3b07f70694dd0a9f7314d7d65bb2b2040ad0af3658d763ad540bb40daf90e1494100e49ab72a10540377786d793a2416536cc055f85a16983fcb7
|
|
7
|
+
data.tar.gz: dbab2960b310640f780b3d88695ec16cbdf1902fba99019736bedf7ab3ecf0a6f956c370b9b3c8858ad559f4f40fe7a6f354843a7ceef790e97010f751c898cc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [0.7.4] - 2026-09-18
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added Codecov coverage reporting: CI uploads Cobertura XML (via `simplecov-cobertura`) after the Ruby quality suite, with `codecov.yml` status checks (98% project / 90% patch targets)
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Auto-update `Gemfile.lock` on `rake version:bump` via `bundle lock` (use `SKIP_LOCK=1` to skip)
|
|
12
|
+
- Further reduced `latest_documents.rb` `render` complexity by extracting `resolve_count` and `select_documents`
|
|
13
|
+
- Extracted shared `TagHelpers` module (markup parsing, document collection access, path normalization, HTML escaping) used by `doc_link`, `doc_category`, `document_icon`, and `latest_documents` tags — removes SonarCloud-flagged duplication
|
|
14
|
+
- Extracted shared `liquid tag helpers` spec context (`spec/support/shared_context_tags.rb`) for tag spec setup
|
|
15
|
+
- Added `.sonarcloud.properties` excluding `spec/fixtures/` from SonarCloud duplication analysis (fixture templates intentionally mirror shipped includes/layouts)
|
|
16
|
+
|
|
3
17
|
## [0.7.3] - 2026-09-10
|
|
4
18
|
|
|
5
19
|
### Added
|
data/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://deepwiki.com/gundestrup/jekyll-documents)
|
|
9
9
|
[](https://www.codefactor.io/repository/github/gundestrup/jekyll-documents)
|
|
10
10
|
[](https://github.com/gundestrup/jekyll-documents/security/code-scanning)
|
|
11
|
+
[](https://sonarcloud.io/summary/new_code?id=gundestrup_jekyll-documents)
|
|
11
12
|
|
|
12
13
|
Turn files in `assets/documents/` into browsable document pages.
|
|
13
14
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module Documents
|
|
5
|
+
# Shared markup parsing, document collection access, path
|
|
6
|
+
# normalization, and HTML escaping for the Liquid tags.
|
|
7
|
+
module TagHelpers
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def parse_markup(markup)
|
|
11
|
+
text = markup.to_s
|
|
12
|
+
target, remainder = extract_target(text)
|
|
13
|
+
options = extract_options(remainder)
|
|
14
|
+
[target, options]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def extract_target(text)
|
|
18
|
+
return [nil, text] if text.strip.match?(/\Apath\s*:/)
|
|
19
|
+
|
|
20
|
+
quoted = text.match(/\A["']([^"']+)["']/)
|
|
21
|
+
return [quoted[1], text[quoted.end(0)..]] if quoted
|
|
22
|
+
|
|
23
|
+
bare = text.strip.match(/\A([^\s]+)/)
|
|
24
|
+
return [nil, ""] unless bare
|
|
25
|
+
|
|
26
|
+
[bare[1], text[bare.end(0)..]]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def extract_options(text)
|
|
30
|
+
OptionsParser.parse_options(text)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def documents_from(context)
|
|
34
|
+
site = context.registers[:site]
|
|
35
|
+
site.collections["documents"]&.docs || []
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def normalize_tag_path(path)
|
|
39
|
+
path.to_s.strip.tr("\\", "/").squeeze("/").delete_prefix("./").delete_prefix("/")
|
|
40
|
+
.delete_suffix("/")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def escape_html(value)
|
|
44
|
+
value.to_s.gsub(/[&<>"']/,
|
|
45
|
+
"&" => "&",
|
|
46
|
+
"<" => "<",
|
|
47
|
+
">" => ">",
|
|
48
|
+
'"' => """,
|
|
49
|
+
"'" => "'")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -4,6 +4,7 @@ module Jekyll
|
|
|
4
4
|
module Documents
|
|
5
5
|
module CategoryResolver
|
|
6
6
|
include ResolutionReporter
|
|
7
|
+
include TagHelpers
|
|
7
8
|
|
|
8
9
|
private
|
|
9
10
|
|
|
@@ -34,7 +35,7 @@ module Jekyll
|
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
def resolve_category_path(path, categories, site)
|
|
37
|
-
normalized =
|
|
38
|
+
normalized = normalize_tag_path(path)
|
|
38
39
|
matches = categories.select { |category| category["path"] == normalized }
|
|
39
40
|
return matches if matches.one?
|
|
40
41
|
|
|
@@ -54,17 +55,13 @@ module Jekyll
|
|
|
54
55
|
leaf = category["path"].split("/").last.to_s.downcase
|
|
55
56
|
[category["category"], category["slug"], leaf].map { |value| value.to_s.downcase }.uniq
|
|
56
57
|
end
|
|
57
|
-
|
|
58
|
-
def normalize_category_path(path)
|
|
59
|
-
path.to_s.strip.tr("\\", "/").squeeze("/").delete_prefix("./").delete_prefix("/")
|
|
60
|
-
.delete_suffix("/")
|
|
61
|
-
end
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
class DocCategoryTag < Liquid::Tag
|
|
65
61
|
public_class_method :new
|
|
66
62
|
|
|
67
63
|
include CategoryResolver
|
|
64
|
+
include TagHelpers
|
|
68
65
|
include Jekyll::Filters::URLFilters
|
|
69
66
|
|
|
70
67
|
def initialize(tag_name, markup, tokens)
|
|
@@ -88,11 +85,6 @@ module Jekyll
|
|
|
88
85
|
|
|
89
86
|
private
|
|
90
87
|
|
|
91
|
-
def documents_from(context)
|
|
92
|
-
site = context.registers[:site]
|
|
93
|
-
site.collections["documents"]&.docs || []
|
|
94
|
-
end
|
|
95
|
-
|
|
96
88
|
def available_categories(docs)
|
|
97
89
|
categories = docs.group_by { |doc| doc.data["category_path"] || doc.data["category"] }
|
|
98
90
|
.map do |path, matches|
|
|
@@ -137,38 +129,6 @@ module Jekyll
|
|
|
137
129
|
out << %(<li><a href="#{url}">#{title}</a> <small>(#{date})</small></li>\n)
|
|
138
130
|
end
|
|
139
131
|
end
|
|
140
|
-
|
|
141
|
-
def parse_markup(markup)
|
|
142
|
-
text = markup.to_s
|
|
143
|
-
category, remainder = extract_category(text)
|
|
144
|
-
options = extract_options(remainder)
|
|
145
|
-
[category, options]
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def extract_category(text)
|
|
149
|
-
return [nil, text] if text.strip.match?(/\Apath\s*:/)
|
|
150
|
-
|
|
151
|
-
quoted = text.match(/\A["']([^"']+)["']/)
|
|
152
|
-
return [quoted[1], text[quoted.end(0)..]] if quoted
|
|
153
|
-
|
|
154
|
-
bare = text.strip.match(/\A([^\s]+)/)
|
|
155
|
-
return [nil, ""] unless bare
|
|
156
|
-
|
|
157
|
-
[bare[1], text[bare.end(0)..]]
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def extract_options(text)
|
|
161
|
-
OptionsParser.parse_options(text)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def escape_html(value)
|
|
165
|
-
value.to_s.gsub(/[&<>"']/,
|
|
166
|
-
"&" => "&",
|
|
167
|
-
"<" => "<",
|
|
168
|
-
">" => ">",
|
|
169
|
-
'"' => """,
|
|
170
|
-
"'" => "'")
|
|
171
|
-
end
|
|
172
132
|
end
|
|
173
133
|
end
|
|
174
134
|
end
|
|
@@ -4,6 +4,7 @@ module Jekyll
|
|
|
4
4
|
module Documents
|
|
5
5
|
module DocumentResolver
|
|
6
6
|
include ResolutionReporter
|
|
7
|
+
include TagHelpers
|
|
7
8
|
|
|
8
9
|
private
|
|
9
10
|
|
|
@@ -37,7 +38,7 @@ module Jekyll
|
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def find_document_by_path(docs, path, site)
|
|
40
|
-
normalized =
|
|
41
|
+
normalized = normalize_tag_path(path)
|
|
41
42
|
matches = docs.select { |doc| doc.data["source_path"].to_s == normalized }
|
|
42
43
|
return matches.first if matches.one?
|
|
43
44
|
|
|
@@ -48,11 +49,6 @@ module Jekyll
|
|
|
48
49
|
nil
|
|
49
50
|
end
|
|
50
51
|
|
|
51
|
-
def normalize_identifier_path(path)
|
|
52
|
-
path.to_s.strip.tr("\\", "/").squeeze("/").delete_prefix("./").delete_prefix("/")
|
|
53
|
-
.delete_suffix("/")
|
|
54
|
-
end
|
|
55
|
-
|
|
56
52
|
def document_values(doc)
|
|
57
53
|
[doc.data["title"], doc.data["slug"]].map { |value| value.to_s.downcase }
|
|
58
54
|
end
|
|
@@ -62,6 +58,7 @@ module Jekyll
|
|
|
62
58
|
public_class_method :new
|
|
63
59
|
|
|
64
60
|
include DocumentResolver
|
|
61
|
+
include TagHelpers
|
|
65
62
|
include Jekyll::Filters::URLFilters
|
|
66
63
|
|
|
67
64
|
SIZE_UNITS = %w[B KB MB GB].freeze
|
|
@@ -87,11 +84,6 @@ module Jekyll
|
|
|
87
84
|
|
|
88
85
|
private
|
|
89
86
|
|
|
90
|
-
def documents_from(context)
|
|
91
|
-
site = context.registers[:site]
|
|
92
|
-
site.collections["documents"]&.docs || []
|
|
93
|
-
end
|
|
94
|
-
|
|
95
87
|
def build_link(doc, url, text)
|
|
96
88
|
inner = +""
|
|
97
89
|
inner << icon_html(doc) if @options["icon"] != "false"
|
|
@@ -133,38 +125,6 @@ module Jekyll
|
|
|
133
125
|
value /= 1024
|
|
134
126
|
end
|
|
135
127
|
end
|
|
136
|
-
|
|
137
|
-
def parse_markup(markup)
|
|
138
|
-
text = markup.to_s
|
|
139
|
-
query, remainder = extract_query(text)
|
|
140
|
-
options = extract_options(remainder)
|
|
141
|
-
[query, options]
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def extract_query(text)
|
|
145
|
-
return [nil, text] if text.strip.match?(/\Apath\s*:/)
|
|
146
|
-
|
|
147
|
-
quoted = text.match(/\A["']([^"']+)["']/)
|
|
148
|
-
return [quoted[1], text[quoted.end(0)..]] if quoted
|
|
149
|
-
|
|
150
|
-
bare = text.strip.match(/\A([^\s]+)/)
|
|
151
|
-
return [nil, ""] unless bare
|
|
152
|
-
|
|
153
|
-
[bare[1], text[bare.end(0)..]]
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def extract_options(text)
|
|
157
|
-
OptionsParser.parse_options(text)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def escape_html(value)
|
|
161
|
-
value.to_s.gsub(/[&<>"']/,
|
|
162
|
-
"&" => "&",
|
|
163
|
-
"<" => "<",
|
|
164
|
-
">" => ">",
|
|
165
|
-
'"' => """,
|
|
166
|
-
"'" => "'")
|
|
167
|
-
end
|
|
168
128
|
end
|
|
169
129
|
end
|
|
170
130
|
end
|
|
@@ -5,6 +5,7 @@ module Jekyll
|
|
|
5
5
|
class DocumentIconTag < Liquid::Tag
|
|
6
6
|
public_class_method :new
|
|
7
7
|
|
|
8
|
+
include TagHelpers
|
|
8
9
|
include Jekyll::Filters::URLFilters
|
|
9
10
|
|
|
10
11
|
def initialize(tag_name, markup, tokens)
|
|
@@ -47,15 +48,6 @@ module Jekyll
|
|
|
47
48
|
expression = markup.to_s.strip[/\A[^\s]+/]
|
|
48
49
|
[expression, OptionsParser.parse_options(markup)]
|
|
49
50
|
end
|
|
50
|
-
|
|
51
|
-
def escape_html(value)
|
|
52
|
-
value.to_s.gsub(/[&<>"']/,
|
|
53
|
-
"&" => "&",
|
|
54
|
-
"<" => "<",
|
|
55
|
-
">" => ">",
|
|
56
|
-
'"' => """,
|
|
57
|
-
"'" => "'")
|
|
58
|
-
end
|
|
59
51
|
end
|
|
60
52
|
end
|
|
61
53
|
end
|
|
@@ -10,21 +10,29 @@ module Jekyll
|
|
|
10
10
|
|
|
11
11
|
public_class_method :new
|
|
12
12
|
|
|
13
|
+
include TagHelpers
|
|
14
|
+
|
|
13
15
|
def render(context)
|
|
14
16
|
site = context.registers[:site]
|
|
15
17
|
cfg = Configuration.read(site)
|
|
16
|
-
count = (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
docs = site.collections["documents"]&.docs || []
|
|
20
|
-
docs = docs.select { |doc| doc.data["category"] == category } if category
|
|
21
|
-
docs = docs.sort_by { |doc| doc.data["date"] || Time.at(0) }.reverse.first(count)
|
|
18
|
+
count = resolve_count(cfg)
|
|
19
|
+
docs = select_documents(site, @args["category"], count)
|
|
22
20
|
|
|
23
21
|
render_list(docs)
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
private
|
|
27
25
|
|
|
26
|
+
def resolve_count(cfg)
|
|
27
|
+
(@args["count"] || cfg["latest_default_count"] || 5).to_i
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def select_documents(site, category, count)
|
|
31
|
+
docs = site.collections["documents"]&.docs || []
|
|
32
|
+
docs = docs.select { |doc| doc.data["category"] == category } if category
|
|
33
|
+
docs.sort_by { |doc| doc.data["date"] || Time.at(0) }.reverse.first(count)
|
|
34
|
+
end
|
|
35
|
+
|
|
28
36
|
def render_list(docs)
|
|
29
37
|
out = +"<ul class=\"latest-documents\">\n"
|
|
30
38
|
docs.each { |doc| out << list_item(doc) }
|
|
@@ -40,21 +48,9 @@ module Jekyll
|
|
|
40
48
|
%(<li><a href="#{url}">#{title}</a> <small>(#{date})</small></li>\n)
|
|
41
49
|
end
|
|
42
50
|
|
|
43
|
-
def escape_html(text)
|
|
44
|
-
return "" unless text
|
|
45
|
-
|
|
46
|
-
text.to_s.gsub(/[&<>"']/, {
|
|
47
|
-
"&" => "&",
|
|
48
|
-
"<" => "<",
|
|
49
|
-
">" => ">",
|
|
50
|
-
'"' => """,
|
|
51
|
-
"'" => "'"
|
|
52
|
-
})
|
|
53
|
-
end
|
|
54
|
-
|
|
55
51
|
# supports: count:5 category:'referat'
|
|
56
52
|
def parse_args(markup)
|
|
57
|
-
|
|
53
|
+
extract_options(markup)
|
|
58
54
|
end
|
|
59
55
|
end
|
|
60
56
|
end
|
data/lib/jekyll-documents.rb
CHANGED
|
@@ -12,6 +12,7 @@ require_relative "jekyll/documents/assets_generator"
|
|
|
12
12
|
require_relative "jekyll/documents/json_index_generator"
|
|
13
13
|
require_relative "jekyll/documents/layout_registrar"
|
|
14
14
|
require_relative "jekyll/documents/options_parser"
|
|
15
|
+
require_relative "jekyll/documents/tag_helpers"
|
|
15
16
|
|
|
16
17
|
# Liquid tag(s)
|
|
17
18
|
require_relative "jekyll/documents/tags/latest_documents"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-documents
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Svend Gundestrup
|
|
@@ -155,6 +155,7 @@ files:
|
|
|
155
155
|
- lib/jekyll/documents/json_index_generator.rb
|
|
156
156
|
- lib/jekyll/documents/layout_registrar.rb
|
|
157
157
|
- lib/jekyll/documents/options_parser.rb
|
|
158
|
+
- lib/jekyll/documents/tag_helpers.rb
|
|
158
159
|
- lib/jekyll/documents/tags/doc_category.rb
|
|
159
160
|
- lib/jekyll/documents/tags/doc_link.rb
|
|
160
161
|
- lib/jekyll/documents/tags/document_icon.rb
|