ما هو تحويل HTML إلى JSX؟
تحويل HTML إلى JSX هو عملية تحويل ترميز HTML القياسي إلى صيغة JSX التي تستطيع مكونات React عرضها. تبدو JSX مشابهة لـ HTML، لكنها تتبع قواعد وتسميات JavaScript. تُعاد تسمية السمات؛ فـ class تصبح className، وfor تصبح htmlFor، وتُستبدَل سلاسل style النصية بكائنات JavaScript. هذه التغييرات ضرورية لأن JSX تُترجَم إلى استدعاءات React.createElement()، حيث يجب أن تطابق أسماء السمات أسماء خصائص DOM API لا أسماء سمات HTML.
التعيين بين سمات HTML وخصائص JSX محدَّد في توثيق عناصر DOM الخاصة بـ React. تستخدم React camelCase للسمات متعددة الكلمات (فـ tabindex تصبح tabIndex، وmaxlength تصبح maxLength)، لأن معرّفات JavaScript لا تقبل الواصلات. كما يجب أن تتضمن الوسوم ذاتية الإغلاق مثل <img> و<br> و<input> شرطة مائلة في النهاية ضمن JSX (مثل <img />) لأن JSX تتبع قواعد XML حيث يجب إغلاق كل وسم صراحةً.
إلى جانب إعادة تسمية السمات، يتعامل تحويل HTML إلى JSX مع الأنماط المضمّنة والتعليقات. تستخدم سمات style في HTML صيغة CSS كسلسلة نصية (مثل style="color: red; font-size: 14px")، بينما تتوقع JSX كائن JavaScript بأسماء خصائص camelCase (مثل style={{ color: 'red', fontSize: '14px' }})). وتُحوَّل تعليقات HTML (<!-- '-->') إلى تعليقات تعبيرات JSX ({/* */}). أي إغفال لهذه التحويلات يُنتج أخطاء وقت التشغيل أو أخطاء عرض صامتة في تطبيقات React.
لماذا تستخدم محوّل HTML إلى JSX؟
إعادة تسمية السمات يدويًا وإعادة كتابة سلاسل style عبر عشرات عناصر HTML عملية بطيئة وعرضة للأخطاء. يتولى المحوّل كل تحويل دفعةً واحدة، فتلصق HTML من أي مصدر وتحصل على JSX صالحة في ثوانٍ.
حالات استخدام محوّل HTML إلى JSX
مرجع تعيين سمات HTML إلى JSX
يسرد الجدول أدناه سمات HTML التي تتغير عند تحويلها إلى JSX. السمات غير المذكورة هنا (مثل id وsrc وhref وalt وplaceholder وغيرها) تبقى دون تغيير لأن أسماءها في HTML تطابق أسماء خصائص DOM API المقابلة.
| سمة HTML | خاصية JSX | ملاحظات |
|---|---|---|
| class | className | Reserved word in JavaScript |
| for | htmlFor | Reserved word in JavaScript |
| tabindex | tabIndex | camelCase convention |
| readonly | readOnly | camelCase convention |
| maxlength | maxLength | camelCase convention |
| minlength | minLength | camelCase convention |
| cellpadding | cellPadding | camelCase convention |
| cellspacing | cellSpacing | camelCase convention |
| rowspan | rowSpan | camelCase convention |
| colspan | colSpan | camelCase convention |
| enctype | encType | camelCase convention |
| autocomplete | autoComplete | camelCase convention |
| autofocus | autoFocus | camelCase convention |
| autoplay | autoPlay | camelCase convention |
| contenteditable | contentEditable | camelCase convention |
| crossorigin | crossOrigin | camelCase convention |
| novalidate | noValidate | camelCase convention |
| allowfullscreen | allowFullScreen | camelCase convention |
| spellcheck | spellCheck | camelCase convention |
| http-equiv | httpEquiv | Hyphen removed, camelCase |
| onclick | onClick | Event handler camelCase |
| onchange | onChange | Event handler camelCase |
| onsubmit | onSubmit | Event handler camelCase |
تحويل الأنماط المضمّنة: HTML مقابل JSX
الأنماط المضمّنة هي الجزء الأكثر عرضةً للأخطاء في تحويل HTML إلى JSX، لأن تنسيق القيمة وأسماء الخصائص يتغيران معًا:
<div style="background-color: #fff; font-size: 14px; margin-top: 10px;">
<div style={{
backgroundColor: '#fff',
fontSize: '14px',
marginTop: 10
}}>أمثلة برمجية
توضّح هذه الأمثلة كيفية تحويل HTML إلى JSX برمجيًا بلغات وبيئات مختلفة. تتناول كل منها إعادة تسمية السمات وتحويل الأنماط ومعالجة الوسوم ذاتية الإغلاق.
// Simple attribute conversion using string replacement
function htmlToJsx(html) {
return html
.replace(/\bclass=/g, 'className=')
.replace(/\bfor=/g, 'htmlFor=')
.replace(/\btabindex=/g, 'tabIndex=')
.replace(/<!--([\s\S]*?)-->/g, '{/*$1*/}')
}
htmlToJsx('<div class="box" tabindex="0"><!-- note --></div>')
// → '<div className="box" tabIndex="0">{/* note */}</div>'import parse from 'html-react-parser'
// Parse HTML string into React elements (handles all JSX rules)
const element = parse('<div class="card"><img src="photo.jpg" alt="Photo"></div>')
// Returns: React.createElement('div', { className: 'card' },
// React.createElement('img', { src: 'photo.jpg', alt: 'Photo' }))
// With custom element replacement
const options = {
replace(domNode) {
if (domNode.name === 'img') {
return <OptimizedImage src={domNode.attribs.src} alt={domNode.attribs.alt} />
}
}
}
const custom = parse('<img src="photo.jpg" alt="Photo">', options)from bs4 import BeautifulSoup
import re
ATTR_MAP = {
'class': 'className', 'for': 'htmlFor',
'tabindex': 'tabIndex', 'readonly': 'readOnly',
'maxlength': 'maxLength', 'autocomplete': 'autoComplete',
}
def html_to_jsx(html: str) -> str:
"""Convert HTML attribute names to JSX equivalents."""
for html_attr, jsx_attr in ATTR_MAP.items():
html = re.sub(rf'\b{html_attr}=', f'{jsx_attr}=', html)
# Convert HTML comments to JSX comments
html = re.sub(r'<!--(.*?)-->', r'{/*\1*/}', html)
return html
print(html_to_jsx('<label for="email" class="field">Email</label>'))
# → '<label htmlFor="email" className="field">Email</label>'package main
import (
"fmt"
"strings"
)
var attrMap = map[string]string{
"class=": "className=",
"for=": "htmlFor=",
"tabindex=": "tabIndex=",
"readonly": "readOnly",
}
func htmlToJSX(html string) string {
result := html
for old, new := range attrMap {
result = strings.ReplaceAll(result, old, new)
}
// Convert comments
result = strings.ReplaceAll(result, "<!--", "{/*")
result = strings.ReplaceAll(result, "-->", "*/}")
return result
}
func main() {
html := `<div class="wrapper"><input readonly tabindex="1"></div>`
fmt.Println(htmlToJSX(html))
// → <div className="wrapper"><input readOnly tabIndex="1"></div>
}