trifle-docs 0.7.1 → 0.7.2
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/Gemfile.lock +1 -1
- data/README.md +18 -0
- data/lib/trifle/docs/app.rb +100 -62
- data/lib/trifle/docs/configuration.rb +2 -1
- data/lib/trifle/docs/engine.rb +23 -7
- data/lib/trifle/docs/helper/llms.rb +38 -14
- data/lib/trifle/docs/helper/markdown_layout.rb +1 -4
- data/lib/trifle/docs/helper/sitemap.rb +47 -7
- data/lib/trifle/docs/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4660d54f61927575620d127f9493bc2921bf4a0395362acd2f71b4eeaee38712
|
|
4
|
+
data.tar.gz: c59600b536c976dbf67eaf4f99a61d214b1022b6a18795cc7ea37d9f5caf4ba7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fc4c3fa9f2d46e94c6a7a19169830b33c2601fbc2a39360945d57691332b3d3a6d00be8fdc12aa13a379595aefd655f887c02dcbd3ceda561c6431fdda1b0d2d
|
|
7
|
+
data.tar.gz: cd867ffc069b37ee0e513893abe097c8ed4c6a5ecdd8e7fb1d47c0fd0c33f950892024ca04ac653f3281383aab64cb3d7c88671ee5b5b8579b543b49112b3745
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -41,6 +41,8 @@ require 'trifle/docs'
|
|
|
41
41
|
Trifle::Docs.configure do |config|
|
|
42
42
|
config.path = File.join(__dir__, 'docs')
|
|
43
43
|
config.views = File.join(__dir__, 'templates')
|
|
44
|
+
# Optional: canonical base URL used for absolute <loc> values in sitemap.xml
|
|
45
|
+
# config.sitemap_base_url = ENV.fetch('TRIFLE_DOCS_SITEMAP_BASE_URL', nil)
|
|
44
46
|
config.register_harvester(Trifle::Docs::Harvester::Markdown)
|
|
45
47
|
config.register_harvester(Trifle::Docs::Harvester::File)
|
|
46
48
|
end
|
|
@@ -110,6 +112,22 @@ There are several variables available in your template file (except `layout.erb`
|
|
|
110
112
|
- **Caching support** - Optional caching for production environments
|
|
111
113
|
- **Navigation helpers** - Automatic menu and breadcrumb generation
|
|
112
114
|
|
|
115
|
+
## Sitemap URL configuration
|
|
116
|
+
|
|
117
|
+
`/sitemap.xml` emits absolute URLs. By default, Trifle::Docs uses the incoming request host (`request.base_url`).
|
|
118
|
+
|
|
119
|
+
If your app runs behind a proxy/ingress and you need a canonical public domain, set:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
config.sitemap_base_url = 'https://docs.trifle.io'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
In containerized deployments you can wire this through an env var, for example:
|
|
126
|
+
|
|
127
|
+
```ruby
|
|
128
|
+
config.sitemap_base_url = ENV.fetch('TRIFLE_DOCS_SITEMAP_BASE_URL', nil)
|
|
129
|
+
```
|
|
130
|
+
|
|
113
131
|
## Harvesters
|
|
114
132
|
|
|
115
133
|
Trifle::Docs supports multiple content processors:
|
data/lib/trifle/docs/app.rb
CHANGED
|
@@ -4,65 +4,11 @@ require 'sinatra/base'
|
|
|
4
4
|
|
|
5
5
|
module Trifle
|
|
6
6
|
module Docs
|
|
7
|
-
|
|
8
|
-
configure do
|
|
9
|
-
set :bind, '0.0.0.0'
|
|
10
|
-
set :views, proc { Trifle::Docs.default.views }
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
get '/search' do
|
|
14
|
-
results = Trifle::Docs.search(query: params['query'], scope: params['scope'])
|
|
15
|
-
erb(
|
|
16
|
-
'search'.to_sym,
|
|
17
|
-
{},
|
|
18
|
-
{
|
|
19
|
-
results: results,
|
|
20
|
-
query: params['query'],
|
|
21
|
-
scope: params['scope'],
|
|
22
|
-
sitemap: Trifle::Docs.sitemap,
|
|
23
|
-
meta: { description: 'Search' }
|
|
24
|
-
}
|
|
25
|
-
)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
get '/llms.txt' do
|
|
29
|
-
meta = Trifle::Docs.meta(url: 'llms.txt')
|
|
30
|
-
return send_file(meta['path']) if meta && meta['type'] == 'file'
|
|
31
|
-
|
|
32
|
-
content = Trifle::Docs::Helper::Llms.homepage_markdown
|
|
33
|
-
halt(404, 'Not Found') if content.nil?
|
|
34
|
-
|
|
35
|
-
content_type 'text/plain'
|
|
36
|
-
content
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
get '/llms-full.txt' do
|
|
40
|
-
meta = Trifle::Docs.meta(url: 'llms-full.txt')
|
|
41
|
-
return send_file(meta['path']) if meta && meta['type'] == 'file'
|
|
42
|
-
|
|
43
|
-
content = Trifle::Docs::Helper::Llms.full_markdown
|
|
44
|
-
halt(404, 'Not Found') if content.nil? || content.strip.empty?
|
|
45
|
-
|
|
46
|
-
content_type 'text/plain'
|
|
47
|
-
content
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
get '/sitemap.xml' do
|
|
51
|
-
meta = Trifle::Docs.meta(url: 'sitemap.xml')
|
|
52
|
-
return send_file(meta['path']) if meta && meta['type'] == 'file'
|
|
53
|
-
|
|
54
|
-
render_generated_sitemap
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
get '/*' do
|
|
58
|
-
handle_request(params, request)
|
|
59
|
-
end
|
|
60
|
-
|
|
7
|
+
module AppHelpers
|
|
61
8
|
def markdown_requested?(request, params)
|
|
62
9
|
return true if params['format'].to_s.downcase == 'md'
|
|
63
10
|
|
|
64
|
-
|
|
65
|
-
accept.include?('text/markdown')
|
|
11
|
+
request.env['HTTP_ACCEPT'].to_s.include?('text/markdown')
|
|
66
12
|
end
|
|
67
13
|
|
|
68
14
|
def render_markdown?(meta, request, params)
|
|
@@ -77,9 +23,9 @@ module Trifle
|
|
|
77
23
|
meta = Trifle::Docs.meta(url: url)
|
|
78
24
|
halt(404, 'Not Found') if meta.nil?
|
|
79
25
|
|
|
80
|
-
set_vary_header unless meta
|
|
26
|
+
set_vary_header unless file_meta?(meta)
|
|
81
27
|
return render_markdown(meta, url) if render_markdown?(meta, request, params)
|
|
82
|
-
return send_file(meta['path']) if meta
|
|
28
|
+
return send_file(meta['path']) if file_meta?(meta)
|
|
83
29
|
|
|
84
30
|
render_html(meta, url)
|
|
85
31
|
end
|
|
@@ -88,8 +34,7 @@ module Trifle
|
|
|
88
34
|
content_type markdown_content_type(request)
|
|
89
35
|
Trifle::Docs::Helper::MarkdownLayout.render(
|
|
90
36
|
meta: meta,
|
|
91
|
-
raw_content: Trifle::Docs.raw_content(url: url)
|
|
92
|
-
sitemap: Trifle::Docs.sitemap
|
|
37
|
+
raw_content: Trifle::Docs.raw_content(url: url)
|
|
93
38
|
)
|
|
94
39
|
end
|
|
95
40
|
|
|
@@ -104,7 +49,8 @@ module Trifle
|
|
|
104
49
|
end
|
|
105
50
|
|
|
106
51
|
def render_generated_sitemap
|
|
107
|
-
|
|
52
|
+
base_url = Trifle::Docs.default.sitemap_base_url || request.base_url
|
|
53
|
+
content = Trifle::Docs::Helper::Sitemap.xml(base_url: base_url)
|
|
108
54
|
halt(404, 'Not Found') if content.nil? || content.strip.empty?
|
|
109
55
|
|
|
110
56
|
content_type 'application/xml'
|
|
@@ -122,6 +68,21 @@ module Trifle
|
|
|
122
68
|
headers['Vary'] = append_vary(headers['Vary'], 'Accept')
|
|
123
69
|
end
|
|
124
70
|
|
|
71
|
+
def render_llms_for(base_url, full:)
|
|
72
|
+
base_url = normalize_base_url(base_url)
|
|
73
|
+
url = llms_url(base_url, full: full)
|
|
74
|
+
meta = Trifle::Docs.meta(url: url)
|
|
75
|
+
return send_file(meta['path']) if file_meta?(meta)
|
|
76
|
+
|
|
77
|
+
content = llms_content(full: full, base_url: base_url)
|
|
78
|
+
halt(404, 'Not Found') if llms_missing?(content, full: full)
|
|
79
|
+
|
|
80
|
+
content_type 'text/plain'
|
|
81
|
+
content
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
125
86
|
def append_vary(existing, value)
|
|
126
87
|
values = existing.to_s.split(',').map(&:strip).reject(&:empty?)
|
|
127
88
|
return value if values.empty?
|
|
@@ -130,7 +91,84 @@ module Trifle
|
|
|
130
91
|
(values + [value]).join(', ')
|
|
131
92
|
end
|
|
132
93
|
|
|
133
|
-
|
|
94
|
+
def normalize_base_url(base_url)
|
|
95
|
+
base_url.to_s.gsub(%r{^/+}, '').gsub(%r{/+$}, '')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def llms_url(base_url, full:)
|
|
99
|
+
llms_name = full ? 'llms-full.txt' : 'llms.txt'
|
|
100
|
+
[base_url, llms_name].reject(&:empty?).join('/')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def llms_content(full:, base_url:)
|
|
104
|
+
if full
|
|
105
|
+
Trifle::Docs::Helper::Llms.full_markdown(base_url: base_url)
|
|
106
|
+
else
|
|
107
|
+
Trifle::Docs::Helper::Llms.homepage_markdown(base_url: base_url)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def llms_missing?(content, full:)
|
|
112
|
+
return true if content.nil?
|
|
113
|
+
return false unless full
|
|
114
|
+
|
|
115
|
+
content.strip.empty?
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def file_meta?(meta)
|
|
119
|
+
meta && meta['type'] == 'file'
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class App < Sinatra::Base
|
|
124
|
+
configure do
|
|
125
|
+
set :bind, '0.0.0.0'
|
|
126
|
+
set :views, proc { Trifle::Docs.default.views }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
helpers AppHelpers
|
|
130
|
+
|
|
131
|
+
get '/search' do
|
|
132
|
+
results = Trifle::Docs.search(query: params['query'], scope: params['scope'])
|
|
133
|
+
erb(
|
|
134
|
+
'search'.to_sym,
|
|
135
|
+
{},
|
|
136
|
+
{
|
|
137
|
+
results: results,
|
|
138
|
+
query: params['query'],
|
|
139
|
+
scope: params['scope'],
|
|
140
|
+
sitemap: Trifle::Docs.sitemap,
|
|
141
|
+
meta: { description: 'Search' }
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
get '/llms.txt' do
|
|
147
|
+
render_llms_for('', full: false)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
get %r{/(.+)/llms\.txt} do |path|
|
|
151
|
+
render_llms_for(path, full: false)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
get '/llms-full.txt' do
|
|
155
|
+
render_llms_for('', full: true)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
get %r{/(.+)/llms-full\.txt} do |path|
|
|
159
|
+
render_llms_for(path, full: true)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
get '/sitemap.xml' do
|
|
163
|
+
meta = Trifle::Docs.meta(url: 'sitemap.xml')
|
|
164
|
+
return send_file(meta['path']) if meta && meta['type'] == 'file'
|
|
165
|
+
|
|
166
|
+
render_generated_sitemap
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
get '/*' do
|
|
170
|
+
handle_request(params, request)
|
|
171
|
+
end
|
|
134
172
|
end
|
|
135
173
|
end
|
|
136
174
|
end
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
module Trifle
|
|
4
4
|
module Docs
|
|
5
5
|
class Configuration
|
|
6
|
-
attr_accessor :path, :views, :layout, :namespace, :cache
|
|
6
|
+
attr_accessor :path, :views, :layout, :namespace, :cache, :sitemap_base_url
|
|
7
7
|
|
|
8
8
|
def initialize
|
|
9
9
|
@harvesters = []
|
|
10
10
|
@path = nil
|
|
11
11
|
@namespace = nil
|
|
12
12
|
@cache = true
|
|
13
|
+
@sitemap_base_url = nil
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def harvester
|
data/lib/trifle/docs/engine.rb
CHANGED
|
@@ -19,6 +19,8 @@ if Object.const_defined?('Rails')
|
|
|
19
19
|
root to: 'page#show'
|
|
20
20
|
get 'llms.txt', to: 'page#llms'
|
|
21
21
|
get 'llms-full.txt', to: 'page#llms_full'
|
|
22
|
+
get '*path/llms.txt', to: 'page#llms'
|
|
23
|
+
get '*path/llms-full.txt', to: 'page#llms_full'
|
|
22
24
|
get 'sitemap.xml', to: 'page#sitemap'
|
|
23
25
|
get 'search', to: 'page#search'
|
|
24
26
|
get '*url', to: 'page#show'
|
|
@@ -71,8 +73,7 @@ if Object.const_defined?('Rails')
|
|
|
71
73
|
def render_markdown(url:, meta:)
|
|
72
74
|
render plain: Trifle::Docs::Helper::MarkdownLayout.render(
|
|
73
75
|
meta: meta,
|
|
74
|
-
raw_content: Trifle::Docs.raw_content(url: url, config: configuration)
|
|
75
|
-
sitemap: Trifle::Docs.sitemap(config: configuration)
|
|
76
|
+
raw_content: Trifle::Docs.raw_content(url: url, config: configuration)
|
|
76
77
|
), content_type: markdown_content_type
|
|
77
78
|
end
|
|
78
79
|
|
|
@@ -100,6 +101,10 @@ if Object.const_defined?('Rails')
|
|
|
100
101
|
[url, wants_md]
|
|
101
102
|
end
|
|
102
103
|
|
|
104
|
+
def llms_scope
|
|
105
|
+
params[:path].to_s.gsub(%r{^/+}, '').gsub(%r{/+$}, '')
|
|
106
|
+
end
|
|
107
|
+
|
|
103
108
|
def render_markdown?(meta, wants_md, request)
|
|
104
109
|
return false if meta['type'] == 'file'
|
|
105
110
|
|
|
@@ -166,20 +171,31 @@ if Object.const_defined?('Rails')
|
|
|
166
171
|
end
|
|
167
172
|
|
|
168
173
|
def llms
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
base_url = llms_scope
|
|
175
|
+
llms_url = [base_url, 'llms.txt'].reject(&:empty?).join('/')
|
|
176
|
+
render_llms(llms_url, allow_empty: true) do
|
|
177
|
+
Trifle::Docs::Helper::Llms.homepage_markdown(
|
|
178
|
+
config: configuration,
|
|
179
|
+
base_url: base_url
|
|
180
|
+
)
|
|
171
181
|
end
|
|
172
182
|
end
|
|
173
183
|
|
|
174
184
|
def llms_full
|
|
175
|
-
|
|
176
|
-
|
|
185
|
+
base_url = llms_scope
|
|
186
|
+
llms_url = [base_url, 'llms-full.txt'].reject(&:empty?).join('/')
|
|
187
|
+
render_llms(llms_url) do
|
|
188
|
+
Trifle::Docs::Helper::Llms.full_markdown(
|
|
189
|
+
config: configuration,
|
|
190
|
+
base_url: base_url
|
|
191
|
+
)
|
|
177
192
|
end
|
|
178
193
|
end
|
|
179
194
|
|
|
180
195
|
def sitemap
|
|
196
|
+
base_url = configuration.sitemap_base_url || request.base_url
|
|
181
197
|
render_sitemap('sitemap.xml') do
|
|
182
|
-
Trifle::Docs::Helper::Sitemap.xml(config: configuration)
|
|
198
|
+
Trifle::Docs::Helper::Sitemap.xml(config: configuration, base_url: base_url)
|
|
183
199
|
end
|
|
184
200
|
end
|
|
185
201
|
end
|
|
@@ -6,32 +6,56 @@ module Trifle
|
|
|
6
6
|
module Llms
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
|
-
def homepage_markdown(config: nil)
|
|
10
|
-
|
|
9
|
+
def homepage_markdown(config: nil, base_url: '')
|
|
10
|
+
base_url = normalize_base_url(base_url)
|
|
11
|
+
meta = Trifle::Docs.meta(url: base_url, config: config)
|
|
11
12
|
return nil if meta.nil?
|
|
12
13
|
|
|
13
14
|
Trifle::Docs::Helper::MarkdownLayout.render(
|
|
14
15
|
meta: meta,
|
|
15
|
-
raw_content: Trifle::Docs.raw_content(url:
|
|
16
|
-
sitemap: Trifle::Docs.sitemap(config: config)
|
|
16
|
+
raw_content: Trifle::Docs.raw_content(url: base_url, config: config)
|
|
17
17
|
)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def full_markdown(config: nil)
|
|
20
|
+
def full_markdown(config: nil, base_url: '')
|
|
21
|
+
pages = llms_pages(config: config, base_url: base_url)
|
|
22
|
+
return nil if pages.nil?
|
|
23
|
+
|
|
24
|
+
pages.filter_map { |page| render_llms_page(page, config: config) }
|
|
25
|
+
.join("\n\n")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def llms_pages(config:, base_url:)
|
|
29
|
+
base_url = normalize_base_url(base_url)
|
|
21
30
|
sitemap = Trifle::Docs.sitemap(config: config)
|
|
22
|
-
|
|
31
|
+
scoped_sitemap = sitemap_subtree(sitemap, base_url)
|
|
32
|
+
return nil if scoped_sitemap.nil?
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
path = base_url.empty? ? [] : base_url.split('/')
|
|
35
|
+
flatten_sitemap(scoped_sitemap, path)
|
|
36
|
+
end
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
def render_llms_page(page, config:)
|
|
39
|
+
meta = page[:meta]
|
|
40
|
+
return nil if meta.nil? || meta['type'] == 'file'
|
|
30
41
|
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
raw = Trifle::Docs.raw_content(url: page[:url], config: config)
|
|
43
|
+
return nil if raw.nil? || raw.strip.empty?
|
|
44
|
+
|
|
45
|
+
format_page(meta: meta, url: page[:url], raw_content: raw)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def sitemap_subtree(sitemap, base_url)
|
|
49
|
+
return nil unless sitemap.is_a?(Hash)
|
|
50
|
+
|
|
51
|
+
base_url = normalize_base_url(base_url)
|
|
52
|
+
return sitemap if base_url.empty?
|
|
53
|
+
|
|
54
|
+
sitemap.dig(*base_url.split('/'))
|
|
55
|
+
end
|
|
33
56
|
|
|
34
|
-
|
|
57
|
+
def normalize_base_url(base_url)
|
|
58
|
+
base_url.to_s.gsub(%r{^/+}, '').gsub(%r{/+$}, '')
|
|
35
59
|
end
|
|
36
60
|
|
|
37
61
|
def flatten_sitemap(node, path = [])
|
|
@@ -6,15 +6,12 @@ module Trifle
|
|
|
6
6
|
module MarkdownLayout
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
|
-
def render(meta:, raw_content
|
|
9
|
+
def render(meta:, raw_content:)
|
|
10
10
|
lines = []
|
|
11
11
|
title = meta['title'] || derive_title_from_url(meta['url'])
|
|
12
12
|
|
|
13
13
|
lines << "# #{title}"
|
|
14
14
|
lines << ''
|
|
15
|
-
lines << '## Navigation'
|
|
16
|
-
lines << navigation_toc(sitemap)
|
|
17
|
-
lines << ''
|
|
18
15
|
lines << '## Content'
|
|
19
16
|
lines << raw_content.to_s.strip
|
|
20
17
|
lines << ''
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'cgi'
|
|
4
4
|
require 'time'
|
|
5
|
+
require 'uri'
|
|
5
6
|
|
|
6
7
|
module Trifle
|
|
7
8
|
module Docs
|
|
@@ -9,9 +10,10 @@ module Trifle
|
|
|
9
10
|
module Sitemap
|
|
10
11
|
module_function
|
|
11
12
|
|
|
12
|
-
def xml(config: nil)
|
|
13
|
+
def xml(config: nil, base_url: nil)
|
|
13
14
|
sitemap = Trifle::Docs.sitemap(config: config)
|
|
14
|
-
|
|
15
|
+
resolved_base_url = resolve_base_url(config: config, base_url: base_url)
|
|
16
|
+
urls = sitemap_urls(sitemap, base_url: resolved_base_url)
|
|
15
17
|
return nil if urls.empty?
|
|
16
18
|
|
|
17
19
|
build_document(urls)
|
|
@@ -31,13 +33,13 @@ module Trifle
|
|
|
31
33
|
entries
|
|
32
34
|
end
|
|
33
35
|
|
|
34
|
-
def sitemap_urls(sitemap)
|
|
36
|
+
def sitemap_urls(sitemap, base_url: nil)
|
|
35
37
|
entries = flatten_sitemap(sitemap)
|
|
36
38
|
entries.filter_map do |entry|
|
|
37
39
|
meta = entry[:meta]
|
|
38
40
|
next if meta.nil? || meta['type'] == 'file'
|
|
39
41
|
|
|
40
|
-
build_url_entry(entry[:url], meta)
|
|
42
|
+
build_url_entry(entry[:url], meta, base_url: base_url)
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
|
|
@@ -50,21 +52,59 @@ module Trifle
|
|
|
50
52
|
].join("\n")
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
def build_url_entry(url, meta)
|
|
54
|
-
loc = normalize_loc(url, meta)
|
|
55
|
+
def build_url_entry(url, meta, base_url: nil)
|
|
56
|
+
loc = normalize_loc(url, meta, base_url: base_url)
|
|
55
57
|
lastmod = format_lastmod(meta['updated_at'])
|
|
56
58
|
lastmod_tag = lastmod ? "<lastmod>#{lastmod}</lastmod>" : ''
|
|
57
59
|
|
|
58
60
|
"<url><loc>#{loc}</loc>#{lastmod_tag}</url>"
|
|
59
61
|
end
|
|
60
62
|
|
|
61
|
-
def normalize_loc(url, meta)
|
|
63
|
+
def normalize_loc(url, meta, base_url: nil)
|
|
62
64
|
loc = meta['url']
|
|
63
65
|
loc = "/#{url}" if loc.nil? || loc.empty?
|
|
64
66
|
loc = '/' if loc == '//'
|
|
67
|
+
loc = absolutize_loc(loc, base_url)
|
|
65
68
|
CGI.escapeHTML(loc)
|
|
66
69
|
end
|
|
67
70
|
|
|
71
|
+
def absolutize_loc(loc, base_url)
|
|
72
|
+
return loc if base_url.nil? || absolute_url?(loc)
|
|
73
|
+
|
|
74
|
+
path = loc.to_s.gsub(%r{^/+}, '')
|
|
75
|
+
return "#{base_url}/" if path.empty?
|
|
76
|
+
|
|
77
|
+
"#{base_url}/#{path}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def absolute_url?(loc)
|
|
81
|
+
loc.to_s.match?(%r{\Ahttps?://}i)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def resolve_base_url(config:, base_url:)
|
|
85
|
+
normalize_base_url(base_url) || normalize_base_url(configuration_base_url(config))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def configuration_base_url(config)
|
|
89
|
+
return nil unless config.respond_to?(:sitemap_base_url)
|
|
90
|
+
|
|
91
|
+
config.sitemap_base_url
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def normalize_base_url(base_url)
|
|
95
|
+
value = base_url.to_s.strip
|
|
96
|
+
return nil if value.empty?
|
|
97
|
+
|
|
98
|
+
uri = URI.parse(value)
|
|
99
|
+
return nil unless uri.is_a?(URI::HTTP) && uri.host
|
|
100
|
+
|
|
101
|
+
uri.query = nil
|
|
102
|
+
uri.fragment = nil
|
|
103
|
+
uri.to_s.gsub(%r{/+$}, '')
|
|
104
|
+
rescue URI::InvalidURIError
|
|
105
|
+
nil
|
|
106
|
+
end
|
|
107
|
+
|
|
68
108
|
def format_lastmod(value)
|
|
69
109
|
return nil if value.nil?
|
|
70
110
|
|
data/lib/trifle/docs/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trifle-docs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jozef Vaclavik
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-02-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|