utopia-project 0.40.0 → 0.41.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/bake/utopia/project.rb +9 -17
- data/lib/utopia/project/base.rb +19 -1
- data/lib/utopia/project/document.rb +45 -1
- data/lib/utopia/project/guide.rb +6 -1
- data/lib/utopia/project/guides.rb +3 -4
- data/lib/utopia/project/import_map.rb +4 -1
- data/lib/utopia/project/linkify.rb +15 -1
- data/lib/utopia/project/releases_document.rb +41 -1
- data/lib/utopia/project/renderer.rb +4 -1
- data/lib/utopia/project/sidebar.rb +5 -1
- data/lib/utopia/project/version.rb +1 -1
- data/lib/utopia/project.rb +11 -8
- data/license.md +1 -1
- data/pages/_header.xnode +3 -3
- data/pages/_page.xnode +1 -1
- data/pages/source/_signature.xnode +14 -0
- data/readme.md +24 -7
- data/releases.md +5 -0
- data/template/config/application.rb +12 -0
- data/template/config/environment.rb +8 -0
- data/template/config/serve.rb +8 -0
- data.tar.gz.sig +0 -0
- metadata +8 -20
- metadata.gz.sig +0 -0
- data/template/config.ru +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2b939e146930849d4cf8f02d043129ed9ac4d4e30cef2c672936deeba8ebf834
|
|
4
|
+
data.tar.gz: e481fe629ee2812bf5138577ee0e55b8a1025960bb0f050129b40a1bae3a3565
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d403f98935fc293324f8d0b1001535cfe38d7ce04aea3040257b651d89fd2bcacad593d0749fe2c250bd8b61ccbd30dd00db40f981164865d74ae26831841f51
|
|
7
|
+
data.tar.gz: 28ecbb2dae306f4a0568e7b325a5f47f2d487de5854190db1d82e8bb489effcd8d77d62ef3cf94ece65c21a863a2c7b41158fc5f4141242497908752d8910c20
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/bake/utopia/project.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2020-
|
|
4
|
+
# Copyright, 2020-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
def initialize(context)
|
|
7
7
|
super
|
|
@@ -35,7 +35,7 @@ end
|
|
|
35
35
|
# @parameter port [Integer] The port to bind to.
|
|
36
36
|
# @parameter bind [String] The URL to bind to, e.g. `http://localhost:80`.
|
|
37
37
|
def serve(port: nil, bind: nil)
|
|
38
|
-
config_path = File.expand_path("../../template/config.
|
|
38
|
+
config_path = File.expand_path("../../template/config/serve.rb", __dir__)
|
|
39
39
|
preload_path = File.expand_path("../../template/preload.rb", __dir__)
|
|
40
40
|
|
|
41
41
|
options = []
|
|
@@ -55,22 +55,15 @@ end
|
|
|
55
55
|
# @parameter output_path [String] The output path for the static site.
|
|
56
56
|
# @parameter force [Boolean] Remove the output directory before generating the static content.
|
|
57
57
|
def static(output_path: "docs", force: true)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
config_path = File.expand_path("../../template/config.ru", __dir__)
|
|
58
|
+
application_path = File.expand_path("../../template/config/application.rb", __dir__)
|
|
61
59
|
public_path = File.expand_path("../../public", __dir__)
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Rackula::Command::Top["generate", *arguments,
|
|
70
|
-
"--config", config_path,
|
|
71
|
-
"--public", public_path,
|
|
72
|
-
"--output-path", output_path
|
|
73
|
-
].call
|
|
61
|
+
context["utopia:static:generate"].call(
|
|
62
|
+
output_path: output_path,
|
|
63
|
+
application_path: application_path,
|
|
64
|
+
public_path: public_path,
|
|
65
|
+
force: force,
|
|
66
|
+
)
|
|
74
67
|
|
|
75
68
|
FileUtils.touch File.expand_path(".nojekyll", output_path)
|
|
76
69
|
end
|
|
@@ -94,4 +87,3 @@ def description(root: context.root)
|
|
|
94
87
|
end
|
|
95
88
|
end
|
|
96
89
|
end
|
|
97
|
-
|
data/lib/utopia/project/base.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2020-
|
|
4
|
+
# Copyright, 2020-2026, by Samuel Williams.
|
|
5
5
|
# Copyright, 2023, by Michael Adams.
|
|
6
6
|
|
|
7
7
|
require "utopia/path"
|
|
@@ -24,6 +24,8 @@ module Utopia
|
|
|
24
24
|
class Base
|
|
25
25
|
extend Thread::Local
|
|
26
26
|
|
|
27
|
+
# Load the current project and index its Ruby source files.
|
|
28
|
+
# @returns [Base] The loaded project.
|
|
27
29
|
def self.local
|
|
28
30
|
instance = self.new
|
|
29
31
|
|
|
@@ -100,6 +102,9 @@ module Utopia
|
|
|
100
102
|
end
|
|
101
103
|
end
|
|
102
104
|
|
|
105
|
+
# Load the supplemental document associated with a definition.
|
|
106
|
+
# @parameter definition [Decode::Definition] The definition to load documentation for.
|
|
107
|
+
# @returns [Document | Nil] The supplemental document, if it exists.
|
|
103
108
|
def document_for(definition)
|
|
104
109
|
document_path = File.join("lib", definition.lexical_path.map{|_| _.to_s.downcase}) + ".md"
|
|
105
110
|
|
|
@@ -114,6 +119,11 @@ module Utopia
|
|
|
114
119
|
end
|
|
115
120
|
end
|
|
116
121
|
|
|
122
|
+
# Format source text with links to referenced definitions.
|
|
123
|
+
# @parameter text [String] The source text to format.
|
|
124
|
+
# @parameter definition [Decode::Definition] The definition that provides the lexical context.
|
|
125
|
+
# @parameter language [Decode::Language::Generic] The source language.
|
|
126
|
+
# @returns [String] The formatted source code markup.
|
|
117
127
|
def linkify(text, definition, language: definition&.language)
|
|
118
128
|
rewriter = Linkify.new(self, language, text)
|
|
119
129
|
|
|
@@ -205,22 +215,30 @@ module Utopia
|
|
|
205
215
|
@guides ||= Guides.new(self, @links)
|
|
206
216
|
end
|
|
207
217
|
|
|
218
|
+
# Load the project README document.
|
|
219
|
+
# @returns [Document | Nil] The README document, if one exists.
|
|
208
220
|
def readme_document
|
|
209
221
|
if path = self.path_for("readme.md") || self.path_for("README.md")
|
|
210
222
|
Document.new(File.read(path), self)
|
|
211
223
|
end
|
|
212
224
|
end
|
|
213
225
|
|
|
226
|
+
# Get the project title from its README.
|
|
227
|
+
# @returns [String] The project title, or a generic fallback.
|
|
214
228
|
def project_title
|
|
215
229
|
readme_document&.title || "Project"
|
|
216
230
|
end
|
|
217
231
|
|
|
232
|
+
# Load the project release notes document.
|
|
233
|
+
# @returns [ReleasesDocument | Nil] The release notes document, if one exists.
|
|
218
234
|
def releases_document
|
|
219
235
|
if path = self.path_for("releases.md")
|
|
220
236
|
ReleasesDocument.new(File.read(path), self)
|
|
221
237
|
end
|
|
222
238
|
end
|
|
223
239
|
|
|
240
|
+
# Enumerate the project releases.
|
|
241
|
+
# @returns [Enumerator(ReleasesDocument::Release) | Nil] The releases, if release notes exist.
|
|
224
242
|
def releases
|
|
225
243
|
if releases_document = self.releases_document
|
|
226
244
|
releases_document.releases
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2020-
|
|
4
|
+
# Copyright, 2020-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require_relative "renderer"
|
|
7
7
|
require "xrb"
|
|
8
8
|
|
|
9
9
|
module Utopia
|
|
10
10
|
module Project
|
|
11
|
+
# Represents a Markdown document with optional source code cross-references.
|
|
11
12
|
class Document
|
|
13
|
+
# Initialize a document from Markdown text.
|
|
14
|
+
# @parameter text [String] The Markdown source text.
|
|
15
|
+
# @parameter base [Base | Nil] The project used to resolve source code references.
|
|
16
|
+
# @parameter definition [Decode::Definition | Nil] The definition that provides the lexical context.
|
|
17
|
+
# @parameter default_language [Decode::Language::Generic | Nil] The default language for source code references.
|
|
12
18
|
def initialize(text, base = nil, definition: nil, default_language: nil)
|
|
13
19
|
@text = text
|
|
14
20
|
@base = base
|
|
@@ -20,10 +26,14 @@ module Utopia
|
|
|
20
26
|
@root = nil
|
|
21
27
|
end
|
|
22
28
|
|
|
29
|
+
# Parse and resolve the document root.
|
|
30
|
+
# @returns [Markly::Node] The root document node.
|
|
23
31
|
def root
|
|
24
32
|
@root ||= resolve(Markly.parse(@text, extensions: [:table]))
|
|
25
33
|
end
|
|
26
34
|
|
|
35
|
+
# Extract the leading heading as the document title.
|
|
36
|
+
# @returns [String | Nil] The title, if the document starts with a heading.
|
|
27
37
|
def title
|
|
28
38
|
child = self.root.first_child
|
|
29
39
|
|
|
@@ -32,10 +42,17 @@ module Utopia
|
|
|
32
42
|
end
|
|
33
43
|
end
|
|
34
44
|
|
|
45
|
+
# Get the first node in the document.
|
|
46
|
+
# @returns [Markly::Node | Nil] The first child node.
|
|
35
47
|
def first_child
|
|
36
48
|
self.root.first_child
|
|
37
49
|
end
|
|
38
50
|
|
|
51
|
+
# Remove a named section and yield its heading for replacement.
|
|
52
|
+
# @parameter name [String] A fragment of the heading text to match.
|
|
53
|
+
# @parameter children [Boolean] Whether to remove nested subsections too.
|
|
54
|
+
# @yields {|header| ...} The matched heading node.
|
|
55
|
+
# @parameter header [Markly::Node] The matched heading.
|
|
39
56
|
def replace_section(name, children: false)
|
|
40
57
|
child = self.first_child
|
|
41
58
|
|
|
@@ -72,39 +89,62 @@ module Utopia
|
|
|
72
89
|
end
|
|
73
90
|
end
|
|
74
91
|
|
|
92
|
+
# Render the document as Markdown.
|
|
93
|
+
# @returns [String] The rendered Markdown.
|
|
75
94
|
def to_markdown(**options)
|
|
76
95
|
self.root.to_markdown(**options)
|
|
77
96
|
end
|
|
78
97
|
|
|
98
|
+
# Render a document node as HTML.
|
|
99
|
+
# @parameter node [Markly::Node] The node to render.
|
|
100
|
+
# @returns [XRB::MarkupString] The rendered HTML markup.
|
|
79
101
|
def to_html(node = self.root, **options)
|
|
80
102
|
renderer = Renderer.new(ids: true, flags: Markly::UNSAFE, **options)
|
|
81
103
|
XRB::Markup.raw(renderer.render(node))
|
|
82
104
|
end
|
|
83
105
|
|
|
106
|
+
# Wrap a node in a paragraph.
|
|
107
|
+
# @parameter child [Markly::Node] The node to wrap.
|
|
108
|
+
# @returns [Markly::Node] The paragraph node.
|
|
84
109
|
def paragraph_node(child)
|
|
85
110
|
node = Markly::Node.new(:paragraph)
|
|
86
111
|
node.append_child(child)
|
|
87
112
|
return node
|
|
88
113
|
end
|
|
89
114
|
|
|
115
|
+
# Build an HTML block node.
|
|
116
|
+
# @parameter content [String] The raw HTML content.
|
|
117
|
+
# @parameter type [Symbol] The node type retained for compatibility.
|
|
118
|
+
# @returns [Markly::Node] The HTML node.
|
|
90
119
|
def html_node(content, type = :html)
|
|
91
120
|
node = Markly::Node.new(:html)
|
|
92
121
|
node.string_content = content
|
|
93
122
|
return node
|
|
94
123
|
end
|
|
95
124
|
|
|
125
|
+
# Build an inline HTML node.
|
|
126
|
+
# @parameter content [String] The raw HTML content.
|
|
127
|
+
# @returns [Markly::Node] The inline HTML node.
|
|
96
128
|
def inline_html_node(content)
|
|
97
129
|
node = Markly::Node.new(:inline_html)
|
|
98
130
|
node.string_content = content
|
|
99
131
|
return node
|
|
100
132
|
end
|
|
101
133
|
|
|
134
|
+
# Build a text node.
|
|
135
|
+
# @parameter content [String] The text content.
|
|
136
|
+
# @returns [Markly::Node] The text node.
|
|
102
137
|
def text_node(content)
|
|
103
138
|
node = Markly::Node.new(:text)
|
|
104
139
|
node.string_content = content
|
|
105
140
|
return node
|
|
106
141
|
end
|
|
107
142
|
|
|
143
|
+
# Build a link node around a child node.
|
|
144
|
+
# @parameter title [String | Nil] The link title.
|
|
145
|
+
# @parameter url [String | XRB::Reference] The link target.
|
|
146
|
+
# @parameter child [Markly::Node] The linked child node.
|
|
147
|
+
# @returns [Markly::Node] The link node.
|
|
108
148
|
def link_node(title, url, child)
|
|
109
149
|
node = Markly::Node.new(:link)
|
|
110
150
|
node.title = title
|
|
@@ -115,6 +155,10 @@ module Utopia
|
|
|
115
155
|
return node
|
|
116
156
|
end
|
|
117
157
|
|
|
158
|
+
# Build an inline code node.
|
|
159
|
+
# @parameter content [String] The code content.
|
|
160
|
+
# @parameter language [String | Nil] The source language name.
|
|
161
|
+
# @returns [Markly::Node] The code node.
|
|
118
162
|
def code_node(content, language = nil)
|
|
119
163
|
if language
|
|
120
164
|
node = inline_html_node(
|
data/lib/utopia/project/guide.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2020-
|
|
4
|
+
# Copyright, 2020-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "utopia/path"
|
|
7
7
|
require "xrb/reference"
|
|
@@ -38,10 +38,15 @@ module Utopia
|
|
|
38
38
|
# @attribute [Hash]
|
|
39
39
|
attr :metadata
|
|
40
40
|
|
|
41
|
+
# The explicit display order of the guide.
|
|
42
|
+
# @returns [Integer | Nil]
|
|
41
43
|
def order
|
|
42
44
|
metadata[:order]
|
|
43
45
|
end
|
|
44
46
|
|
|
47
|
+
# Compare guides by explicit order and then by name.
|
|
48
|
+
# @parameter other [Guide] The other guide to compare.
|
|
49
|
+
# @returns [Integer] The comparison result.
|
|
45
50
|
def <=> other
|
|
46
51
|
if order = self.order
|
|
47
52
|
if other_order = other.order
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require_relative "guide"
|
|
7
7
|
|
|
@@ -45,14 +45,14 @@ module Utopia
|
|
|
45
45
|
# @parameter name [String] The guide name.
|
|
46
46
|
# @returns [Guide | Nil]
|
|
47
47
|
def [](name)
|
|
48
|
-
to_a.find
|
|
48
|
+
to_a.find{|guide| guide.name == name}
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# Get the related guides (previous and next) for the given guide.
|
|
52
52
|
# @parameter guide [Guide] The current guide.
|
|
53
53
|
# @returns [Array(Guide | Nil, Guide | Nil)] A two-element array containing the previous and next guides.
|
|
54
54
|
def related(guide)
|
|
55
|
-
index = to_a.index
|
|
55
|
+
index = to_a.index{|g| g.name == guide.name}
|
|
56
56
|
return [nil, nil] unless index
|
|
57
57
|
|
|
58
58
|
previous_guide = index > 0 ? to_a[index - 1] : nil
|
|
@@ -63,4 +63,3 @@ module Utopia
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
|
-
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
|
+
|
|
3
6
|
require "utopia/import_map"
|
|
4
7
|
|
|
5
8
|
module Utopia
|
|
@@ -9,4 +12,4 @@ module Utopia
|
|
|
9
12
|
map.import("@socketry/syntax", "./@socketry/syntax/Syntax.js")
|
|
10
13
|
end
|
|
11
14
|
end
|
|
12
|
-
end
|
|
15
|
+
end
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2020-
|
|
4
|
+
# Copyright, 2020-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "decode/syntax/rewriter"
|
|
7
7
|
|
|
8
8
|
module Utopia
|
|
9
9
|
module Project
|
|
10
|
+
# Rewrites source code as HTML with links to indexed definitions.
|
|
10
11
|
class Linkify < Decode::Syntax::Rewriter
|
|
12
|
+
# Initialize a source code rewriter.
|
|
11
13
|
# @parameter base [Base] The base data.
|
|
14
|
+
# @parameter language [Decode::Language::Generic] The source language.
|
|
15
|
+
# @parameter text [String] The source text to rewrite.
|
|
12
16
|
def initialize(base, language, text)
|
|
13
17
|
@base = base
|
|
14
18
|
@language = language
|
|
@@ -16,12 +20,19 @@ module Utopia
|
|
|
16
20
|
super(text)
|
|
17
21
|
end
|
|
18
22
|
|
|
23
|
+
# Escape an unmatched range of source text for HTML output.
|
|
24
|
+
# @parameter range [Range] The source text range.
|
|
25
|
+
# @returns [String] The escaped text.
|
|
19
26
|
def text_for(range)
|
|
20
27
|
text = super(range)
|
|
21
28
|
|
|
22
29
|
return XRB::Strings.to_html(text)
|
|
23
30
|
end
|
|
24
31
|
|
|
32
|
+
# Build a link to an indexed definition.
|
|
33
|
+
# @parameter definition [Decode::Definition] The linked definition.
|
|
34
|
+
# @parameter text [String] The visible link text.
|
|
35
|
+
# @returns [XRB::MarkupString] The link markup.
|
|
25
36
|
def link_to(definition, text)
|
|
26
37
|
XRB::Builder.fragment do |builder|
|
|
27
38
|
builder.inline("a", href: @base.link_for(definition), title: definition.qualified_name) do
|
|
@@ -30,6 +41,9 @@ module Utopia
|
|
|
30
41
|
end
|
|
31
42
|
end
|
|
32
43
|
|
|
44
|
+
# Apply the source links and wrap the result in a code element.
|
|
45
|
+
# @parameter output [XRB::Builder] The output builder.
|
|
46
|
+
# @returns [String] The generated HTML markup.
|
|
33
47
|
def apply(output = XRB::Builder.new)
|
|
34
48
|
output.inline("code", class: "language-#{@language.name}") do
|
|
35
49
|
super
|
|
@@ -1,39 +1,56 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2024-
|
|
4
|
+
# Copyright, 2024-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require_relative "document"
|
|
7
7
|
require_relative "sidebar"
|
|
8
8
|
|
|
9
9
|
module Utopia
|
|
10
10
|
module Project
|
|
11
|
+
# Represents project release notes organized by release headings.
|
|
11
12
|
class ReleasesDocument < Document
|
|
13
|
+
# Represents a section within a release.
|
|
12
14
|
class Summary
|
|
15
|
+
# Initialize a release section summary.
|
|
16
|
+
# @parameter node [Markly::Node] The section heading node.
|
|
13
17
|
def initialize(node)
|
|
14
18
|
@node = node
|
|
15
19
|
end
|
|
16
20
|
|
|
21
|
+
# The section heading node.
|
|
22
|
+
# @attribute [Markly::Node]
|
|
17
23
|
attr :node
|
|
18
24
|
|
|
25
|
+
# Generate the section identifier.
|
|
26
|
+
# @returns [String] The normalized section identifier.
|
|
19
27
|
def id
|
|
20
28
|
@node.to_plaintext.chomp.downcase.gsub(/\s+/, "-")
|
|
21
29
|
end
|
|
22
30
|
|
|
31
|
+
# Render the section heading contents as Markdown.
|
|
32
|
+
# @returns [String] The rendered Markdown.
|
|
23
33
|
def to_markdown
|
|
24
34
|
@node.dup.extract_children.to_markdown
|
|
25
35
|
end
|
|
26
36
|
|
|
37
|
+
# Render the section heading contents as HTML.
|
|
38
|
+
# @returns [String] The rendered HTML.
|
|
27
39
|
def to_html
|
|
28
40
|
@node.dup.extract_children.to_html
|
|
29
41
|
end
|
|
30
42
|
end
|
|
31
43
|
|
|
44
|
+
# Represents a single release and its notes.
|
|
32
45
|
class Release
|
|
46
|
+
# Initialize a release from its heading node.
|
|
47
|
+
# @parameter node [Markly::Node] The release heading node.
|
|
33
48
|
def initialize(node)
|
|
34
49
|
@node = node
|
|
35
50
|
end
|
|
36
51
|
|
|
52
|
+
# Extract the introductory notes for the release.
|
|
53
|
+
# @returns [Markly::Node] A document containing the release notes.
|
|
37
54
|
def notes
|
|
38
55
|
node = @node.next
|
|
39
56
|
|
|
@@ -48,6 +65,10 @@ module Utopia
|
|
|
48
65
|
return notes
|
|
49
66
|
end
|
|
50
67
|
|
|
68
|
+
# Enumerate the change sections for the release.
|
|
69
|
+
# @yields {|summary| ...} If a block is given.
|
|
70
|
+
# @parameter summary [Summary] A change section.
|
|
71
|
+
# @returns [Enumerator(Summary)] If no block is given.
|
|
51
72
|
def changes
|
|
52
73
|
return to_enum(:changes) unless block_given?
|
|
53
74
|
|
|
@@ -68,15 +89,25 @@ module Utopia
|
|
|
68
89
|
end
|
|
69
90
|
end
|
|
70
91
|
|
|
92
|
+
# Get the release name from its heading.
|
|
93
|
+
# @returns [String] The release name.
|
|
71
94
|
def name
|
|
72
95
|
@node.to_plaintext.chomp
|
|
73
96
|
end
|
|
74
97
|
|
|
98
|
+
# Build a link to a section within the release.
|
|
99
|
+
# @parameter base [String] The base URL path.
|
|
100
|
+
# @parameter anchor [String] The section anchor.
|
|
101
|
+
# @returns [String] The release section URL.
|
|
75
102
|
def href(base = "/", anchor:)
|
|
76
103
|
"#{base}releases/index##{anchor.downcase.gsub(/\s+/, "-")}"
|
|
77
104
|
end
|
|
78
105
|
end
|
|
79
106
|
|
|
107
|
+
# Enumerate release names in document order.
|
|
108
|
+
# @yields {|name| ...} If a block is given.
|
|
109
|
+
# @parameter name [String] A release name.
|
|
110
|
+
# @returns [Enumerator(String)] If no block is given.
|
|
80
111
|
def release_names
|
|
81
112
|
return to_enum(:release_names) unless block_given?
|
|
82
113
|
|
|
@@ -87,6 +118,9 @@ module Utopia
|
|
|
87
118
|
end
|
|
88
119
|
end
|
|
89
120
|
|
|
121
|
+
# Find a release by name.
|
|
122
|
+
# @parameter name [String] The release name.
|
|
123
|
+
# @returns [Release | Nil] The matching release.
|
|
90
124
|
def release(name)
|
|
91
125
|
self.root.each do |node|
|
|
92
126
|
if node.type == :header and node.header_level == 2 and node.to_plaintext.chomp == name
|
|
@@ -95,12 +129,18 @@ module Utopia
|
|
|
95
129
|
end
|
|
96
130
|
end
|
|
97
131
|
|
|
132
|
+
# Get the first release in the document.
|
|
133
|
+
# @returns [Release | Nil] The latest release.
|
|
98
134
|
def latest_release
|
|
99
135
|
if name = release_names.first
|
|
100
136
|
release(name)
|
|
101
137
|
end
|
|
102
138
|
end
|
|
103
139
|
|
|
140
|
+
# Enumerate releases in document order.
|
|
141
|
+
# @yields {|release| ...} If a block is given.
|
|
142
|
+
# @parameter release [Release] A release.
|
|
143
|
+
# @returns [Enumerator(Release)] If no block is given.
|
|
104
144
|
def releases
|
|
105
145
|
return to_enum(:releases) unless block_given?
|
|
106
146
|
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2022-
|
|
4
|
+
# Copyright, 2022-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "markly"
|
|
7
7
|
require "markly/renderer/html"
|
|
8
8
|
|
|
9
9
|
module Utopia
|
|
10
10
|
module Project
|
|
11
|
+
# Renders project Markdown with support for Mermaid code blocks.
|
|
11
12
|
class Renderer < Markly::Renderer::HTML
|
|
13
|
+
# Render a fenced code block, including Mermaid diagrams.
|
|
14
|
+
# @parameter node [Markly::Node] The fenced code block node.
|
|
12
15
|
def code_block(node)
|
|
13
16
|
language, _ = node.fence_info.split(/\s+/, 2)
|
|
14
17
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require_relative "renderer"
|
|
7
7
|
|
|
@@ -12,6 +12,10 @@ module Utopia
|
|
|
12
12
|
|
|
13
13
|
# Represents a sidebar navigation entry with title, level, and anchor.
|
|
14
14
|
class Entry
|
|
15
|
+
# Initialize a sidebar entry.
|
|
16
|
+
# @parameter title_html [XRB::Markup] The rendered heading title.
|
|
17
|
+
# @parameter level [Integer] The heading level.
|
|
18
|
+
# @parameter anchor [String] The heading anchor.
|
|
15
19
|
def initialize(title_html, level, anchor)
|
|
16
20
|
@title_html = title_html
|
|
17
21
|
@level = level
|
data/lib/utopia/project.rb
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2020-
|
|
4
|
+
# Copyright, 2020-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "utopia/project/version"
|
|
7
7
|
|
|
8
8
|
require "variant"
|
|
9
9
|
|
|
10
|
+
require "utopia/application"
|
|
11
|
+
require "utopia/content"
|
|
12
|
+
require "utopia/controller"
|
|
13
|
+
require "utopia/exceptions"
|
|
10
14
|
require "utopia/localization"
|
|
15
|
+
require "utopia/redirection"
|
|
16
|
+
require "utopia/static"
|
|
11
17
|
|
|
12
18
|
require_relative "project/base"
|
|
13
19
|
require_relative "project/import_map"
|
|
14
20
|
|
|
21
|
+
# @namespace
|
|
15
22
|
module Utopia
|
|
23
|
+
# Provides project documentation generation and rendering.
|
|
16
24
|
module Project
|
|
17
25
|
# The root directory of the web application files.
|
|
18
26
|
SITE_ROOT = File.expand_path("../..", __dir__)
|
|
@@ -23,9 +31,9 @@ module Utopia
|
|
|
23
31
|
# The root directory for static assets.
|
|
24
32
|
PUBLIC_ROOT = File.expand_path("public", SITE_ROOT)
|
|
25
33
|
|
|
26
|
-
# Appends a project application to the
|
|
34
|
+
# Appends a project application to the protocol HTTP middleware builder.
|
|
27
35
|
#
|
|
28
|
-
# @parameter builder [
|
|
36
|
+
# @parameter builder [Protocol::HTTP::Middleware::Builder]
|
|
29
37
|
# @parameter root [String] The file-system root path of the project/gem.
|
|
30
38
|
# @parameter locales [Array(String)] an array of locales to support, e.g. `['en', 'ja']`.
|
|
31
39
|
def self.call(builder, root = Dir.pwd, locales: nil)
|
|
@@ -33,9 +41,6 @@ module Utopia
|
|
|
33
41
|
# Handle exceptions in production with a error page and send an email notification:
|
|
34
42
|
builder.use Utopia::Exceptions::Handler
|
|
35
43
|
builder.use Utopia::Exceptions::Mailer
|
|
36
|
-
else
|
|
37
|
-
# We want to propate exceptions up when running tests:
|
|
38
|
-
builder.use Rack::ShowExceptions unless UTOPIA.testing?
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
# We serve static files from the project root:
|
|
@@ -46,7 +51,6 @@ module Utopia
|
|
|
46
51
|
builder.use Utopia::Redirection::Rewrite, {
|
|
47
52
|
"/" => "/index"
|
|
48
53
|
}
|
|
49
|
-
|
|
50
54
|
builder.use Utopia::Redirection::DirectoryIndex
|
|
51
55
|
|
|
52
56
|
builder.use Utopia::Redirection::Errors, {
|
|
@@ -67,7 +71,6 @@ module Utopia
|
|
|
67
71
|
# 'gallery' => Utopia::Gallery::Tags.new
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
builder.run lambda {|env| [404, {}, []]}
|
|
71
74
|
end
|
|
72
75
|
end
|
|
73
76
|
end
|
data/license.md
CHANGED
data/pages/_header.xnode
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
path = path + "index"
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
if link = links(path.dirname, name: path.last, locale: localization
|
|
9
|
+
if link = links(path.dirname, name: path.last, locale: localization&.locale, indices: true).first
|
|
10
10
|
if replace = link[:replace]&.to_sym and base = controller[:base]
|
|
11
11
|
?> › #{link.to_href(content: base.public_send(replace))}<?r
|
|
12
12
|
else
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
?> › <a href="/guides/#{guide.name}/index">#{guide.title}</a> <?r
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
if localization
|
|
33
|
+
if localization&.localized?
|
|
34
34
|
?> • (<?r
|
|
35
35
|
localization.all_locales.each.with_index do |locale, index|
|
|
36
36
|
?>#{index.zero? ? '' : ' '}<a href="#{localization.localized_path(page_path, locale)}">#{locale}</a><?r
|
|
37
37
|
end
|
|
38
38
|
?>)<?r
|
|
39
39
|
end
|
|
40
|
-
?></header>
|
|
40
|
+
?></header>
|
data/pages/_page.xnode
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<link rel="icon" type="image/png" href="/_static/icon.png" />
|
|
16
16
|
<link rel="stylesheet" href="/_static/site.css" type="text/css" media="screen" />
|
|
17
17
|
|
|
18
|
-
#{Utopia::Project::IMPORT_MAP.relative_to(request.
|
|
18
|
+
#{Utopia::Project::IMPORT_MAP.relative_to(request.request_path).to_html}
|
|
19
19
|
<script type="module" src="/_static/application.js"></script>
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
@@ -3,7 +3,21 @@
|
|
|
3
3
|
symbol = self[:symbol]
|
|
4
4
|
documentation = symbol&.documentation
|
|
5
5
|
|
|
6
|
+
# Check if there are any non-Example children before rendering:
|
|
7
|
+
has_signature_children = false
|
|
6
8
|
if documentation&.children?
|
|
9
|
+
documentation.traverse do |node, descend|
|
|
10
|
+
node.each do |child|
|
|
11
|
+
unless child.is_a?(Decode::Comment::Example)
|
|
12
|
+
has_signature_children = true
|
|
13
|
+
break
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
break if has_signature_children
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if has_signature_children
|
|
7
21
|
?>
|
|
8
22
|
<details open>
|
|
9
23
|
<summary><h4>Signature</h4></summary>
|
data/readme.md
CHANGED
|
@@ -33,6 +33,11 @@ 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.41.0
|
|
37
|
+
|
|
38
|
+
- Don't render empty signature block when there are only examples.
|
|
39
|
+
- Use protocol HTTP middleware for serving and testing project documentation.
|
|
40
|
+
|
|
36
41
|
### v0.40.0
|
|
37
42
|
|
|
38
43
|
- 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").
|
|
@@ -71,10 +76,6 @@ Please see the [project releases](https://socketry.github.io/utopia-project/rele
|
|
|
71
76
|
|
|
72
77
|
- Support brief release notes in `releases.md` document.
|
|
73
78
|
|
|
74
|
-
### v0.30.0
|
|
75
|
-
|
|
76
|
-
- [Rename `changes.md` to `releases.md`](https://socketry.github.io/utopia-project/releases/index#rename-changes.md-to-releases.md)
|
|
77
|
-
|
|
78
79
|
## See Also
|
|
79
80
|
|
|
80
81
|
- [Utopia](https://github.com/socketry/utopia) — The website framework which powers this web application.
|
|
@@ -84,11 +85,27 @@ Please see the [project releases](https://socketry.github.io/utopia-project/rele
|
|
|
84
85
|
|
|
85
86
|
We welcome contributions to this project.
|
|
86
87
|
|
|
87
|
-
1. Fork
|
|
88
|
+
1. Fork the repository.
|
|
88
89
|
2. Create your feature branch (`git checkout -b my-new-feature`).
|
|
89
|
-
3. Commit your changes (`git commit -am 'Add some feature'`).
|
|
90
|
+
3. Commit your changes (`git commit -am 'Add some feature.'`).
|
|
90
91
|
4. Push to the branch (`git push origin my-new-feature`).
|
|
91
|
-
5. Create new
|
|
92
|
+
5. Create a new pull request.
|
|
93
|
+
|
|
94
|
+
### Running Tests
|
|
95
|
+
|
|
96
|
+
To run the test suite:
|
|
97
|
+
|
|
98
|
+
``` shell
|
|
99
|
+
bundle exec sus
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Making Releases
|
|
103
|
+
|
|
104
|
+
To make a new release:
|
|
105
|
+
|
|
106
|
+
``` shell
|
|
107
|
+
bundle exec bake gem:release:patch # or minor or major
|
|
108
|
+
```
|
|
92
109
|
|
|
93
110
|
### Developer Certificate of Origin
|
|
94
111
|
|
data/releases.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## v0.41.0
|
|
4
|
+
|
|
5
|
+
- Don't render empty signature block when there are only examples.
|
|
6
|
+
- Use protocol HTTP middleware for serving and testing project documentation.
|
|
7
|
+
|
|
3
8
|
## v0.40.0
|
|
4
9
|
|
|
5
10
|
- 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").
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require_relative "environment"
|
|
7
|
+
|
|
8
|
+
require "utopia/project"
|
|
9
|
+
|
|
10
|
+
Application = Utopia::Application.build do |builder|
|
|
11
|
+
Utopia::Project.call(builder)
|
|
12
|
+
end
|
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.
|
|
4
|
+
version: 0.41.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -83,20 +83,6 @@ dependencies:
|
|
|
83
83
|
- - "~>"
|
|
84
84
|
- !ruby/object:Gem::Version
|
|
85
85
|
version: '0.15'
|
|
86
|
-
- !ruby/object:Gem::Dependency
|
|
87
|
-
name: rackula
|
|
88
|
-
requirement: !ruby/object:Gem::Requirement
|
|
89
|
-
requirements:
|
|
90
|
-
- - "~>"
|
|
91
|
-
- !ruby/object:Gem::Version
|
|
92
|
-
version: '1.3'
|
|
93
|
-
type: :runtime
|
|
94
|
-
prerelease: false
|
|
95
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
96
|
-
requirements:
|
|
97
|
-
- - "~>"
|
|
98
|
-
- !ruby/object:Gem::Version
|
|
99
|
-
version: '1.3'
|
|
100
86
|
- !ruby/object:Gem::Dependency
|
|
101
87
|
name: thread-local
|
|
102
88
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -117,14 +103,14 @@ dependencies:
|
|
|
117
103
|
requirements:
|
|
118
104
|
- - "~>"
|
|
119
105
|
- !ruby/object:Gem::Version
|
|
120
|
-
version: '
|
|
106
|
+
version: '3.0'
|
|
121
107
|
type: :runtime
|
|
122
108
|
prerelease: false
|
|
123
109
|
version_requirements: !ruby/object:Gem::Requirement
|
|
124
110
|
requirements:
|
|
125
111
|
- - "~>"
|
|
126
112
|
- !ruby/object:Gem::Version
|
|
127
|
-
version: '
|
|
113
|
+
version: '3.0'
|
|
128
114
|
executables: []
|
|
129
115
|
extensions: []
|
|
130
116
|
extra_rdoc_files: []
|
|
@@ -674,7 +660,9 @@ files:
|
|
|
674
660
|
- public/robots.txt
|
|
675
661
|
- readme.md
|
|
676
662
|
- releases.md
|
|
677
|
-
- template/config.
|
|
663
|
+
- template/config/application.rb
|
|
664
|
+
- template/config/environment.rb
|
|
665
|
+
- template/config/serve.rb
|
|
678
666
|
- template/gems.rb
|
|
679
667
|
- template/preload.rb
|
|
680
668
|
homepage: https://socketry.github.io/utopia-project
|
|
@@ -691,14 +679,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
691
679
|
requirements:
|
|
692
680
|
- - ">="
|
|
693
681
|
- !ruby/object:Gem::Version
|
|
694
|
-
version: '3.
|
|
682
|
+
version: '3.3'
|
|
695
683
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
696
684
|
requirements:
|
|
697
685
|
- - ">="
|
|
698
686
|
- !ruby/object:Gem::Version
|
|
699
687
|
version: '0'
|
|
700
688
|
requirements: []
|
|
701
|
-
rubygems_version:
|
|
689
|
+
rubygems_version: 4.0.10
|
|
702
690
|
specification_version: 4
|
|
703
691
|
summary: A project documentation tool based on Utopia.
|
|
704
692
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|