Add 6 new tools: Hasher, Base64, JWT Decoder, Password Gen, Timestamp, Text Diff
- backend/tools/hasher.py: POST /api/hash/sha256 and /api/hash/bcrypt (bcrypt added to requirements) - backend/tools/base64tool.py: POST /api/base64/encode and /api/base64/decode - backend/tools/jwtdecoder.py: POST /api/jwt/decode (signature verification disabled) - backend/tools/passwordgen.py: POST /api/password/generate with charset and length options - backend/tools/timestamp.py: POST /api/timestamp/convert (unix<->date, ISO 8601 + German format) - backend/tools/textdiff.py: POST /api/text/diff returning structured added/removed/unchanged lines - All blueprints registered in app.py and tools/__init__.py - React components with copy button, dark/light mode support via CSS variables - ToolOverview rebuilt as card grid; App.jsx routes added for all tools Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { useState } from 'react';
|
||||
import axios from '../services/api';
|
||||
|
||||
const diffColors = {
|
||||
added: { bg: 'rgba(34, 197, 94, 0.12)', text: '#22c55e', prefix: '+ ' },
|
||||
removed: { bg: 'rgba(239, 68, 68, 0.12)', text: '#ef4444', prefix: '- ' },
|
||||
unchanged: { bg: 'transparent', text: 'var(--muted)', prefix: ' ' },
|
||||
};
|
||||
|
||||
function TextDiffTool() {
|
||||
const [text1, setText1] = useState('');
|
||||
const [text2, setText2] = useState('');
|
||||
const [diff, setDiff] = useState(null);
|
||||
|
||||
const compare = async () => {
|
||||
try {
|
||||
const res = await axios.post('/api/text/diff', { text1, text2 });
|
||||
setDiff(res.data.diff);
|
||||
} catch {
|
||||
alert('Fehler beim Vergleich');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h2>Text Diff</h2>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
|
||||
<div>
|
||||
<p className="muted" style={{ marginBottom: '6px', fontWeight: 600 }}>Text A</p>
|
||||
<textarea
|
||||
rows={10}
|
||||
value={text1}
|
||||
onChange={(e) => { setText1(e.target.value); setDiff(null); }}
|
||||
placeholder="Originaltext eingeben..."
|
||||
style={{ resize: 'vertical', fontFamily: 'monospace', fontSize: '0.875rem' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="muted" style={{ marginBottom: '6px', fontWeight: 600 }}>Text B</p>
|
||||
<textarea
|
||||
rows={10}
|
||||
value={text2}
|
||||
onChange={(e) => { setText2(e.target.value); setDiff(null); }}
|
||||
placeholder="Geänderter Text eingeben..."
|
||||
style={{ resize: 'vertical', fontFamily: 'monospace', fontSize: '0.875rem' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button onClick={compare}>Vergleichen</button>
|
||||
|
||||
{diff !== null && (
|
||||
<div style={{ marginTop: '16px', border: '1px solid var(--border)', borderRadius: '12px', overflow: 'hidden' }}>
|
||||
{diff.length === 0 ? (
|
||||
<p style={{ padding: '12px 14px', color: 'var(--muted)', margin: 0 }}>Keine Unterschiede gefunden.</p>
|
||||
) : (
|
||||
diff.map((line, i) => {
|
||||
const c = diffColors[line.type] || diffColors.unchanged;
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
padding: '2px 14px',
|
||||
background: c.bg,
|
||||
color: c.text,
|
||||
fontFamily: 'monospace',
|
||||
fontSize: '0.875rem',
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-all',
|
||||
borderLeft: `3px solid ${line.type !== 'unchanged' ? c.text : 'transparent'}`,
|
||||
}}
|
||||
>
|
||||
{c.prefix}{line.text}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TextDiffTool;
|
||||
Reference in New Issue
Block a user