Skip to content

Commit a6b4ed5

Browse files
committed
Initial commit
0 parents  commit a6b4ed5

File tree

3 files changed

+455
-0
lines changed

3 files changed

+455
-0
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module bash-script-tools
2+
3+
go 1.21

index.html

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Bash Script Formatter & Checker</title>
7+
<script src="https://cdn.tailwindcss.com"></script>
8+
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.2/ace.js"></script>
9+
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.2/mode-sh.min.js"></script>
10+
<style>
11+
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap");
12+
13+
body {
14+
font-family: "Inter", sans-serif;
15+
}
16+
17+
#editor {
18+
height: 400px;
19+
border: 1px solid #27272a;
20+
border-radius: 0.5rem;
21+
}
22+
23+
/* Loading spinner */
24+
.htmx-request .htmx-indicator {
25+
display: inline;
26+
}
27+
28+
.htmx-indicator {
29+
display: none;
30+
}
31+
</style>
32+
</head>
33+
<body class="bg-background min-h-screen">
34+
<div class="container mx-auto px-4 py-8 max-w-4xl">
35+
<div class="mb-8">
36+
<h1 class="text-3xl font-semibold mb-2">Bash Script Tools</h1>
37+
<p class="text-muted-foreground">Format and check your bash scripts</p>
38+
</div>
39+
40+
<div class="space-y-4">
41+
<!-- Code Editor -->
42+
<div>
43+
<label class="block text-sm font-medium mb-2">Script</label>
44+
<div id="editor">#!/bin/bash echo "Paste your bash script here..."</div>
45+
</div>
46+
47+
<!-- Action Buttons -->
48+
<div class="flex gap-3">
49+
<button
50+
onclick="formatCode()"
51+
class="inline-flex items-center px-4 py-2 bg-zinc-900 text-zinc-100 rounded-md hover:bg-zinc-800 focus:outline-none focus:ring-2 focus:ring-zinc-700 transition-colors font-medium text-sm border border-zinc-800"
52+
>
53+
<span>Format</span>
54+
<svg
55+
id="format-spinner"
56+
class="htmx-indicator ml-2 animate-spin h-4 w-4"
57+
xmlns="http://www.w3.org/2000/svg"
58+
fill="none"
59+
viewBox="0 0 24 24"
60+
>
61+
<circle
62+
class="opacity-25"
63+
cx="12"
64+
cy="12"
65+
r="10"
66+
stroke="currentColor"
67+
stroke-width="4"
68+
></circle>
69+
<path
70+
class="opacity-75"
71+
fill="currentColor"
72+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
73+
></path>
74+
</svg>
75+
</button>
76+
77+
<button
78+
onclick="checkCode()"
79+
class="inline-flex items-center px-4 py-2 bg-zinc-900 text-zinc-100 rounded-md hover:bg-zinc-800 focus:outline-none focus:ring-2 focus:ring-zinc-700 transition-colors font-medium text-sm border border-zinc-800"
80+
>
81+
<span>Shellcheck</span>
82+
<svg
83+
id="check-spinner"
84+
class="htmx-indicator ml-2 animate-spin h-4 w-4"
85+
xmlns="http://www.w3.org/2000/svg"
86+
fill="none"
87+
viewBox="0 0 24 24"
88+
>
89+
<circle
90+
class="opacity-25"
91+
cx="12"
92+
cy="12"
93+
r="10"
94+
stroke="currentColor"
95+
stroke-width="4"
96+
></circle>
97+
<path
98+
class="opacity-75"
99+
fill="currentColor"
100+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
101+
></path>
102+
</svg>
103+
</button>
104+
</div>
105+
106+
<!-- Output Box -->
107+
<div>
108+
<label class="block text-sm font-medium mb-2">ShellCheck Output</label>
109+
<div
110+
id="output-box"
111+
class="w-full min-h-[200px] px-4 py-3 bg-black text-zinc-100 border border-zinc-800 rounded-lg overflow-auto text-xs"
112+
>
113+
<div class="text-xs text-zinc-500">Click Shellcheck to see results</div>
114+
</div>
115+
</div>
116+
</div>
117+
118+
<div class="mt-8 pt-6 border-t border-zinc-800">
119+
<p class="text-sm text-zinc-500">
120+
<strong>Format</strong> uses
121+
<code class="px-1 py-0.5 bg-zinc-900 rounded text-xs">shfmt</code> to format your bash
122+
script. <strong>Shellcheck</strong> uses
123+
<code class="px-1 py-0.5 bg-zinc-900 rounded text-xs">shellcheck</code> to find potential
124+
issues.
125+
</p>
126+
</div>
127+
</div>
128+
129+
<script>
130+
// Configure Ace Editor
131+
ace.config.set("basePath", "https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.2/");
132+
133+
const editor = ace.edit("editor");
134+
editor.session.setMode("ace/mode/sh");
135+
editor.setOptions({
136+
fontSize: "14px",
137+
showPrintMargin: false,
138+
showGutter: true,
139+
highlightGutterLine: true,
140+
});
141+
142+
function showSpinner(id) {
143+
document.getElementById(id).style.display = "inline";
144+
}
145+
146+
function hideSpinner(id) {
147+
document.getElementById(id).style.display = "none";
148+
}
149+
150+
async function formatCode() {
151+
const code = editor.getValue();
152+
showSpinner("format-spinner");
153+
154+
try {
155+
const response = await fetch("/format", {
156+
method: "POST",
157+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
158+
body: "code=" + encodeURIComponent(code),
159+
});
160+
161+
const formattedCode = await response.text();
162+
const cursor = editor.getCursorPosition();
163+
editor.setValue(formattedCode, -1);
164+
editor.moveCursorToPosition(cursor);
165+
} catch (error) {
166+
console.error("Format error:", error);
167+
} finally {
168+
hideSpinner("format-spinner");
169+
}
170+
}
171+
172+
async function checkCode() {
173+
const code = editor.getValue();
174+
showSpinner("check-spinner");
175+
editor.session.clearAnnotations();
176+
177+
try {
178+
const response = await fetch("/shellcheck", {
179+
method: "POST",
180+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
181+
body: "code=" + encodeURIComponent(code),
182+
});
183+
184+
const result = await response.json();
185+
document.getElementById("output-box").innerHTML = result.html;
186+
187+
if (result.annotations && result.annotations.length > 0) {
188+
editor.session.setAnnotations(result.annotations);
189+
}
190+
} catch (error) {
191+
console.error("Shellcheck error:", error);
192+
document.getElementById("output-box").innerHTML =
193+
'<div class="text-sm text-red-600">Error running shellcheck</div>';
194+
} finally {
195+
hideSpinner("check-spinner");
196+
}
197+
}
198+
</script>
199+
</body>
200+
</html>

0 commit comments

Comments
 (0)