Herzlich willkommen zum SELF-Treffen 2026
vom 24.04. – 26.04.2026 in Halle (Saale)

Beispiel:URL-Decoder.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SVG URL-Decoder</title>

<style>

 textarea {
   width: 100%;
   height: 15em;
   font-family: monospace;
   font-size: 1em;
   margin-bottom: 1rem;
 }
 body {
   max-width: 60em;
   margin: 2rem auto;
   padding: 0 1rem;
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 1em;
 }
 h1 {
   grid-column: 1 / -1;
 }
 div {
   display: grid;
   gap: 1em;
   grid-template-columns: 1fr 2em;
 }
 
 body > div label {
   font: bold 1.25em sans-serif;
 }
 
 textarea, #preview {
   grid-column: 1 / -1;
   aspect-ratio: 2 / 1;
   border: thin solid;
 }
 #preview {
   background-repeat: no-repeat;
   background-size: contain;
   background-position: center;
   display: block;
 }

</style> </head>

<body>

 <label for="encoded">Input URL-encoded</label>
 <textarea id="encoded" placeholder="Füge hier den URL-kodierten SVG-Code ein..."></textarea>
 <label for="css">Input background-image CSS</label>
 <textarea id="css" placeholder="background-image: url("data:image/svg+xml,...");"></textarea>
 <label for="decoded">Dekodiertes SVG</label>
 <button data-copy="decoded">📋</button>
 <textarea id="decoded" placeholder="Hier erscheint der dekodierte SVG-Code..."></textarea>
 <label for="preview">So sieht's aus</label>

<script> document.addEventListener('DOMContentLoaded', function () { const encoded = document.getElementById('encoded'); const css = document.getElementById('css'); const decoded = document.getElementById('decoded'); const preview = document.getElementById('preview');

let lock = false;

// --- Hilfsfunktionen ---

function clearAll() {

 lock = true;
 encoded.value = ;
 css.value = ;
 decoded.value = ;
 preview.style.backgroundImage = ;
 lock = false;

}

function extractEncodedFromCSS(cssText) {

 const match = cssText.match(/url\s*\(\s*["']?data:image\/svg\+xml,([^"')]+)["']?\s*\)/);
 return match ? match[1] : null;

}

function ensureXmlns(svg) {

 if (svg.includes('<svg') && !svg.includes('xmlns=')) {
   return svg.replace(/<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
 }
 return svg;

}

function compactSVG(svg) {

 return svg
   .trim()
   .replace(/\r?\n|\r/g, )
   .replace(/\t+/g, ' ')
   .replace(/\s{2,}/g, ' ')
   .replace(/>\s+</g, '><');

}

function encodeSVG(svg) {

 return encodeURIComponent(svg)
   .replace(/%0A/g, )
   .replace(/%20/g, ' ')
   .replace(/%3D/g, '=')
   .replace(/%3A/g, ':')
   .replace(/%2F/g, '/');

}

function formatSVG(svg) {

 svg = ensureXmlns(svg);
 
 let formatted = svg
   .replace(/></g, '>\n<')
   .replace(/(<svg[^>]*>)/g, '$1\n')
   .replace(/(<\/svg>)/g, '\n$1');
 
 let lines = formatted.split('\n');
 let indent = 0;
 let result = [];
 
 lines.forEach(line => {
   line = line.trim();
   if (!line) return;
   
   if (line.startsWith('</')) {
     indent = Math.max(0, indent - 2);
   }
   
   result.push(' '.repeat(indent) + line);
   
   if (line.startsWith('<') && !line.startsWith('</') && !line.endsWith('/>')) {
     if (!line.match(/<[^>]+>.*<\/[^>]+>/)) {
       indent += 2;
     }
   }
 });
 
 return result.join('\n');

}

// --- Update-Funktionen ---

function updateFromEncoded(enc) {

 try {
   const svg = decodeURIComponent(enc);
   const svgWithXmlns = ensureXmlns(svg);
   const formatted = formatSVG(svg);
   const compact = compactSVG(svgWithXmlns);
   const encWithXmlns = encodeSVG(compact);
   const cssText = `background-image: url("data:image/svg+xml,${encWithXmlns}");`;
   
   decoded.value = formatted;
   css.value = cssText;
   preview.style.backgroundImage = `url("data:image/svg+xml,${encWithXmlns}")`;
 } catch (e) {
   decoded.value = 'Fehler beim Dekodieren: ' + e.message;
   preview.style.backgroundImage = ;
 }

}

function updateFromCSS(cssText) {

 try {
   const enc = extractEncodedFromCSS(cssText);
   if (!enc) {
     throw new Error('Kein gültiger data:image/svg+xml URL gefunden');
   }
   
   const svg = decodeURIComponent(enc);
   const svgWithXmlns = ensureXmlns(svg);
   const formatted = formatSVG(svg);
   const compact = compactSVG(svgWithXmlns);
   const encWithXmlns = encodeSVG(compact);
   
   encoded.value = encWithXmlns;
   decoded.value = formatted;
   preview.style.backgroundImage = `url("data:image/svg+xml,${encWithXmlns}")`;
 } catch (e) {
   decoded.value = 'Fehler beim Dekodieren: ' + e.message;
   preview.style.backgroundImage = ;
 }

}

function updateFromDecoded(svg) {

 try {
   svg = ensureXmlns(svg);
   const compact = compactSVG(svg);
   const enc = encodeSVG(compact);
   const cssText = `background-image: url("data:image/svg+xml,${enc}");`;
   
   encoded.value = enc;
   css.value = cssText;
   preview.style.backgroundImage = `url("data:image/svg+xml,${enc}")`;
 } catch (e) {
   encoded.value = 'Fehler beim Kodieren: ' + e.message;
   preview.style.backgroundImage = ;
 }

}

// --- Event Listeners ---

encoded.addEventListener('input', () => {

 if (lock) return;
 if (!encoded.value.trim()) {
   clearAll();
   return;
 }
 lock = true;
 updateFromEncoded(encoded.value);
 lock = false;

});

css.addEventListener('input', () => {

 if (lock) return;
 if (!css.value.trim()) {
   clearAll();
   return;
 }
 lock = true;
 updateFromCSS(css.value);
 lock = false;

});

decoded.addEventListener('input', () => {

 if (lock) return;
 if (!decoded.value.trim()) {
   clearAll();
   return;
 }
 lock = true;
 updateFromDecoded(decoded.value);
 lock = false;

});

document.querySelectorAll('[data-copy]').forEach(btn => {

 btn.addEventListener('click', () => {
   const id = btn.dataset.copy;
   const el = document.getElementById(id);
   if (!el) return;
   
   const textToCopy = el.value || ;
   if (!textToCopy) return;
   navigator.clipboard.writeText(textToCopy).then(() => {
     const old = btn.textContent;
     btn.textContent = '✓';
     setTimeout(() => btn.textContent = old, 800);
   }).catch(err => {
     console.error('Copy failed:', err);
   });
 });

}); }); </script>

</body> </html>