Skip to content

Commit 6b93db5

Browse files
committed
added supported gem versions table
1 parent 6a067ac commit 6b93db5

File tree

9 files changed

+291
-22
lines changed

9 files changed

+291
-22
lines changed

Gemfile

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,7 @@ gem "bigdecimal"
1818
gem "drb" # For ActiveSupport::TestCase
1919
gem "mutex_m"
2020

21-
# Supported integrations
22-
gem "bugsnag", "~> 6.26"
23-
gem "carrierwave", "~> 3.0"
24-
gem "honeybadger", "~> 5.4"
25-
gem "rollbar", "~> 3.4"
26-
gem "sentry-ruby", "~> 5.15"
27-
gem "shrine", "~> 3.5"
28-
gem "sidekiq", "~> 7.2"
21+
# Sorbet is needed for development
2922
gem "sorbet", "~> 0.5"
3023

3124
# Essential testing gems that don't have Ruby version restrictions

logstruct.gemspec

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
2626
"lib/**/*",
2727
"README.md",
2828
"CHANGELOG.md",
29-
"LICENSE.txt",
29+
"LICENSE",
3030
"*.gemspec",
3131
]
3232
spec.bindir = "exe"
@@ -37,5 +37,15 @@ Gem::Specification.new do |spec|
3737
spec.add_dependency "rails", ">= 7.0"
3838
spec.add_dependency "sorbet-runtime", ">= 0.5"
3939

40+
# Optional integrations
41+
spec.add_development_dependency "bugsnag", "~> 6.26"
42+
spec.add_development_dependency "carrierwave", "~> 3.0"
43+
spec.add_development_dependency "honeybadger", "~> 5.4"
44+
spec.add_development_dependency "rollbar", "~> 3.4"
45+
spec.add_development_dependency "sentry-ruby", "~> 5.15"
46+
spec.add_development_dependency "shrine", "~> 3.5"
47+
spec.add_development_dependency "sidekiq", "~> 7.2"
48+
spec.add_development_dependency "sorbet", "~> 0.5"
49+
4050
spec.metadata["rubygems_mfa_required"] = "true"
4151
end

site/app/docs/layout.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ export default function DocsLayout({
6666
title="Sorbet Types"
6767
active={pathname === '/docs/sorbet-types'}
6868
/>
69+
<DocNavItem
70+
href="/docs/supported-gem-versions"
71+
title="Supported Gem Versions"
72+
active={pathname === '/docs/supported-gem-versions'}
73+
/>
6974
</nav>
7075

7176
<h2 className="mt-6 mb-3 text-lg font-semibold">Reference</h2>
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import { HeadingWithAnchor } from '@/components/heading-with-anchor';
2+
import { EditPageLink } from '@/components/edit-page-link';
3+
import { parseGemspec, GemDependency } from '@/lib/gemspec-parser';
4+
import { Card } from '@/components/ui/card';
5+
import { Callout } from '@/components/ui/callout';
6+
7+
// Make this a server component
8+
export default async function SupportedVersionsPage() {
9+
const dependencies = parseGemspec();
10+
const requiredDeps = dependencies.filter((dep) => dep.type === 'required');
11+
const optionalDeps = dependencies.filter((dep) => dep.type === 'optional');
12+
13+
return (
14+
<div className="space-y-6">
15+
<HeadingWithAnchor id="supported-gem-versions" level={1}>
16+
Supported Gem Versions
17+
</HeadingWithAnchor>
18+
<p className="text-lg text-neutral-600 dark:text-neutral-400">
19+
LogStruct works with the following versions of Rails and various
20+
integration gems.
21+
</p>
22+
23+
<HeadingWithAnchor id="required-dependencies" level={2}>
24+
Required Dependencies
25+
</HeadingWithAnchor>
26+
<p className="text-neutral-600 dark:text-neutral-400 mb-4">
27+
These gems are required for LogStruct to function properly.
28+
</p>
29+
30+
<Card className="p-6">
31+
<div className="relative overflow-x-auto">
32+
<table className="w-full text-sm text-left">
33+
<thead className="text-neutral-700 dark:text-neutral-300 border-b border-neutral-200 dark:border-neutral-700">
34+
<tr>
35+
<th scope="col" className="px-4 py-3 font-medium">
36+
Gem
37+
</th>
38+
<th scope="col" className="px-4 py-3 font-medium">
39+
Version
40+
</th>
41+
<th scope="col" className="px-4 py-3 font-medium">
42+
Description
43+
</th>
44+
</tr>
45+
</thead>
46+
<tbody>
47+
{requiredDeps.map((dep) => (
48+
<tr
49+
key={dep.name}
50+
className="border-b border-neutral-200 dark:border-neutral-700"
51+
>
52+
<td className="px-4 py-4 font-medium">
53+
<a
54+
href={`https://rubygems.org/gems/${dep.name}`}
55+
target="_blank"
56+
rel="noopener noreferrer"
57+
>
58+
{dep.name}
59+
</a>
60+
</td>
61+
<td className="px-4 py-4 font-mono text-xs">{dep.version}</td>
62+
<td className="px-4 py-4">{getGemDescription(dep.name)}</td>
63+
</tr>
64+
))}
65+
</tbody>
66+
</table>
67+
</div>
68+
</Card>
69+
70+
<HeadingWithAnchor id="optional-integrations" level={2}>
71+
Optional Integrations
72+
</HeadingWithAnchor>
73+
<p className="text-neutral-600 dark:text-neutral-400 mb-4">
74+
LogStruct provides seamless integration with these gems, but they are
75+
not required for its core functionality.
76+
</p>
77+
78+
<Callout type="info">
79+
<p>
80+
Feel free to open a PR if you want to add support for an older version
81+
or a different gem.
82+
</p>
83+
</Callout>
84+
85+
<Card className="p-6">
86+
<div className="relative overflow-x-auto">
87+
<table className="w-full text-sm text-left">
88+
<thead className="text-neutral-700 dark:text-neutral-300 border-b border-neutral-200 dark:border-neutral-700">
89+
<tr>
90+
<th scope="col" className="px-4 py-3 font-medium">
91+
Gem
92+
</th>
93+
<th scope="col" className="px-4 py-3 font-medium">
94+
Version
95+
</th>
96+
<th scope="col" className="px-4 py-3 font-medium">
97+
Description
98+
</th>
99+
</tr>
100+
</thead>
101+
<tbody>
102+
{optionalDeps.map((dep) => (
103+
<tr
104+
key={dep.name}
105+
className="border-b border-neutral-200 dark:border-neutral-700"
106+
>
107+
<td className="px-4 py-4 font-medium">
108+
<a
109+
href={`https://rubygems.org/gems/${dep.name}`}
110+
target="_blank"
111+
rel="noopener noreferrer"
112+
>
113+
{dep.name}
114+
</a>
115+
</td>
116+
<td className="px-4 py-4 font-mono text-xs">{dep.version}</td>
117+
<td className="px-4 py-4">{getGemDescription(dep.name)}</td>
118+
</tr>
119+
))}
120+
</tbody>
121+
</table>
122+
</div>
123+
</Card>
124+
125+
<HeadingWithAnchor id="ruby-versions" level={2}>
126+
Ruby Versions
127+
</HeadingWithAnchor>
128+
<p className="text-neutral-600 dark:text-neutral-400">
129+
LogStruct requires Ruby <span className="text-gray-200">3.2.0</span> or
130+
higher.
131+
</p>
132+
133+
<HeadingWithAnchor id="how-to-use" level={2}>
134+
How to Use Integrations
135+
</HeadingWithAnchor>
136+
<p className="text-neutral-600 dark:text-neutral-400">
137+
To use LogStruct with any of the optional integrations, simply add the
138+
desired gem to your Gemfile and LogStruct will automatically detect and
139+
configure it. See the <a href="/docs/integrations">Integrations</a> page
140+
for more details and log examples.
141+
</p>
142+
143+
<EditPageLink />
144+
</div>
145+
);
146+
}
147+
148+
// Helper function to provide descriptions for each gem
149+
function getGemDescription(gemName: string): string {
150+
const descriptions: { [key: string]: string } = {
151+
rails: 'Web application framework',
152+
lograge: "Taming Rails' default request logging",
153+
'sorbet-runtime': "Sorbet's runtime type checking component",
154+
bugsnag: 'Error monitoring and reporting service',
155+
carrierwave: 'File upload solution for Rails',
156+
honeybadger: 'Exception, uptime, and performance monitoring',
157+
rollbar: 'Error tracking and debugging tool',
158+
'sentry-ruby':
159+
'Error tracking that helps developers monitor and fix crashes',
160+
shrine: 'File attachment toolkit for Ruby applications',
161+
sidekiq: 'Simple, efficient background processing for Ruby',
162+
sorbet: 'A type checker for Ruby',
163+
};
164+
165+
return descriptions[gemName] || 'Integration supported by LogStruct';
166+
}

site/components/edit-page-link.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@
33
import Link from 'next/link';
44
import { usePathname } from 'next/navigation';
55

6-
export function EditPageLink() {
6+
interface EditPageLinkProps {
7+
path?: string;
8+
}
9+
10+
export function EditPageLink({ path }: EditPageLinkProps) {
711
const pathname = usePathname();
812

9-
// Convert the path to a GitHub file path
10-
// For /docs/getting-started, the file is at site/app/docs/getting-started/page.tsx
11-
// Handle special case for root paths to avoid double slashes
12-
const filePath =
13-
pathname === '/' ? '/site/app/page.tsx' : `/site/app${pathname}/page.tsx`;
13+
// Allow overriding the path or derive it from the pathname
14+
const derivedPath =
15+
path ??
16+
// Convert the path to a GitHub file path
17+
// For /docs/getting-started, the file is at site/app/docs/getting-started/page.tsx
18+
// Handle special case for root paths to avoid double slashes
19+
(pathname === '/' ? '/site/app/page.tsx' : `/site/app${pathname}/page.tsx`);
1420

1521
// Ensure there are no double slashes in the path
16-
const normalizedPath = filePath.replace(/\/\//g, '/');
22+
const normalizedPath = derivedPath.replace(/\/\//g, '/');
1723

1824
const githubEditUrl = `https://github.com/DocSpring/logstruct/edit/main${normalizedPath}`;
1925

site/components/log-scroller.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export function LogScroller() {
140140

141141
// Different styles based on window state and layout
142142
let perspectiveStyle = {};
143-
143+
144144
if (isMinimized) {
145145
// Minimized state - small window in bottom right
146146
perspectiveStyle = {
@@ -191,7 +191,7 @@ export function LogScroller() {
191191
}
192192

193193
// Mouse over effects - only for non-minimized state
194-
const onMouseOverStyle = isMinimized
194+
const onMouseOverStyle = isMinimized
195195
? {}
196196
: isStandalone
197197
? {
@@ -220,7 +220,7 @@ export function LogScroller() {
220220
};
221221

222222
// Adjust height based on maximized state
223-
const heightClass = isMaximized ? "h-screen" : "h-[375px]";
223+
const heightClass = isMaximized ? 'h-screen' : 'h-[375px]';
224224

225225
return (
226226
<div
@@ -293,7 +293,7 @@ export function LogScroller() {
293293
e.stopPropagation();
294294
isMaximized ? handleRestore() : handleMaximize();
295295
}}
296-
title={isMaximized ? "Click to restore" : "Click to maximize"}
296+
title={isMaximized ? 'Click to restore' : 'Click to maximize'}
297297
></div>
298298
</div>
299299
<div
@@ -308,7 +308,9 @@ export function LogScroller() {
308308
</div>
309309

310310
{/* Container with relative positioning for the scrollable content and overlay */}
311-
<div className={`relative ${isMaximized ? "h-[calc(100vh-30px)]" : "h-[333px]"}`}>
311+
<div
312+
className={`relative ${isMaximized ? 'h-[calc(100vh-30px)]' : 'h-[333px]'}`}
313+
>
312314
{/* Scrollable content */}
313315
<div
314316
ref={scrollerRef}
@@ -342,7 +344,9 @@ export function LogScroller() {
342344
{logs.join('\n\n')}
343345
</SyntaxHighlighter>
344346
) : (
345-
<div className={`w-full ${isMaximized ? 'h-[calc(100vh-100px)]' : 'h-[300px]'}`}></div>
347+
<div
348+
className={`w-full ${isMaximized ? 'h-[calc(100vh-100px)]' : 'h-[300px]'}`}
349+
></div>
346350
)}
347351
</div>
348352
</div>

site/lib/gemspec-parser.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// This module directly parses the gemspec file to extract dependencies
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
export interface GemDependency {
6+
name: string;
7+
version: string;
8+
type: 'required' | 'optional';
9+
}
10+
11+
// Fallback dependencies in case of parsing errors
12+
const fallbackDependencies: GemDependency[] = [
13+
{ name: 'rails', version: '>= 7.0', type: 'required' },
14+
{ name: 'lograge', version: '>= 0.11', type: 'required' },
15+
{ name: 'sorbet-runtime', version: '>= 0.5', type: 'required' },
16+
{ name: 'bugsnag', version: '~> 6.26', type: 'optional' },
17+
{ name: 'carrierwave', version: '~> 3.0', type: 'optional' },
18+
{ name: 'honeybadger', version: '~> 5.4', type: 'optional' },
19+
{ name: 'rollbar', version: '~> 3.4', type: 'optional' },
20+
{ name: 'sentry-ruby', version: '~> 5.15', type: 'optional' },
21+
{ name: 'shrine', version: '~> 3.5', type: 'optional' },
22+
{ name: 'sidekiq', version: '~> 7.2', type: 'optional' },
23+
{ name: 'sorbet', version: '~> 0.5', type: 'optional' },
24+
];
25+
26+
export function parseGemspec(): GemDependency[] {
27+
try {
28+
// Path to the gemspec file (relative to site directory)
29+
const gemspecPath = path.join(process.cwd(), '..', 'logstruct.gemspec');
30+
31+
// Read the gemspec file
32+
const gemspecContent = fs.readFileSync(gemspecPath, 'utf8');
33+
34+
// Define regex patterns to match dependencies
35+
const requiredDepPattern =
36+
/spec\.add_dependency\s+["']([^"']+)["'],\s*["']([^"']+)["']/g;
37+
const optionalDepPattern =
38+
/spec\.add_development_dependency\s+["']([^"']+)["'],\s*["']([^"']+)["']/g;
39+
40+
const dependencies: GemDependency[] = [];
41+
42+
// Extract required dependencies
43+
let match;
44+
while ((match = requiredDepPattern.exec(gemspecContent)) !== null) {
45+
dependencies.push({
46+
name: match[1],
47+
version: match[2],
48+
type: 'required',
49+
});
50+
}
51+
52+
// Extract optional dependencies
53+
while ((match = optionalDepPattern.exec(gemspecContent)) !== null) {
54+
dependencies.push({
55+
name: match[1],
56+
version: match[2],
57+
type: 'optional',
58+
});
59+
}
60+
61+
// If no dependencies were found, use fallback data
62+
if (dependencies.length === 0) {
63+
console.warn('No dependencies found in gemspec, using fallback data');
64+
return fallbackDependencies;
65+
}
66+
67+
// Sort dependencies alphabetically, but put required dependencies first
68+
return dependencies.sort((a, b) => {
69+
if (a.type !== b.type) {
70+
return a.type === 'required' ? -1 : 1;
71+
}
72+
return a.name.localeCompare(b.name);
73+
});
74+
} catch (error) {
75+
console.error('Error parsing gemspec:', error);
76+
// Return the fallback data in case of error
77+
return fallbackDependencies;
78+
}
79+
}

site/types/json.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// This declaration file allows importing JSON files directly in TypeScript
2+
declare module '*.json' {
3+
const value: any;
4+
export default value;
5+
}

0 commit comments

Comments
 (0)