docit 0.3.1 → 0.5.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
- data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- data/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- data/CHANGELOG.md +33 -2
- data/CONTRIBUTING.md +1 -1
- data/README.md +41 -14
- data/app/controllers/docit/ui_controller.rb +57 -3
- data/config/routes.rb +3 -0
- data/lib/docit/ai/autodoc_runner.rb +25 -24
- data/lib/docit/ai/system_insight_generator.rb +127 -0
- data/lib/docit/ai/tag_injector.rb +1 -1
- data/lib/docit/ai.rb +1 -0
- data/lib/docit/configuration.rb +37 -1
- data/lib/docit/doc_file.rb +1 -1
- data/lib/docit/dsl.rb +6 -3
- data/lib/docit/operation.rb +7 -2
- data/lib/docit/route_inspector.rb +1 -1
- data/lib/docit/schema_generator.rb +24 -5
- data/lib/docit/system_graph/edge.rb +29 -0
- data/lib/docit/system_graph/generator.rb +15 -0
- data/lib/docit/system_graph/graph.rb +55 -0
- data/lib/docit/system_graph/node.rb +32 -0
- data/lib/docit/system_graph/rails_analyzer.rb +251 -0
- data/lib/docit/system_graph/source_scanner.rb +77 -0
- data/lib/docit/system_graph.rb +8 -0
- data/lib/docit/ui/base_renderer.rb +54 -21
- data/lib/docit/ui/system_renderer.rb +113 -0
- data/lib/docit/ui/system_script.rb +1495 -0
- data/lib/docit/ui/system_styles.rb +582 -0
- data/lib/docit/version.rb +1 -1
- data/lib/docit.rb +4 -0
- data/lib/generators/docit/install/install_generator.rb +3 -3
- data/lib/generators/docit/install/templates/initializer.rb +4 -0
- data/lib/tasks/docit.rake +1 -1
- metadata +15 -6
- data/docs/images/scalar_image.png +0 -0
- data/docs/images/swagger_image.png +0 -0
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
module Docit
|
|
4
4
|
module UI
|
|
5
5
|
class BaseRenderer
|
|
6
|
-
attr_reader :spec_url, :title, :nav_paths
|
|
6
|
+
attr_reader :spec_url, :system_url, :system_insights_url, :title, :nav_paths
|
|
7
7
|
|
|
8
|
-
def initialize(spec_url:, nav_paths: {})
|
|
8
|
+
def initialize(spec_url:, system_url: nil, system_insights_url: nil, nav_paths: {})
|
|
9
9
|
@spec_url = spec_url
|
|
10
|
+
@system_url = system_url
|
|
11
|
+
@system_insights_url = system_insights_url
|
|
10
12
|
@nav_paths = nav_paths
|
|
11
13
|
@title = ERB::Util.html_escape(Docit.configuration.title)
|
|
12
14
|
end
|
|
@@ -20,35 +22,66 @@ module Docit
|
|
|
20
22
|
def nav_bar(active:)
|
|
21
23
|
swagger_active = active == :swagger
|
|
22
24
|
scalar_active = active == :scalar
|
|
25
|
+
system_active = active == :system
|
|
23
26
|
|
|
24
27
|
<<~HTML
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
<style>
|
|
29
|
+
/* Theme-aware nav. Falls back to the original dark values when the
|
|
30
|
+
page has no theme tokens (e.g. Swagger/Scalar renderers). */
|
|
31
|
+
.docit-nav {
|
|
32
|
+
display: flex; align-items: center; gap: 8px;
|
|
33
|
+
padding: 6px 16px;
|
|
34
|
+
background: var(--bg-glass, #111827);
|
|
35
|
+
color: var(--text, #ffffff);
|
|
36
|
+
border-bottom: 1px solid var(--border, transparent);
|
|
37
|
+
backdrop-filter: blur(12px) saturate(150%);
|
|
38
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
39
|
+
font-size: 13px; position: sticky; top: 0; z-index: 9999;
|
|
40
|
+
}
|
|
41
|
+
.docit-nav-link {
|
|
42
|
+
color: var(--haze, rgba(255,255,255,0.7)); text-decoration: none;
|
|
43
|
+
padding: 4px 12px; border-radius: 6px;
|
|
44
|
+
transition: all 150ms;
|
|
45
|
+
font-family: inherit;
|
|
46
|
+
font-size: inherit;
|
|
47
|
+
}
|
|
48
|
+
.docit-nav-link:hover {
|
|
49
|
+
color: var(--text, #ffffff); background: var(--bg-option-hover, rgba(255,255,255,0.15));
|
|
50
|
+
}
|
|
51
|
+
.docit-nav-link.active {
|
|
52
|
+
color: var(--ember, #ffffff); background: var(--bg-option-hover, rgba(255,255,255,0.15)); font-weight: 600;
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
<nav class="docit-nav">
|
|
32
56
|
<span style="font-weight: 600; margin-right: auto;">#{title}</span>
|
|
33
|
-
#{
|
|
34
|
-
#{
|
|
57
|
+
<a href="#{ERB::Util.html_escape(nav_paths[:swagger])}" class="docit-nav-link #{'active' if swagger_active}">Swagger</a>
|
|
58
|
+
<a href="#{ERB::Util.html_escape(nav_paths[:scalar])}" class="docit-nav-link #{'active' if scalar_active}">Scalar</a>
|
|
59
|
+
<a href="#{ERB::Util.html_escape(nav_paths[:system])}" class="docit-nav-link #{'active' if system_active}">System</a>
|
|
35
60
|
</nav>
|
|
36
61
|
HTML
|
|
37
62
|
end
|
|
38
63
|
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"color: #fff; text-decoration: none; padding: 4px 12px; border-radius: 4px; background: rgba(255,255,255,0.15); font-weight: 500;"
|
|
43
|
-
else
|
|
44
|
-
"color: rgba(255,255,255,0.7); text-decoration: none; padding: 4px 12px; border-radius: 4px;"
|
|
45
|
-
end
|
|
64
|
+
def spec_url_json
|
|
65
|
+
json_escape(JSON.generate(spec_url))
|
|
66
|
+
end
|
|
46
67
|
|
|
47
|
-
|
|
68
|
+
def system_url_json
|
|
69
|
+
json_escape(JSON.generate(system_url))
|
|
48
70
|
end
|
|
49
71
|
|
|
50
|
-
def
|
|
51
|
-
JSON.generate(
|
|
72
|
+
def system_insights_url_json
|
|
73
|
+
json_escape(JSON.generate(system_insights_url))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def json_escape(json_string)
|
|
77
|
+
json_string.to_s.gsub(/[&<>'\u2028\u2029]/, {
|
|
78
|
+
'&' => '\u0026',
|
|
79
|
+
'<' => '\u003c',
|
|
80
|
+
'>' => '\u003e',
|
|
81
|
+
"'" => '\u0027',
|
|
82
|
+
"\u2028" => '\u2028',
|
|
83
|
+
"\u2029" => '\u2029'
|
|
84
|
+
})
|
|
52
85
|
end
|
|
53
86
|
end
|
|
54
87
|
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docit
|
|
4
|
+
module UI
|
|
5
|
+
class SystemRenderer < BaseRenderer
|
|
6
|
+
def render
|
|
7
|
+
<<~HTML
|
|
8
|
+
<!DOCTYPE html>
|
|
9
|
+
<html lang="en">
|
|
10
|
+
<head>
|
|
11
|
+
<meta charset="UTF-8">
|
|
12
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
13
|
+
<title>#{title} – System Architecture</title>
|
|
14
|
+
<script>
|
|
15
|
+
/* Apply the saved theme before first paint to avoid a flash.
|
|
16
|
+
Default is light; only switch to dark when explicitly chosen. */
|
|
17
|
+
(function() {
|
|
18
|
+
try {
|
|
19
|
+
var saved = localStorage.getItem("docit-theme");
|
|
20
|
+
if (saved === "dark") document.documentElement.setAttribute("data-theme", "dark");
|
|
21
|
+
} catch (e) {}
|
|
22
|
+
})();
|
|
23
|
+
</script>
|
|
24
|
+
<style>#{SystemStyles.css}</style>
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
#{nav_bar(active: :system)}
|
|
28
|
+
<div class="system-shell">
|
|
29
|
+
<header class="system-toolbar">
|
|
30
|
+
<div class="toolbar-group toolbar-brand">
|
|
31
|
+
<div class="brand-mark" aria-hidden="true">
|
|
32
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
|
|
33
|
+
<rect x="2" y="2" width="5" height="5" rx="1.2"/><rect x="9" y="2" width="5" height="5" rx="1.2"/>
|
|
34
|
+
<rect x="2" y="9" width="5" height="5" rx="1.2"/><rect x="9" y="9" width="5" height="5" rx="1.2"/>
|
|
35
|
+
<path d="M7 4.5h2M4.5 7v2M11.5 7v2"/>
|
|
36
|
+
</svg>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="toolbar-title">
|
|
39
|
+
<strong>System Architecture</strong>
|
|
40
|
+
<span>Interactive diagram · drag, zoom, explore</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="toolbar-group toolbar-filters" id="diagram-filters">
|
|
44
|
+
<input id="search" class="control" type="search" placeholder="Search nodes…" autocomplete="off">
|
|
45
|
+
<select id="diagram-section-filter" class="control"><option value="">All sections</option></select>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="toolbar-group toolbar-filters" id="docs-filters" style="display: none;">
|
|
48
|
+
<select id="section-filter" class="control"><option value="">All sections</option></select>
|
|
49
|
+
</div>
|
|
50
|
+
<div class="toolbar-group toolbar-view-mode" style="margin-left: 6px; border-left: 1px solid var(--border); padding-left: 10px; gap: 4px;">
|
|
51
|
+
<button id="view-diagram" class="system-btn active" type="button">Diagram</button>
|
|
52
|
+
<button id="view-list" class="system-btn" type="button">Docs</button>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="toolbar-group toolbar-zoom">
|
|
55
|
+
<button id="zoom-out" class="system-btn icon-btn" type="button" title="Zoom out" aria-label="Zoom out">
|
|
56
|
+
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 8h10"/></svg>
|
|
57
|
+
</button>
|
|
58
|
+
<span id="zoom-level" class="zoom-label">100%</span>
|
|
59
|
+
<button id="zoom-in" class="system-btn icon-btn" type="button" title="Zoom in" aria-label="Zoom in">
|
|
60
|
+
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M8 3v10M3 8h10"/></svg>
|
|
61
|
+
</button>
|
|
62
|
+
<button id="zoom-fit" class="system-btn" type="button">Fit</button>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="toolbar-group toolbar-actions">
|
|
65
|
+
<button id="theme-toggle" class="system-btn icon-btn" type="button" title="Toggle theme" aria-label="Toggle light or dark theme"></button>
|
|
66
|
+
<button id="export-png" class="system-btn" type="button">
|
|
67
|
+
<span class="btn-icon" aria-hidden="true">
|
|
68
|
+
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v8M5 7.5l3 3 3-3M3 13h10"/></svg>
|
|
69
|
+
</span> Export PNG
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
72
|
+
<div class="toolbar-group toolbar-info">
|
|
73
|
+
<span id="stats" class="stat-pill"></span>
|
|
74
|
+
</div>
|
|
75
|
+
</header>
|
|
76
|
+
|
|
77
|
+
<div class="system-body">
|
|
78
|
+
<main class="canvas-wrap" id="canvas-wrap">
|
|
79
|
+
<div id="canvas" class="canvas"></div>
|
|
80
|
+
<div id="legend" class="legend collapsed">
|
|
81
|
+
<button id="legend-toggle" class="legend-toggle" type="button">Legend ▸</button>
|
|
82
|
+
<div id="legend-content" class="legend-content"></div>
|
|
83
|
+
</div>
|
|
84
|
+
</main>
|
|
85
|
+
<main class="stripe-docs-wrap" id="stripe-docs-wrap" style="display: none;">
|
|
86
|
+
<nav class="stripe-sidebar" id="stripe-sidebar"></nav>
|
|
87
|
+
<div class="stripe-content" id="stripe-content"></div>
|
|
88
|
+
<aside class="stripe-detail" id="stripe-detail">
|
|
89
|
+
<button class="stripe-detail-close" id="stripe-detail-close" type="button" aria-label="Close panel">
|
|
90
|
+
<svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>
|
|
91
|
+
</button>
|
|
92
|
+
<div class="stripe-detail-body" id="stripe-detail-body">
|
|
93
|
+
<div class="stripe-detail-empty">
|
|
94
|
+
<div class="stripe-detail-empty-icon" aria-hidden="true">
|
|
95
|
+
<svg width="26" height="26" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 1.5h6L13 5v9.5H3z"/><path d="M9 1.5V5h4"/><path d="M5.5 8.5h5M5.5 11h3"/></svg>
|
|
96
|
+
</div>
|
|
97
|
+
<p>Select an endpoint to see how to call it, or use <strong>Explain section</strong> for an AI overview.</p>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</aside>
|
|
101
|
+
</main>
|
|
102
|
+
<aside id="panel" class="panel"></aside>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div id="toast" class="toast" role="status"></div>
|
|
106
|
+
<script>#{SystemScript.javascript(graph_url: system_url, insights_url: system_insights_url)}</script>
|
|
107
|
+
</body>
|
|
108
|
+
</html>
|
|
109
|
+
HTML
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|