utopia-project 0.39.0 → 0.40.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: 21be268fb201720abe3d699eba3f8a71ebee79896293f8aaa0861a592d650dab
4
- data.tar.gz: 93c814b9d849ad90d3a7761cf6d4c9bd2713293fb7de7bb48b5b2f28b3c8b34d
3
+ metadata.gz: 9857e236b8690b3e3c8ae113309fdf2af695222643cc998bcac8862c09232465
4
+ data.tar.gz: b8ccb22331616e6f1ff287c067bf22ace7148c7627a6be9209be9c86f928a87d
5
5
  SHA512:
6
- metadata.gz: b0ece167920bd1069f74879b53a1844948808613e6865ecc3984861c9d6c6fe89bb9d2b98e60cb545523c488c8d5c439f8f5ff7a3b589a54222225272c3837f7
7
- data.tar.gz: 885452bfa693632fae6fedb2970ec85575e7633fe2f98c62f06195f524f3fb4d27333b7eb399abfeb33455b5e6a4a390393a8163e526d5534f2528544048de68
6
+ metadata.gz: c9e2c1640bb841704474c7bf6e3bf1a077fa9eae05267fb45874ea5b07c2beefcdfd92011d152e55db42fff3a1b037611355ddcd94e9f43b6425049f765e4741
7
+ data.tar.gz: 21796bcb1f5844dce244d0421a92d86ee3e25a0bf8daa05e12e6c41103fbc0e64f6703f8de664e1ce1110509876f0073850e55980c95847a8c492959ec14da3c
checksums.yaml.gz.sig CHANGED
Binary file
@@ -15,7 +15,7 @@ require "thread/local"
15
15
  require_relative "document"
16
16
  require_relative "releases_document"
17
17
 
18
- require_relative "guide"
18
+ require_relative "guides"
19
19
  require_relative "linkify"
20
20
 
21
21
  module Utopia
@@ -193,10 +193,8 @@ module Utopia
193
193
  end
194
194
  end
195
195
 
196
- # Enumerate over all available guides in order.
197
- # @yields {|guide| ...} If a block is given.
198
- # @parameter guide [Guide]
199
- # @returns [Enumerator(Guide)] If no block given.
196
+ # Get the guides collection for this project.
197
+ # @returns [Guides]
200
198
  #
201
199
  # @example List guide titles
202
200
  # base = Utopia::Project::Base.new
@@ -204,15 +202,7 @@ module Utopia
204
202
  # puts guide.title
205
203
  # end
206
204
  def guides
207
- return to_enum(:guides) unless block_given?
208
-
209
- @links.index("/guides").each do |link|
210
- guide_path = File.join(@root, link.path)
211
-
212
- next unless File.directory?(guide_path)
213
-
214
- yield Guide.new(self, guide_path, link.info)
215
- end
205
+ @guides ||= Guides.new(self, @links)
216
206
  end
217
207
 
218
208
  def readme_document
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "guide"
7
+
8
+ module Utopia
9
+ module Project
10
+ # A collection of guides with navigation and lookup capabilities.
11
+ class Guides
12
+ include Enumerable
13
+
14
+ # Initialize the guides collection.
15
+ # @parameter base [Base] The base instance for the project.
16
+ # @parameter links [Object] The links index for finding guides.
17
+ def initialize(base, links)
18
+ @base = base
19
+ @links = links
20
+ end
21
+
22
+ # Iterate over all guides.
23
+ # @yields {|guide| ...} If a block is given.
24
+ # @parameter guide [Guide]
25
+ # @returns [Enumerator(Guide)] If no block is given.
26
+ def each(&block)
27
+ return to_enum(:each) unless block_given?
28
+
29
+ @links.index("/guides").each do |link|
30
+ guide_path = File.join(@base.root, link.path)
31
+
32
+ next unless File.directory?(guide_path)
33
+
34
+ yield Guide.new(@base, guide_path, link.info)
35
+ end
36
+ end
37
+
38
+ # Get all guides as a sorted array.
39
+ # @returns [Array(Guide)]
40
+ def to_a
41
+ @array ||= super.sort
42
+ end
43
+
44
+ # Find a guide by name.
45
+ # @parameter name [String] The guide name.
46
+ # @returns [Guide | Nil]
47
+ def [](name)
48
+ to_a.find { |guide| guide.name == name }
49
+ end
50
+
51
+ # Get the related guides (previous and next) for the given guide.
52
+ # @parameter guide [Guide] The current guide.
53
+ # @returns [Array(Guide | Nil, Guide | Nil)] A two-element array containing the previous and next guides.
54
+ def related(guide)
55
+ index = to_a.index { |g| g.name == guide.name }
56
+ return [nil, nil] unless index
57
+
58
+ previous_guide = index > 0 ? to_a[index - 1] : nil
59
+ next_guide = index < to_a.size - 1 ? to_a[index + 1] : nil
60
+
61
+ [previous_guide, next_guide]
62
+ end
63
+ end
64
+ end
65
+ end
66
+
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "utopia/import_map"
2
4
 
3
5
  module Utopia
@@ -90,24 +90,14 @@ module Utopia
90
90
  private
91
91
 
92
92
  def self.extract_headings_from_document(document)
93
- headings = []
94
- return headings unless document&.root
93
+ return [] unless document&.root
95
94
 
96
- document.root.walk do |node|
97
- if node.type == :header
98
- next if node.header_level < 2 or node.header_level > 3
99
-
100
- fragment = node.dup.extract_children
101
-
102
- title = XRB::Markup.raw(fragment.to_html)
103
- level = node.header_level
104
- anchor = Markly::Renderer::HTML.anchor_for(fragment)
105
-
106
- headings << Entry.new(title, level, anchor)
107
- end
95
+ Markly::Renderer::Headings.extract(document.root, min_level: 2, max_level: 3).map do |heading|
96
+ fragment = heading.node.dup.extract_children
97
+ title = XRB::Markup.raw(fragment.to_html)
98
+
99
+ Entry.new(title, heading.level, heading.anchor)
108
100
  end
109
-
110
- headings
111
101
  end
112
102
  end
113
103
  end
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Utopia
7
7
  module Project
8
- VERSION = "0.39.0"
8
+ VERSION = "0.40.0"
9
9
  end
10
10
  end
data/pages/_usage.xnode CHANGED
@@ -3,7 +3,7 @@
3
3
  <?r
4
4
  base = self[:base]
5
5
 
6
- base.guides do |guide|
6
+ base.guides.each do |guide|
7
7
  ?>
8
8
  <section>
9
9
  <h3><a href="#{guide.href}">#{guide.title}</a></h3>
@@ -18,4 +18,4 @@
18
18
  </section>
19
19
  <?r
20
20
  end
21
- ?>
21
+ ?>
@@ -1,16 +1,25 @@
1
1
  <content:page>
2
- <?r
3
- base = self[:base]
4
- ?>
5
2
  <content:heading>Guides</content:heading>
6
3
 
7
- <ul>
4
+ <section>
8
5
  <?r
9
- base = controller[:base]
6
+ base = self[:base]
10
7
 
11
- base.guides do |guide|
12
- ?><li><a href="#{guide.name}/">#{guide.title}</a></li><?r
8
+ base.guides.each do |guide|
9
+ ?>
10
+ <section>
11
+ <h3><a href="#{guide.href}">#{guide.title}</a></h3>
12
+
13
+ <?r if description = guide.description ?>
14
+ #{Markup.raw description.to_html}
15
+ <?r elsif documentation = guide.documentation ?>
16
+ #{base.format(documentation.text, language: guide.documentation.language)}
17
+ <?r else ?>
18
+ <p>No description.</p>
19
+ <?r end ?>
20
+ </section>
21
+ <?r
13
22
  end
14
23
  ?>
15
- </ul>
24
+ </section>
16
25
  </content:page>
@@ -9,6 +9,24 @@
9
9
  #{navigation.to_html}
10
10
  </aside>
11
11
  <div class="content">
12
+ <?r
13
+ previous_guide, next_guide = base.guides.related(guide)
14
+
15
+ if previous_guide or next_guide
16
+ ?>
17
+ <nav class="top">
18
+ <?r if previous_guide
19
+ ?><a href="#{previous_guide.href}" class="previous">← #{previous_guide.title}</a><?r
20
+ end
21
+
22
+ if next_guide
23
+ ?><a href="#{next_guide.href}" class="next">#{next_guide.title} →</a><?r
24
+ end ?>
25
+ </nav>
26
+ <?r
27
+ end
28
+ ?>
29
+
12
30
  <content:heading>#{guide.title}</content:heading>
13
31
 
14
32
  <?r
@@ -27,5 +45,21 @@
27
45
  end
28
46
  end
29
47
  ?>
48
+
49
+ <?r
50
+ if previous_guide or next_guide
51
+ ?>
52
+ <nav class="bottom">
53
+ <?r if previous_guide
54
+ ?><a href="#{previous_guide.href}" class="previous">← #{previous_guide.title}</a><?r
55
+ end
56
+
57
+ if next_guide
58
+ ?><a href="#{next_guide.href}" class="next">#{next_guide.title} →</a><?r
59
+ end ?>
60
+ </nav>
61
+ <?r
62
+ end
63
+ ?>
30
64
  </div>
31
65
  </content:page>
@@ -594,3 +594,37 @@ ul.pragmas li.asynchronous {
594
594
  border-left-color: var(--accent-color);
595
595
  font-weight: 500;
596
596
  }
597
+
598
+ /* Guide navigation (previous/next) */
599
+ .content nav {
600
+ display: flex;
601
+ justify-content: space-between;
602
+ gap: 1rem;
603
+ margin: 1rem;
604
+ font-size: 0.9rem;
605
+ font-weight: 500;
606
+ }
607
+
608
+ .content nav.top {
609
+ border-bottom: 1px solid var(--underlay-color);
610
+ padding-bottom: 0.5rem;
611
+ }
612
+
613
+ .content nav.bottom {
614
+ border-top: 1px solid var(--underlay-color);
615
+ padding-top: 0.5rem;
616
+ }
617
+
618
+ .content nav .next {
619
+ margin-left: auto;
620
+ }
621
+
622
+ @media (max-width: 768px) {
623
+ .content nav {
624
+ flex-direction: column;
625
+ }
626
+
627
+ .content nav .next {
628
+ margin-left: 0;
629
+ }
630
+ }
data/readme.md CHANGED
@@ -33,6 +33,12 @@ Please see the [project documentation](https://socketry.github.io/utopia-project
33
33
 
34
34
  Please see the [project releases](https://socketry.github.io/utopia-project/releases/index) for all releases.
35
35
 
36
+ ### v0.40.0
37
+
38
+ - Fixed duplicate heading IDs when multiple sections have the same title. Permalinks and sidebar scroll tracking now work correctly when you have headings with identical text in different sections (e.g., multiple "Deployment" subsections under "Kubernetes" and "Systemd").
39
+ - Improved guides index page to show guide summaries (first paragraph) instead of just listing titles.
40
+ - Added previous/next navigation at the top and bottom of guide pages for easier sequential reading.
41
+
36
42
  ### v0.37.3
37
43
 
38
44
  - Support for `@example` pragmas from the `decode` gem, allowing inline code examples to be rendered in API documentation.
@@ -69,10 +75,6 @@ Please see the [project releases](https://socketry.github.io/utopia-project/rele
69
75
 
70
76
  - [Rename `changes.md` to `releases.md`](https://socketry.github.io/utopia-project/releases/index#rename-changes.md-to-releases.md)
71
77
 
72
- ### v0.29.0
73
-
74
- - [Improve `changes.md` document organization](https://socketry.github.io/utopia-project/releases/index#improve-changes.md-document-organization)
75
-
76
78
  ## See Also
77
79
 
78
80
  - [Utopia](https://github.com/socketry/utopia) — The website framework which powers this web application.
data/releases.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changes
2
2
 
3
+ ## v0.40.0
4
+
5
+ - Fixed duplicate heading IDs when multiple sections have the same title. Permalinks and sidebar scroll tracking now work correctly when you have headings with identical text in different sections (e.g., multiple "Deployment" subsections under "Kubernetes" and "Systemd").
6
+ - Improved guides index page to show guide summaries (first paragraph) instead of just listing titles.
7
+ - Added previous/next navigation at the top and bottom of guide pages for easier sequential reading.
8
+
3
9
  ## v0.37.3
4
10
 
5
11
  - Support for `@example` pragmas from the `decode` gem, allowing inline code examples to be rendered in API documentation.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: utopia-project
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.0
4
+ version: 0.40.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -75,14 +75,14 @@ dependencies:
75
75
  requirements:
76
76
  - - "~>"
77
77
  - !ruby/object:Gem::Version
78
- version: '0.7'
78
+ version: '0.15'
79
79
  type: :runtime
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
82
82
  requirements:
83
83
  - - "~>"
84
84
  - !ruby/object:Gem::Version
85
- version: '0.7'
85
+ version: '0.15'
86
86
  - !ruby/object:Gem::Dependency
87
87
  name: rackula
88
88
  requirement: !ruby/object:Gem::Requirement
@@ -142,6 +142,7 @@ files:
142
142
  - lib/utopia/project/base.rb
143
143
  - lib/utopia/project/document.rb
144
144
  - lib/utopia/project/guide.rb
145
+ - lib/utopia/project/guides.rb
145
146
  - lib/utopia/project/import_map.rb
146
147
  - lib/utopia/project/linkify.rb
147
148
  - lib/utopia/project/releases_document.rb
@@ -697,7 +698,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
697
698
  - !ruby/object:Gem::Version
698
699
  version: '0'
699
700
  requirements: []
700
- rubygems_version: 3.7.2
701
+ rubygems_version: 3.6.9
701
702
  specification_version: 4
702
703
  summary: A project documentation tool based on Utopia.
703
704
  test_files: []
metadata.gz.sig CHANGED
Binary file