docyard 1.0.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ea61eefa97dc9199d17929def1315fdf2ce71f75ddf4f03833b9291fa64ce75
4
- data.tar.gz: '0538fae77efffb84a8aac4ba979510419ff2a8cd8eec1b5aaf9effc2950595d8'
3
+ metadata.gz: 69c121af95a08c379f260d0d444aa4bc5272fdfe2d0699866091885c9f503601
4
+ data.tar.gz: 4550cdcc1d6863b545c4900aac9adb10f14d96a7394ccd3fe4c8924969b278dc
5
5
  SHA512:
6
- metadata.gz: f184c67f1be8766cdd6339da6b25ccd8b7f1d0150ce3f6c0db0de8dd68c590b82e29f76a4ec1928c29151018d318225f2769cea58be9ad1dc2c721a2593663d5
7
- data.tar.gz: 982f4bdcd4170dd013dd5ee10fb21db935eeafcb486372a45db7ae58a3f8d75e6c716555585695ea9527cc7fbd2bf0e43c5a7982894160ec6832c591c2db45a1
6
+ metadata.gz: 690e11d0792b71540f09d26fe45dc46d57558b3aad1b3cf80f3e08c592a4056408b6b8a57bfc47f2459feba94e481038f11ccef287534a9f82e557c255728b53
7
+ data.tar.gz: 8baa1a707f2ff94152499b66c19596a57984c5ff763d2cf43390d986030e2e2eea994febac3089766a764ec1d6314a61479fe2caa54434ee5e64c86ade6431e1
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.2] - 2026-01-23
11
+
12
+ ### Fixed
13
+ - "Last updated" timestamps now show correct dates when deploying via CI (#129)
14
+
15
+ ### Documentation
16
+ - Added git history requirements for accurate timestamps on GitHub Actions, Vercel, and Netlify
17
+
10
18
  ## [1.0.1] - 2026-01-22
11
19
 
12
20
  ### Added
@@ -216,7 +224,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
216
224
  - Initial gem structure
217
225
  - Project scaffolding
218
226
 
219
- [Unreleased]: https://github.com/sanifhimani/docyard/compare/v1.0.1...HEAD
227
+ [Unreleased]: https://github.com/sanifhimani/docyard/compare/v1.0.2...HEAD
228
+ [1.0.2]: https://github.com/sanifhimani/docyard/compare/v1.0.1...v1.0.2
220
229
  [1.0.1]: https://github.com/sanifhimani/docyard/compare/v1.0.0...v1.0.1
221
230
  [1.0.0]: https://github.com/sanifhimani/docyard/compare/v0.9.0...v1.0.0
222
231
  [0.9.0]: https://github.com/sanifhimani/docyard/compare/v0.8.0...v0.9.0
@@ -142,7 +142,8 @@ module Docyard
142
142
  def replace_content_image_paths(content, base_url)
143
143
  return content if base_url == "/"
144
144
 
145
- content.gsub(%r{(<img[^>]*\ssrc=")/(?!_docyard/)([^"]*")}) do
145
+ base_path_pattern = Regexp.escape(base_url.delete_prefix("/"))
146
+ content.gsub(%r{(<img[^>]*\ssrc=")/(?!_docyard/|#{base_path_pattern})([^"]*")}) do
146
147
  "#{Regexp.last_match(1)}#{base_url}#{Regexp.last_match(2)}"
147
148
  end
148
149
  end
@@ -155,7 +155,8 @@ module Docyard
155
155
  @navigation_builder ||= Navigation::PageNavigationBuilder.new(
156
156
  docs_path: docs_path,
157
157
  config: config,
158
- sidebar_cache: sidebar_cache
158
+ sidebar_cache: sidebar_cache,
159
+ base_url: config.build.base
159
160
  )
160
161
  end
161
162
 
@@ -7,10 +7,11 @@ require_relative "breadcrumb_builder"
7
7
  module Docyard
8
8
  module Navigation
9
9
  class PageNavigationBuilder
10
- def initialize(docs_path:, config:, sidebar_cache: nil)
10
+ def initialize(docs_path:, config:, sidebar_cache: nil, base_url: "/")
11
11
  @docs_path = docs_path
12
12
  @config = config
13
13
  @sidebar_cache = sidebar_cache
14
+ @base_url = base_url
14
15
  end
15
16
 
16
17
  def build(current_path:, markdown:, header_ctas: [], show_sidebar: true)
@@ -26,7 +27,7 @@ module Docyard
26
27
 
27
28
  private
28
29
 
29
- attr_reader :docs_path, :config, :sidebar_cache
30
+ attr_reader :docs_path, :config, :sidebar_cache, :base_url
30
31
 
31
32
  def empty_navigation
32
33
  { sidebar_html: "", prev_next_html: "", breadcrumbs: nil }
@@ -47,7 +48,8 @@ module Docyard
47
48
  sidebar_tree: sidebar_builder.tree,
48
49
  current_path: current_path,
49
50
  frontmatter: markdown.frontmatter,
50
- config: {}
51
+ config: {},
52
+ base_url: base_url
51
53
  ).to_html
52
54
  end
53
55
 
@@ -5,13 +5,14 @@ require_relative "../utils/path_resolver"
5
5
 
6
6
  module Docyard
7
7
  class PrevNextBuilder
8
- attr_reader :sidebar_tree, :current_path, :frontmatter, :config
8
+ attr_reader :sidebar_tree, :current_path, :frontmatter, :config, :base_url
9
9
 
10
- def initialize(sidebar_tree:, current_path:, frontmatter: {}, config: {})
10
+ def initialize(sidebar_tree:, current_path:, frontmatter: {}, config: {}, base_url: "/")
11
11
  @sidebar_tree = sidebar_tree
12
12
  @current_path = Utils::PathResolver.normalize(current_path)
13
13
  @frontmatter = frontmatter
14
14
  @config = config
15
+ @base_url = base_url
15
16
  end
16
17
 
17
18
  def prev_next_links
@@ -27,7 +28,7 @@ module Docyard
27
28
  links = prev_next_links
28
29
  return "" if links.nil? || (links[:prev].nil? && links[:next].nil?)
29
30
 
30
- Renderer.new.render_partial(
31
+ Renderer.new(base_url: base_url).render_partial(
31
32
  "_prev_next", {
32
33
  prev: links[:prev],
33
34
  next: links[:next],
@@ -35,7 +35,7 @@ module Docyard
35
35
  markdown = Markdown.new(raw_content, config: config, file_path: file_path)
36
36
 
37
37
  render(
38
- content: strip_md_from_links(markdown.html),
38
+ content: process_content_links(markdown.html),
39
39
  page_title: markdown.title || Constants::DEFAULT_SITE_TITLE,
40
40
  page_description: markdown.description,
41
41
  page_og_image: markdown.og_image,
@@ -51,7 +51,7 @@ module Docyard
51
51
  def render_for_search(file_path)
52
52
  markdown = Markdown.new(File.read(file_path), config: config, file_path: file_path)
53
53
  title = markdown.title || Constants::DEFAULT_SITE_TITLE
54
- content = strip_md_from_links(markdown.html)
54
+ content = process_content_links(markdown.html)
55
55
 
56
56
  <<~HTML
57
57
  <!DOCTYPE html>
@@ -170,10 +170,25 @@ module Docyard
170
170
  @footer_links = footer[:links]
171
171
  end
172
172
 
173
+ def process_content_links(html)
174
+ rewrite_internal_links(strip_md_from_links(html))
175
+ end
176
+
173
177
  def strip_md_from_links(html)
174
178
  html.gsub(/href="([^"]+)\.md"/, 'href="\1"')
175
179
  end
176
180
 
181
+ def rewrite_internal_links(html)
182
+ return html if base_url == "/"
183
+
184
+ html.gsub(%r{href="(/(?!/)[^"]*)"}) do |_match|
185
+ path = ::Regexp.last_match(1)
186
+ next %(href="#{path}") if path.start_with?(base_url)
187
+
188
+ %(href="#{base_url.chomp('/')}#{path}")
189
+ end
190
+ end
191
+
177
192
  def assign_git_info(branding, file_path)
178
193
  @show_edit_link = branding[:show_edit_link] && file_path
179
194
  @show_last_updated = branding[:show_last_updated] && file_path
@@ -11,12 +11,13 @@ module Docyard
11
11
  class PreviewServer
12
12
  DEFAULT_PORT = 4000
13
13
 
14
- attr_reader :port, :output_dir
14
+ attr_reader :port, :output_dir, :base_url
15
15
 
16
16
  def initialize(port: DEFAULT_PORT)
17
17
  @port = port
18
18
  @config = Config.load
19
19
  @output_dir = File.expand_path(@config.build.output)
20
+ @base_url = normalize_base_url(@config.build.base)
20
21
  @launcher = nil
21
22
  end
22
23
 
@@ -38,12 +39,12 @@ module Docyard
38
39
  def print_server_info
39
40
  Docyard.logger.info("Starting preview server...")
40
41
  Docyard.logger.info("* Version: #{Docyard::VERSION}")
41
- Docyard.logger.info("* Running at: http://localhost:#{port}")
42
+ Docyard.logger.info("* Running at: http://localhost:#{port}#{base_url}")
42
43
  Docyard.logger.info("Use Ctrl+C to stop\n")
43
44
  end
44
45
 
45
46
  def run_server
46
- app = StaticFileApp.new(output_dir)
47
+ app = StaticFileApp.new(output_dir, base_path: base_url)
47
48
  puma_config = build_puma_config(app)
48
49
  log_writer = Puma::LogWriter.strings
49
50
 
@@ -64,5 +65,12 @@ module Docyard
64
65
  config.quiet
65
66
  end
66
67
  end
68
+
69
+ def normalize_base_url(url)
70
+ return "/" if url.nil? || url.empty?
71
+
72
+ url = "/#{url}" unless url.start_with?("/")
73
+ url.end_with?("/") ? url : "#{url}/"
74
+ end
67
75
  end
68
76
  end
@@ -4,15 +4,20 @@ require "rack/mime"
4
4
 
5
5
  module Docyard
6
6
  class StaticFileApp
7
- def initialize(root)
7
+ def initialize(root, base_path: "/")
8
8
  @root = root
9
+ @base_path = base_path.chomp("/")
9
10
  end
10
11
 
11
12
  def call(env)
12
13
  path = env["PATH_INFO"]
13
- file_path = File.join(@root, path)
14
14
 
15
- if path.end_with?("/") || File.directory?(file_path)
15
+ return serve_not_found unless path_under_base?(path)
16
+
17
+ relative_path = strip_base_path(path)
18
+ file_path = File.join(@root, relative_path)
19
+
20
+ if relative_path.end_with?("/") || relative_path.empty? || File.directory?(file_path)
16
21
  index_path = File.join(file_path, "index.html")
17
22
  return serve_file(index_path) if File.file?(index_path)
18
23
  elsif File.file?(file_path)
@@ -24,6 +29,18 @@ module Docyard
24
29
 
25
30
  private
26
31
 
32
+ def path_under_base?(path)
33
+ return true if @base_path.empty?
34
+
35
+ path == @base_path || path.start_with?("#{@base_path}/")
36
+ end
37
+
38
+ def strip_base_path(path)
39
+ return path if @base_path.empty?
40
+
41
+ path.delete_prefix(@base_path)
42
+ end
43
+
27
44
  def serve_file(path)
28
45
  content = File.read(path)
29
46
  content_type = Rack::Mime.mime_type(File.extname(path), "application/octet-stream")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Docyard
4
- VERSION = "1.0.1"
4
+ VERSION = "1.0.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docyard
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sanif Himani
@@ -178,7 +178,7 @@ dependencies:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0.18'
181
- description: Beautiful, zero-config documentation sites. Built with Ruby.
181
+ description: Generate beautiful documentation sites from Markdown
182
182
  email:
183
183
  - sanifhimani92@gmail.com
184
184
  executables:
@@ -403,13 +403,16 @@ files:
403
403
  - lib/docyard/utils/text_formatter.rb
404
404
  - lib/docyard/utils/url_helpers.rb
405
405
  - lib/docyard/version.rb
406
- homepage: https://github.com/sanifhimani/docyard
406
+ homepage: https://docyard.dev
407
407
  licenses:
408
408
  - MIT
409
409
  metadata:
410
410
  allowed_push_host: https://rubygems.org
411
- homepage_uri: https://github.com/sanifhimani/docyard
411
+ homepage_uri: https://docyard.dev
412
412
  source_code_uri: https://github.com/sanifhimani/docyard
413
+ changelog_uri: https://github.com/sanifhimani/docyard/blob/main/CHANGELOG.md
414
+ documentation_uri: https://docyard.dev
415
+ bug_tracker_uri: https://github.com/sanifhimani/docyard/issues
413
416
  rubygems_mfa_required: 'true'
414
417
  post_install_message:
415
418
  rdoc_options: []
@@ -429,5 +432,5 @@ requirements: []
429
432
  rubygems_version: 3.5.22
430
433
  signing_key:
431
434
  specification_version: 4
432
- summary: Documentation generator for Ruby
435
+ summary: Generate beautiful documentation sites from Markdown
433
436
  test_files: []