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,88 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
import colorsys
|
||||
import re
|
||||
from util.logger import logger
|
||||
from auth.token import verify_token
|
||||
|
||||
color_blueprint = Blueprint('color_tool', __name__)
|
||||
|
||||
|
||||
def hex_to_rgb(hex_str):
|
||||
hex_str = hex_str.strip().lstrip('#')
|
||||
if len(hex_str) == 3:
|
||||
hex_str = ''.join(c * 2 for c in hex_str)
|
||||
if len(hex_str) != 6:
|
||||
raise ValueError("Ungültiger HEX-Wert")
|
||||
return int(hex_str[0:2], 16), int(hex_str[2:4], 16), int(hex_str[4:6], 16)
|
||||
|
||||
|
||||
def rgb_to_hex(r, g, b):
|
||||
return f"#{r:02x}{g:02x}{b:02x}"
|
||||
|
||||
|
||||
def rgb_to_hsl(r, g, b):
|
||||
# colorsys uses HLS order (hue, lightness, saturation)
|
||||
h, l, s = colorsys.rgb_to_hls(r / 255, g / 255, b / 255)
|
||||
return round(h * 360), round(s * 100), round(l * 100)
|
||||
|
||||
|
||||
def hsl_to_rgb(h, s, l):
|
||||
# CSS HSL: hue 0-360, saturation 0-100, lightness 0-100
|
||||
r, g, b = colorsys.hls_to_rgb(h / 360, l / 100, s / 100)
|
||||
return round(r * 255), round(g * 255), round(b * 255)
|
||||
|
||||
|
||||
def parse_rgb(value):
|
||||
nums = re.findall(r'\d+', value)
|
||||
if len(nums) < 3:
|
||||
raise ValueError("Ungültiger RGB-Wert")
|
||||
r, g, b = int(nums[0]), int(nums[1]), int(nums[2])
|
||||
if not all(0 <= x <= 255 for x in (r, g, b)):
|
||||
raise ValueError("RGB-Werte müssen zwischen 0 und 255 liegen")
|
||||
return r, g, b
|
||||
|
||||
|
||||
def parse_hsl(value):
|
||||
nums = re.findall(r'[\d.]+', value)
|
||||
if len(nums) < 3:
|
||||
raise ValueError("Ungültiger HSL-Wert")
|
||||
h, s, l = float(nums[0]), float(nums[1]), float(nums[2])
|
||||
if not (0 <= h <= 360 and 0 <= s <= 100 and 0 <= l <= 100):
|
||||
raise ValueError("HSL-Werte außerhalb des gültigen Bereichs")
|
||||
return h, s, l
|
||||
|
||||
|
||||
@color_blueprint.route('/api/color/convert', methods=['POST'])
|
||||
def convert_color():
|
||||
user = verify_token()
|
||||
if not user:
|
||||
return jsonify({"message": "Nicht autorisiert"}), 401
|
||||
try:
|
||||
data = request.get_json(silent=True) or {}
|
||||
value = data.get("value", "").strip()
|
||||
from_format = data.get("from_format", "hex").lower()
|
||||
|
||||
if from_format == "hex":
|
||||
r, g, b = hex_to_rgb(value)
|
||||
elif from_format == "rgb":
|
||||
r, g, b = parse_rgb(value)
|
||||
elif from_format == "hsl":
|
||||
h, s, l = parse_hsl(value)
|
||||
r, g, b = hsl_to_rgb(h, s, l)
|
||||
else:
|
||||
return jsonify({"message": "Unbekanntes Format"}), 400
|
||||
|
||||
hex_val = rgb_to_hex(r, g, b)
|
||||
hue, sat, lig = rgb_to_hsl(r, g, b)
|
||||
|
||||
logger.info(f"Farbe konvertiert von {user['username']}")
|
||||
return jsonify({
|
||||
"hex": hex_val,
|
||||
"rgb": f"rgb({r}, {g}, {b})",
|
||||
"hsl": f"hsl({hue}, {sat}%, {lig}%)",
|
||||
})
|
||||
except ValueError as e:
|
||||
return jsonify({"message": str(e)}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler Farbkonverter: {e}")
|
||||
return jsonify({"message": "Fehler bei der Konvertierung"}), 500
|
||||
Reference in New Issue
Block a user