Add 5 new tools: QR-Code, Markdown, Color Converter, JSON Formatter, Regex Tester
- backend/tools/qrcode_gen.py: POST /api/qrcode/generate, returns base64 PNG (qrcode[pil]) - backend/tools/markdown_tool.py: POST /api/markdown/render, extensions: tables/fenced_code/nl2br - backend/tools/colorconverter.py: POST /api/color/convert, HEX/RGB/HSL via colorsys (no deps) - backend/tools/jsonformatter.py: POST /api/json/format, returns formatted JSON with line/col errors - backend/tools/regextester.py: POST /api/regex/test, flags i/m/s, returns matches with positions - QrCodeTool.jsx: generate + download PNG button - MarkdownTool.jsx: split editor/preview, debounce 500ms, white preview bg - ColorConverterTool.jsx: color swatch preview, per-format copy buttons - JsonFormatterTool.jsx: indent toggle 2/4, pre result box with copy - RegexTesterTool.jsx: debounce 400ms, yellow match highlighting, flag checkboxes - All blueprints registered in app.py; qrcode[pil] + markdown added to requirements.txt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import axios from '../services/api';
|
||||
|
||||
function MarkdownTool() {
|
||||
const [text, setText] = useState('');
|
||||
const [html, setHtml] = useState('');
|
||||
const timer = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
clearTimeout(timer.current);
|
||||
if (!text) { setHtml(''); return; }
|
||||
timer.current = setTimeout(async () => {
|
||||
try {
|
||||
const res = await axios.post('/api/markdown/render', { text });
|
||||
setHtml(res.data.html);
|
||||
} catch {
|
||||
setHtml('<p style="color:red">Fehler beim Rendern</p>');
|
||||
}
|
||||
}, 500);
|
||||
return () => clearTimeout(timer.current);
|
||||
}, [text]);
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h2>Markdown Editor</h2>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
|
||||
<div>
|
||||
<p className="muted" style={{ marginBottom: '6px', fontWeight: 600 }}>Editor</p>
|
||||
<textarea
|
||||
rows={20}
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
placeholder="Markdown eingeben..."
|
||||
style={{ resize: 'vertical', fontFamily: 'monospace', fontSize: '0.875rem' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="muted" style={{ marginBottom: '6px', fontWeight: 600 }}>Vorschau</p>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: html || '<span style="color:#999">Vorschau erscheint hier...</span>' }}
|
||||
style={{
|
||||
minHeight: '460px',
|
||||
padding: '16px',
|
||||
background: '#ffffff',
|
||||
color: '#0f172a',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: '12px',
|
||||
overflowY: 'auto',
|
||||
lineHeight: 1.7,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MarkdownTool;
|
||||
Reference in New Issue
Block a user