Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/opencode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ jobs:
issues: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
uses: actions/checkout@v4

- uses: ./.github/actions/setup-bun

- name: Run opencode
uses: anomalyco/opencode/github@latest
env:
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
OPENCODE_PERMISSION: '{"bash": "deny"}'
with:
model: opencode/kimi-k2.5-free
58 changes: 49 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,41 @@ Every tool must follow this hierarchy:
2. **Controls**: A distinct row/area for options (selects, inputs) and primary actions (buttons).
3. **Workspace**: The main area, usually split 50/50 between Input and Output panes.

### Layout Toggle (Horizontal/Vertical)
All tools with split-pane layouts **MUST** include a layout toggle button to allow users to switch between horizontal and vertical arrangements.

**Implementation Pattern:**
```jsx
import useLayoutToggle from '../hooks/useLayoutToggle';
import { ToolLayoutToggle } from '../components/ToolUI';

// In component:
const layout = useLayoutToggle({
toolKey: 'unique-tool-key-layout',
defaultDirection: 'horizontal',
showToggle: true,
persist: true
});

// In ToolControls:
<div style={{ marginLeft: 'auto', paddingBottom: '4px' }}>
<ToolLayoutToggle
direction={layout.direction}
onToggle={layout.toggleDirection}
position="controls"
/>
</div>

// On ToolSplitPane:
<ToolSplitPane columnCount={layout.direction === 'horizontal' ? 2 : 1}>
```

**Requirements:**
- Place the toggle button at the end of the `ToolControls` area using `marginLeft: 'auto'`
- Use a unique `toolKey` for each tool to ensure independent persistence
- Always set `persist: true` to remember user's preference
- Update `ToolSplitPane` to dynamically adjust `columnCount` based on layout direction

### Component Specifics

#### Buttons
Expand Down Expand Up @@ -239,7 +274,7 @@ func TestDecode(t *testing.T) {
## 7. Development Setup

### Prerequisites
- **Node.js** (>= 18)
- **Bun** (>= 1.0) - Required for frontend dependencies
- **Go** (>= 1.22)
- **Wails CLI** (`go install github.com/wailsapp/wails/v2/cmd/wails@latest`)

Expand All @@ -249,7 +284,7 @@ func TestDecode(t *testing.T) {
git clone https://github.com/vuon9/dev-toolbox.git
cd dev-toolbox

# Install frontend dependencies (using Bun)
# Install dependencies (using Bun)
bun install
```

Expand Down Expand Up @@ -304,7 +339,7 @@ bun run format
Follow this step‑by‑step guide to add a new tool component:

1. **Create Component File**
- Create a new `.jsx` file in `frontend/src/tools/` (e.g., `MyNewTool.jsx`).
- Create a new `.jsx` file in `src/pages/` (e.g., `MyNewTool.jsx`).
- Use the existing tool components as reference (e.g., `JwtDebugger.jsx`).

2. **Implement the Tool**
Expand All @@ -316,15 +351,19 @@ Follow this step‑by‑step guide to add a new tool component:
- Ensure input/output panes are symmetrical, have monospace fonts, and include copy buttons.

3. **Add Route**
- Open `frontend/src/App.jsx`.
- Open `src/App.jsx`.
- Import your new component.
- Add a route entry in the `routes` array:
- Add the component to the `renderTool()` switch statement:
```jsx
{ path: '/my-new-tool', element: <MyNewTool /> }
case 'my-new-tool': return <MyNewTool />;
```

4. **Update Sidebar** (Optional)
- If the tool should appear in the sidebar, add an entry in `frontend/src/App.jsx` within the `sidebarItems` array.
4. **Update Sidebar**
- Open `src/components/Sidebar.jsx`.
- Add an entry to the `tools` array:
```jsx
{ id: 'my-new-tool', name: 'My New Tool', icon: '🛠️' }
```

5. **Test the Tool**
- Run `wails dev` to verify the tool works correctly.
Expand Down Expand Up @@ -443,11 +482,12 @@ These guidelines are intended for AI assistants (like opencode) working on this
1. **Run linting & formatting** – Execute any available lint/format commands (see section 8).
2. **Test the tool** – Verify functionality with `wails dev`.
3. **Update `TOOL_STATUS.md`** – Update the tool's status and add completion notes (mark as 🟢 Done when complete).
4. **Update `README.md`** – **Whenever TOOL_STATUS.md is updated, review README.md to ensure consistency**:
4. **Update `README.md`** – **REQUIRED: Whenever TOOL_STATUS.md is updated, README.md MUST also be updated to ensure consistency**:
- Add new tools to the feature table
- Remove deprecated tools
- Update descriptions if features changed
- Keep the tool count/feature list in sync
- **This is mandatory** - never update TOOL_STATUS.md without checking/updating README.md
5. **Commit changes** – Use descriptive commit messages that reference the tool name and changes made.

### Important Notes
Expand Down
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,10 @@ The central hub with 45+ algorithms across 5 categories:
| **Code Formatter** | Format and minify JSON, XML, HTML, SQL, CSS, and JavaScript with advanced filtering support (jq for JSON, XPath for XML, CSS selectors for HTML) |
| **RegExp Tester** | Test regular expressions with real-time matching |
| **Unix Time Converter** | Convert between Unix timestamps and human-readable dates |
| **String Case Converter** | Convert between camelCase, snake_case, PascalCase, etc. |
| **String Utilities** | Sort/Dedupe lines, Case conversion (camelCase, snake_case, etc.), String Inspector |
| **Cron Job Parser** | Parse and explain cron expressions |
| **Text Diff Checker** | Compare two text blocks and highlight differences |
| **Line Sort / Dedupe** | Sort lines, remove duplicates, trim whitespace |
| **String Inspector** | Count characters, words, lines, bytes, and sentences |
| **PHP Serializer** | PHP serialization/unserialization |
| **URL Tools** | Parse URLs, extract components |
| **Number Converter** | Convert between Decimal, Hex, Octal, and Binary |

## Installation

Expand All @@ -62,7 +59,7 @@ Download the latest release for your platform from the [Releases](https://github
### Build from Source

**Prerequisites:**
- Node.js (>= 18)
- Bun (>= 1.0) - Required for frontend dependencies
- Go (>= 1.22)
- Wails CLI: `go install github.com/wailsapp/wails/v2/cmd/wails@latest`

Expand Down
53 changes: 0 additions & 53 deletions TOOL_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,59 +26,6 @@ This document tracks the refactoring and development status of each tool compone
| **TextDiffChecker** | 🟡 In Progress | Refactored with enhanced features. Features: Diff mode switcher (Lines/Words/Chars), auto-compare on input change, Clear button, improved diff view with color coding, layout toggle. | Updated 2026-01-31 |
| **UnixTimeConverter** | 🟡 In Progress | Refactored with new features. Features: Relative time display (e.g., "2 hours ago"), split-pane layout (ISO 8601 / Local), "Now" button with icon, layout toggle, auto-initialization with current time. | Updated 2026-01-31 |

### Removed Tools (Consolidated)

| Tool | Replacement | Reason |
|------|-------------|--------|
| JsonFormatter | CodeFormatter | Unified formatting tool |
| SqlFormatter | CodeFormatter | Unified formatting tool |
| UrlTools | TextConverter | URL encode/decode functionality |
| UrlParser | TextConverter | URL parsing functionality |
| UrlEncoder | TextConverter | URL encoding functionality |
| PhpSerializer | - | Removed - low usage |
| PhpJsonConverter | - | Removed - low usage |
| LineSortDedupe | StringUtilities | Consolidated into StringUtilities |
| StringCaseConverter | StringUtilities | Consolidated into StringUtilities |
| StringInspector | StringUtilities | Consolidated into StringUtilities |
| NumberBaseConverter | NumberConverter | Renamed and refactored |
| TextBasedConverter | TextConverter | Renamed for clarity |

---

## Final Tool Count: 11 Tools

1. **Text Converter** - Encoding, encryption, hashing, escaping
2. **String Utilities** - Sort/Dedupe, Case conversion, Inspector
3. **Number Converter** - Decimal, Hex, Octal, Binary conversions
4. **Unix Time Converter** - Timestamp conversions with relative time
5. **JWT Debugger** - JWT encode/decode/verify
6. **RegExp Tester** - Regular expression testing
7. **Cron Job Parser** - Cron expression parsing
8. **Text Diff Checker** - Text comparison
9. **Code Formatter** - JSON, XML, HTML, SQL, CSS, JS formatting
10. **Barcode Generator** - QR codes and barcodes
11. **Data Generator** - Mock data generation

---

## Refactoring Checklist

When refactoring a tool, ensure:

- [x] Uses **Carbon Design System** components (`@carbon/react`)
- [x] All colors use `var(--cds-*)` tokens, no hardcoded hex values
- [x] Implements **useReducer** for state management (not multiple useState hooks)
- [x] Uses **useCallback** for memoized functions
- [x] Follows **DRY principle** - no duplicated components/logic
- [x] Has proper **ToolHeader** with title and description
- [x] Input/Output panes are symmetrical and use **Carbon TextArea**
- [x] All buttons properly spaced (gap: 1rem)
- [x] Copy buttons present on all output/data panes
- [x] Monospace font for data (`'IBM Plex Mono', monospace`)
- [x] Proper flex layout for responsive sizing
- [x] No unused imports or variables
- [x] Code compiles without errors or warnings

---

## How to Update This File
Expand Down
20 changes: 18 additions & 2 deletions src/pages/BarcodeGenerator.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState, useCallback, useRef } from 'react';
import { Button, Dropdown, InlineLoading } from '@carbon/react';
import { Renew, Download } from '@carbon/icons-react';
import { ToolHeader, ToolPane, ToolSplitPane } from '../components/ToolUI';
import { ToolHeader, ToolPane, ToolSplitPane, ToolLayoutToggle } from '../components/ToolUI';
import useLayoutToggle from '../hooks/useLayoutToggle';
import { Backend } from '../utils/backendBridge';

const BARCODE_STANDARDS = [
Expand Down Expand Up @@ -119,6 +120,13 @@ export default function BarcodeGenerator() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');

const layout = useLayoutToggle({
toolKey: 'barcode-generator-layout',
defaultDirection: 'horizontal',
showToggle: true,
persist: true
});

// Track what was last generated to prevent duplicate generation
const lastGeneratedParams = useRef({ content: '', standard: 'QR', size: 256, level: 'M' });

Expand Down Expand Up @@ -288,9 +296,17 @@ export default function BarcodeGenerator() {
>
Generate
</Button>

<div style={{ marginLeft: 'auto', paddingBottom: '4px' }}>
<ToolLayoutToggle
direction={layout.direction}
onToggle={layout.toggleDirection}
position="controls"
/>
</div>
</div>

<ToolSplitPane columnCount={2}>
<ToolSplitPane columnCount={layout.direction === 'horizontal' ? 2 : 1}>
{/* Input Pane */}
<ToolPane
label="Content"
Expand Down
20 changes: 18 additions & 2 deletions src/pages/CodeFormatter/index.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState, useCallback, useEffect } from 'react';
import { Button, Select, SelectItem, TextInput, IconButton } from '@carbon/react';
import { Code, TrashCan, Close } from '@carbon/icons-react';
import { ToolHeader, ToolControls, ToolPane, ToolSplitPane } from '../../components/ToolUI';
import { ToolHeader, ToolControls, ToolPane, ToolSplitPane, ToolLayoutToggle } from '../../components/ToolUI';
import useLayoutToggle from '../../hooks/useLayoutToggle';
import { Backend } from '../../utils/backendBridge';

const FORMATTERS = [
Expand Down Expand Up @@ -39,6 +40,13 @@ export default function CodeFormatter() {
const [error, setError] = useState(null);
const [isMinified, setIsMinified] = useState(false);

const layout = useLayoutToggle({
toolKey: 'code-formatter-layout',
defaultDirection: 'horizontal',
showToggle: true,
persist: true
});

// Persist state
useEffect(() => {
localStorage.setItem(STORAGE_KEY, JSON.stringify({
Expand Down Expand Up @@ -206,6 +214,14 @@ export default function CodeFormatter() {
<Button onClick={minify} kind="secondary" size='md'>
Minify
</Button>

<div style={{ marginLeft: 'auto', paddingBottom: '4px' }}>
<ToolLayoutToggle
direction={layout.direction}
onToggle={layout.toggleDirection}
position="controls"
/>
</div>
</div>
</ToolControls>

Expand All @@ -221,7 +237,7 @@ export default function CodeFormatter() {
</div>
)}

<ToolSplitPane>
<ToolSplitPane columnCount={layout.direction === 'horizontal' ? 2 : 1}>
<ToolPane
label="Input"
value={input}
Expand Down
83 changes: 0 additions & 83 deletions src/pages/CsvJsonConverter.jsx

This file was deleted.

Loading