From 7ceb3004cdc889ca852b2bf8ace349b268c528b8 Mon Sep 17 00:00:00 2001 From: niranjanjangir Date: Thu, 11 Jun 2026 16:38:48 +0530 Subject: [PATCH 1/2] feat: add switch to toggle b/w html & jsx compatible code --- index.html | 4 ++ index.js | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 2aa9fa6..7586017 100644 --- a/index.html +++ b/index.html @@ -61,6 +61,10 @@

Download SVG image +
+ + +
diff --git a/index.js b/index.js index 43b1ce4..1a10c49 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,7 @@ import './codemirror/mode/xml/xml.js' const download = document.getElementById('download') const copy = document.getElementById('copy') const previewBg = document.getElementById('preview-bg') + const react = document.getElementById('react-checkbox') let code = '' let theme = 'default' @@ -34,15 +35,123 @@ import './codemirror/mode/xml/xml.js' return 'data:image/svg+xml,' + encodeURIComponent(svgAsXML) } + const ATTRIBUTE_MAPPING = { + 'class': 'className', + 'accent-height': 'accentHeight', + 'alignment-baseline': 'alignmentBaseline', + 'arabic-form': 'arabicForm', + 'baseline-shift': 'baselineShift', + 'cap-height': 'capHeight', + 'clip-path': 'clipPath', + 'clip-rule': 'clipRule', + 'color-interpolation': 'colorInterpolation', + 'color-interpolation-filters': 'colorInterpolationFilters', + 'color-profile': 'colorProfile', + 'color-rendering': 'colorRendering', + 'dominant-baseline': 'dominantBaseline', + 'enable-background': 'enableBackground', + 'fill-opacity': 'fillOpacity', + 'fill-rule': 'fillRule', + 'flood-color': 'floodColor', + 'flood-opacity': 'floodOpacity', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-size-adjust': 'fontSizeAdjust', + 'font-stretch': 'fontStretch', + 'font-style': 'fontStyle', + 'font-variant': 'fontVariant', + 'font-weight': 'fontWeight', + 'glyph-name': 'glyphName', + 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', + 'glyph-orientation-vertical': 'glyphOrientationVertical', + 'horiz-adv-x': 'horizAdvX', + 'horiz-origin-x': 'horizOriginX', + 'image-rendering': 'imageRendering', + 'letter-spacing': 'letterSpacing', + 'lighting-color': 'lightingColor', + 'marker-end': 'markerEnd', + 'marker-mid': 'markerMid', + 'marker-start': 'markerStart', + 'overline-position': 'overlinePosition', + 'overline-thickness': 'overlineThickness', + 'paint-order': 'paintOrder', + 'panose-1': 'panose1', + 'pointer-events': 'pointerEvents', + 'rendering-intent': 'renderingIntent', + 'shape-rendering': 'shapeRendering', + 'stop-color': 'stopColor', + 'stop-opacity': 'stopOpacity', + 'strikethrough-position': 'strikethroughPosition', + 'strikethrough-thickness': 'strikethroughThickness', + 'stroke-dasharray': 'strokeDasharray', + 'stroke-dashoffset': 'strokeDashoffset', + 'stroke-linecap': 'strokeLinecap', + 'stroke-linejoin': 'strokeLinejoin', + 'stroke-miterlimit': 'strokeMiterlimit', + 'stroke-opacity': 'strokeOpacity', + 'stroke-width': 'strokeWidth', + 'text-anchor': 'textAnchor', + 'text-decoration': 'textDecoration', + 'text-rendering': 'textRendering', + 'underline-position': 'underlinePosition', + 'underline-thickness': 'underlineThickness', + 'unicode-bidi': 'unicodeBidi', + 'unicode-range': 'unicodeRange', + 'units-per-em': 'unitsPerEm', + 'v-alphabetic': 'vAlphabetic', + 'v-hanging': 'vHanging', + 'v-ideographic': 'vIdeographic', + 'v-mathematical': 'vMathematical', + 'vector-effect': 'vectorEffect', + 'vert-adv-y': 'vertAdvY', + 'vert-origin-x': 'vertOriginX', + 'vert-origin-y': 'vertOriginY', + 'word-spacing': 'wordSpacing', + 'writing-mode': 'writingMode', + 'x-height': 'xHeight', + 'xlink:actuate': 'xlinkActuate', + 'xlink:arcrole': 'xlinkArcrole', + 'xlink:href': 'xlinkHref', + 'xlink:role': 'xlinkRole', + 'xlink:show': 'xlinkShow', + 'xlink:title': 'xlinkTitle', + 'xlink:type': 'xlinkType', + 'xml:base': 'xmlBase', + 'xml:lang': 'xmlLang', + 'xml:space': 'xmlSpace', + 'xmlns:xlink': 'xmlnsXlink' + } + + function htmlToJsx(htmlStr) { + let result = htmlStr + for (const [htmlAttr, jsxAttr] of Object.entries(ATTRIBUTE_MAPPING)) { + const escapedHtmlAttr = htmlAttr.replace(/:/g, '\\:') + const regex = new RegExp(`\\b${escapedHtmlAttr}\\s*=`, 'g') + result = result.replace(regex, `${jsxAttr}=`) + } + return result + } + + function jsxToHtml(jsxStr) { + let result = jsxStr + for (const [htmlAttr, jsxAttr] of Object.entries(ATTRIBUTE_MAPPING)) { + const regex = new RegExp(`\\b${jsxAttr}\\s*=`, 'g') + result = result.replace(regex, `${htmlAttr}=`) + } + return result + } + function readFile(event) { const value = (event.target && event.target.result) || event if (event.target && event.target.result) { - editor.setValue(value) + const editorValue = react.checked ? htmlToJsx(value) : value + editor.setValue(editorValue) } - const fragment = document.createRange().createContextualFragment(value) + const standardSvg = react.checked ? jsxToHtml(value) : value + const fragment = document.createRange().createContextualFragment(standardSvg) if (fragment.querySelector('svg')) { - preview.innerHTML = value - code = value + preview.innerHTML = standardSvg + code = react.checked ? htmlToJsx(standardSvg) : standardSvg copy.removeAttribute('disabled') const svg = preview.querySelector('svg') download.href = svgDataURL(svg) @@ -81,10 +190,21 @@ import './codemirror/mode/xml/xml.js' preview.style.background = e?.target?.value || '#e3e3e3' } + function handleReactChange() { + const value = editor.getValue() + if (!value) return + if (react.checked) { + editor.setValue(htmlToJsx(value)) + } else { + editor.setValue(jsxToHtml(value)) + } + } + input.addEventListener('change', changeFile) copy.addEventListener('click', handleCopy) download.addEventListener('click', handleDownload) previewBg.addEventListener('input', handlePreviewBgChange) + react.addEventListener('change', handleReactChange) handlePreviewBgChange() })() \ No newline at end of file From 014b57a10a6b08023955cde10d5436e91443f99a Mon Sep 17 00:00:00 2001 From: Niranjan Jangir Date: Tue, 16 Jun 2026 17:32:57 +0530 Subject: [PATCH 2/2] fix lint errors --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 1a10c49..5bb4525 100644 --- a/index.js +++ b/index.js @@ -124,7 +124,7 @@ import './codemirror/mode/xml/xml.js' function htmlToJsx(htmlStr) { let result = htmlStr - for (const [htmlAttr, jsxAttr] of Object.entries(ATTRIBUTE_MAPPING)) { + for (const [ htmlAttr, jsxAttr ] of Object.entries(ATTRIBUTE_MAPPING)) { const escapedHtmlAttr = htmlAttr.replace(/:/g, '\\:') const regex = new RegExp(`\\b${escapedHtmlAttr}\\s*=`, 'g') result = result.replace(regex, `${jsxAttr}=`) @@ -134,7 +134,7 @@ import './codemirror/mode/xml/xml.js' function jsxToHtml(jsxStr) { let result = jsxStr - for (const [htmlAttr, jsxAttr] of Object.entries(ATTRIBUTE_MAPPING)) { + for (const [ htmlAttr, jsxAttr ] of Object.entries(ATTRIBUTE_MAPPING)) { const regex = new RegExp(`\\b${jsxAttr}\\s*=`, 'g') result = result.replace(regex, `${htmlAttr}=`) }