نصوص التلوين بتنسيق html و React

من السهل إضافة ترميز إلى النص بيديك. يمكنك ترميز النص هنا على حبري ، ثم نسخه إلى الموقع. يمكنك البحث باستخدام بديل في Notepad ++ أو Atom.

إذا كان النص 1. إذا كان هناك الكثير من النصوص ، فأنا أريد الحصول على أداة لاستخراج أجزاء النص باستخدام علامات html أو توليد شفرة مصدر لـ React. على Python ، هذا ليس صعبًا (بضعة أسطر من التعليمات البرمجية لكل لون).



إذا كنت تعرف Python والتعبيرات العادية ، فاتبع الرابط.

هناك أمثلة ورموز المصدر. تحت كاتوم وصفا مفصلا.

ترميز النص على سبيل المثال تلوين كود مصدر جافا سكريبت


النظر في الوظيفة:

def jsToHtml(s):

عند الإدخال ، يُرجع النص المصدر html.

نقوم بتعيين المتغيرات التي تحدد سمات الكتل. في المثال ، تُستخدم الأنماط للوضوح ، في المستقبل يكون من المنطقي استبدالها بفئات.

comm = 'style="color: red;"' #   
blue = 'style="color: blue;"' # 
...

وضع علامة على.

أول شيء تفعله هو الهروب من الأحرف "&" ، "<" ، ">"

s = s.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

تم تجاوز "&" لعرض مجموعات الحروف "& lt؛" و "& gt؛" وغيرها من "& ...؛" ، يتم

تجاوز الأحرف "<" و ">" حتى لا تتعارض مع العلامات.

يمكنك حماية الكثير من الأشياء ، لكن في رأيي ، هذا في utf-8 هذا يكفي.

خوارزمية الترميز:

  • نأخذ نموذجًا جديدًا ونبحث عن جميع أجزاء النص التي ترضيه.
  • نقطع كل جزء ، ونضيف ترميزًا إليه ونحفظ الجزء الذي تم وضع علامة عليه في مصفوفة (في نفس الوقت ، احفظ النص الأصلي: سيكون مفيدًا).
  • في مكانه ، أدخل كعب مع الرقم.
  • وهكذا لكل لون.
  • عندما يتم رسم كل شيء ، استبدل الأشرطة بشظايا ملونة من الصفيف.

يجب أن يكون الروتين فريدًا ، ولكن في نصنا لا يوجد حرف واحد "<" وليس حرفًا واحدًا ">".

صنع كعب:

f'<{i}>'

حيث i هو رقم كعب الروتين. بالتأكيد لا يوجد شيء من هذا القبيل في النص.

ماذا تفعل إذا كان هناك بالفعل كعب داخل الجزء.

على سبيل المثال ، في النص المصدر كانت هناك خطوط:

`  :   /*     */ `
/* , `     ` */

الخيار 2:

  1. تجاهل. في هذه الحالة ، سيكون للسلسلة لون مزدوج.
  2. ابحث عن بذرة متداخلة واستبدلها بالنص الأصلي (غير المميز).

نقوم بعمل وظيفة تنفذ كل هذا (10 أسطر من التعليمات البرمجية ، 10 أسطر من التعليق):

def oneRe(reStr, s, attr, ls, multiColor=False):
    '''
        s  ,          ls,
           (<0>, <1> ...<1528>...).
          .
    
    reStr - re
    s - 
    attr -  style/class/etc
    ls -   
    multiColor=False,     
    '''
    for block in set(re.findall(reStr, s)):
        toArr = block
        if not multiColor: #  multiColor==False,   
            for prev in set(re.findall(r'<[\d]+>', block)): #  : <0> ... <21>
                iPrev = int(prev[1:-1], 10)                #     
                toArr = toArr.replace(prev, ls[iPrev][1])  #   '<0> qwe <21>'  (<0>,<21>)  . 
        ls.append([f'<span {attr}>{toArr}</span>', toArr]) #     ls 2 :     
        s = s.replace(block, f'<{len(ls)-1}>')
    return s

هذا عرض توضيحي: قد يكون ترميز التعبير العادي غير صحيح ، ولا تتم معالجة الأحرف الفارغة (\ '، \ ").

كمرجع: التعبير:

s = s.replace(/A + B/g, 'A - B');

برامج تحرير Notepad ++ و Atom لها ألوان مختلفة.

الآن بعد أن أصبح هناك oneRe ، تتم شظايا التلوين ببساطة. مثال على تلوين الخطوط في الفواصل العليا وعلامات الاقتباس:

s = oneRe(r"'[\s\S]*?'", s, green, ls, multiColor=False) #    ''   ls
s = oneRe(r'"[\s\S]*?"', s, green, ls, multiColor=False) #    ""   ls

مثال على تلوين أكثر تعقيدًا. تحتاج شبيبة لتلوين التعابير في خطوط متعددة
`    ${A + B}  ${A - B}`


for mStr in set(re.findall(r'`[\s\S]+?`', s)): #    
    newFstr = mStr
    for val in set(re.findall(r"\$\{[\s\S]+?\}", mStr)):
        ls.append([f'<span {darkRed}>{val}</span>', val])
        newFstr = newFstr.replace(val, f'<{i}>')
        i += 1
    s = s.replace(mStr, newFstr)
    
s = oneRe(r'`[\s\S]+?`', s, green, ls, multiColor=True) #    ``   ls

نجد أولاً

السلاسل المتعددة: re.findall (r "[\ s \ S] +؟ ''، s) تُرجع قائمة من كتل النص بين أحرف الاقتباس.

تحتوي كل كتلة على مسافات أو غير مسافات ([\ s \ S] أي شيء).

طول الكتلة 1 أو أكثر (+).

بدون جشع ("؟" يعني أنه لا يوجد رمز "" "داخل الكتلة).

انسخ الكتلة الموجودة (متغير mStr ) إلى متغير newFstr .
نجد في الكتل الفرعية مع التعابير $ {...}.

re.findall (r "\ $ \ {[\ s \ S] *؟ \}" ، mStr) تُرجع قائمة بهذه الكتل الفرعية. نحفظ الترميز في الصفيف ls ونستبدل الكتلة الفرعية مع كعب في متغير newFstr .
عند تشغيل الكتل الفرعية من استبدال في سلسلة الأصلي الصورةقيمة الكتلة الأصلية إلى الجديدة.

تعيين ليس لزوم لها. إذا أعاد findall العديد من الكتل المتطابقة ، عند معالجة الكتلة الأولى في شفرة المصدر ، يتم استبدال جميع الكتل المتطابقة بأرواح في آن واحد. عند معالجة الكتلة الثانية نفسها ، لن تكون موجودة في النص المصدر بعد الآن. تعيين يزيل الازدواجية.

ملف JsToHtml.py
# -*- coding: utf-8 -*- 
'''
AON 2020

'''

import re

# *** *** ***

def oneRe(reStr, s, attr, ls, multiColor=False):
    '''
        s  ,          ls,
           (<0>, <1> ...<1528>...).
          .
    
    reStr - re
    s - 
    attr -  style/class/etc
    ls -   
    multiColor=False,     
    '''
    i = len(ls) #   
    for block in set(re.findall(reStr, s)):
        toArr = block
        if not multiColor: #  multiColor==False,   
            for prev in set(re.findall(r'<[\d]+>', block)): #  : <0> ... <21>
                iPrev = int(prev[1:-1], 10)                 #     
                toArr = toArr.replace(prev, ls[iPrev][1])   #   '<0> qwe <21>'  (<0>,<21>)  . 
        ls.append([f'<span {attr}>{toArr}</span>', toArr])  #     ls 2 :     
        s = s.replace(block, f'<{i}>')              #       
        i += 1
    return s

# *** *** ***

def operColor(s, ls, color):
    '''
     .
      ,       ,  
    '''
    i = len(ls)
    for c in ['&lt;=', '&gt;=', '=&lt;', '=&gt;', '&lt;', '&gt;', '&amp;&amp;', '&amp;',
              '===', '!==', '==', '!=', '+=', '-=', '++', '--', '||']:
        ls.append([f'<span {color}>{c}</span>',0])
        s = s.replace(c, f'<{i}>')
        i += 1
    for c in '!|=+-?:,.[](){}%*/':
        ls.append([f'<span {color}>{c}</span>',0])
        s = s.replace(c, f'<{i}>')
        i += 1
    return s

# *** *** ***

def jsToHtml(s):
    '''
      .
     ,        <span>.
    '''

    black = '''style="font-family: 'Courier New', monospace;
        background: #fff; 
        color: black;
        font-weight: bold;
        border: 1px solid #ddd;
        padding: 5px;
        text-align: left;
        white-space: pre;"'''
    comm = 'style="color: red;"'
    green = 'style="color: green; font-style: italic;"'
    blue = 'style="color: blue;"'
    red2 = 'style="color: #840;"'

    s = s.replace('&', '&amp;').replace('<', &'&lt;').replace('>', '&gt;')   #   '&', '<', '>'

    ls = []

    i = 0
    for mStr in set(re.findall(r'`[\s\S]+?`', s)): #    
        newFstr = mStr
        for val in set(re.findall(r"\$\{[\s\S]+?\}", mStr)):
            ls.append([f'<span {darkRed}>{val}</span>', val])
            newFstr =newFstr.replace(val, f'<{i}>')
            i += 1
        s = s.replace(mStr, newFstr)
        
    s = oneRe(r'`[\s\S]+?`', s, green, ls, multiColor=True) #    ``   ls
    s = oneRe(r"'[\s\S]*?'", s, green, ls, multiColor=False) #    ''   ls
    s = oneRe(r'"[\s\S]*?"', s, green, ls, multiColor=False) #    ""   ls
    s = oneRe(r'/[\s\S].*?/g\b', s, green, ls, multiColor=False) #    re-   ls
    s = oneRe(r'/[\s\S].*?/\.', s, green, ls, multiColor=False) #    re-   ls
    s = oneRe(r'/\*[\s\S]+?\*/', s, comm, ls, multiColor=False) #    /*  */   ls (  - )
    s = oneRe(r'//[\s\S]*?\n', s, comm, ls, multiColor=False) #    //    ls (  - )

    i = len(ls)

    #    
    for c in ['new', 'JSON', 'Promise', 'then', 'catch', 'let', 'const', 'var', 'true', 'false', 'class', 'from', 'import', 'set', 'list', 'for', 'in', 'if', 'else', 'return', 'null']:
        ls.append([f'<span {blue}>{c}</span>',0])
        s = re.sub (r'\b%s\b' % c, f'<{i}>', s)
        i += 1

    #     
    for c in ['window', 'doc', 'cmd', 'init','init2', 'recalc', 'hide', 'readOnly', 'validate']:
        ls.append([f'<span {darkRed}>{c}</span>',0])
        s = re.sub (r'\b%s\b' % c, f'<{i}>', s)
        i += 1

    s = operColor(s, ls, darkBlue) #    

    for j in range(len(ls), 0, -1):  #  , , ,    
        s = s.replace(f'<{j-1}>', ls[j-1][0])

    return f'<div {black}>{s}</div>'

# *** *** ***


Html في رد الفعل


تحويل html إلى رمز مصدر React على htmltoreact.com . هناك أيضًا رابط إلى GitHub.

هذا لم يناسبني: أولاً ، لا يشكل بالضبط ما أحتاجه ، وثانيًا ، كيف سأجر هذه المعجزة إلى خادمي.

لقد كتبت الخاصة بي.

قم بتثبيت مكتبة lxml (تثبيت pip lxml أو تثبيت pip3 lxml).

نستورد:

from xml.dom.minidom import parseString
from lxml import html, etree

تحويل نص html إلى نص xhtml. إنها تقريبًا نفس الشيء ، ولكن تم إغلاق جميع العلامات.

doc = html.fromstring(htmlText)
ht = etree.tostring(doc, encoding='utf-8').decode()

ناتج parsim xhtml إلى بيت الشجرة باستخدام البيت الصغير.

dom = parseString(ht)

نقوم بعمل وظيفة تقفز بشكل متكرر فوق العقد وتولد النتيجة في شكل رمز مصدر التفاعل.

بعد استدعاء parseString ، فإن شجرة dom هي عقدة أبي تحتوي على عقد أطفال لديها أطفال ، إلخ.

كل عقدة هي قاموس يحتوي على وصفها:

  • nodeName - اسم العقدة ، السلسلة
  • childNodes - عقد الأطفال ، قائمة
  • سمات - سمات ، قاموس
  • عقدة تسمى #text لها nodeValue (سلسلة)

مثال:

<div class="A" style="color: red;">Red of course,<br> </div>

بعد التحولات نحصل على:
{ 'nodeName':'div',
  'attributes': {'style': 'color: red;', 'class': 'A'},
  'childNodes': [
    {'nodeName':'#text', 'nodeValue': 'Red of course,'},
    {'nodeName':'br'},
    {'nodeName':'#text', 'nodeValue': ''},
  ],
}

يعد تحويل dom إلى سلسلة أمرًا سهلاً (هناك صورة مطبوعة) ، عند إنشاء رمز React ، قمت باستبدال الفئة بـ className وأعدت سمة النمط.

في العقد النصية ، يتم إفلات '{'، '}'، '<'، '>'.

ملف HtmlToReact.py
# -*- coding: utf-8 -*- 
# -*- coding: utf-8 -*- 

from xml.dom.minidom import parseString
from lxml import html, etree

# *** *** ***

_react = ''

def htmlToReact(buf):
    '''
    buf - html-
     ReactJS- 
    '''
    global _react
    _react = ''

    try:
        r = re.search('<[\\s\\S]+>', buf)
        if r:
            doc = html.fromstring(r.group(0))
            ht = etree.tostring(doc, encoding='utf-8').decode()
            xHtmlToReact(parseString(ht).childNodes[0], '')
            return _react
        else:
            return '<empty/>'
    except Exception as ex:
        s = f'htmlToReact: \n{ex}'
        print(s)
        return s

# *** *** ***

def sU(a, c):
    '''
    xlink:show   ->  xlinkShow
    font-weight  ->  fontWeight
    '''
    l, _, r = a.partition(c)
    return ( (l + r[0].upper() + r[1:]) if r else a).strip()

# *** *** ***

def xHtmlToReact(n, shift='\n    '):
    '''
       -
      ,        upperCase
       global  _react
    '''
    global _react

    if n.nodeName.lower() in ['head', 'script']:
        return
    
    _react += shift + '<' + n.nodeName.lower()
    if n.attributes:
        for k, v in n.attributes.items():
            if k == 'style':
                style = ''
                for s in v.split(';'):
                    if s.strip():
                        l, _, r = s.partition(':')
                        style += f'''{sU(l, '-')}: "{r.strip()}", '''
                if style:
                    _react += ' style={{' + style + '}}'
            elif k == 'class':
                _react += f' className="{v}"'
            else:
                kk = k.replace('xlink:href', 'href') # deprcated
                _react += f''' {sU( sU(kk, ':'), '-' )}="{v}"'''
        
    _react += '>'
    if n.childNodes:
        for child in n.childNodes:
            if  child.nodeName == '#text':
                tx = child.nodeValue
                for x in ['{', '}', '<', '>']:
                    tx = tx.replace(x, '{"' + x + '"_{_')
                tx = tx.replace('_{_', '}')
                if tx[-1] == ' ':
                    tx = tx[:-1] + '\xa0'
                _react += tx.replace('\n', '<br/>')
            else:
                xHtmlToReact(child)
                
    _react += f'{shift}</{n.nodeName.lower()}>'

# *** *** ***



أمثلة وشفرة المصدر هنا.

ملاحظة على حبري ، تلوين كود بايثون (وربما غيره) ليس مثاليًا. إذا كانت سلسلة python تحتوي على السلسلة & amp؛ ، يتم عرضه كـ & . في شفراتي ، قمت بتعديلها لجعلها تبدو صحيحة. إذا صحح هبر خطأً ، فإن نصوصي ستتقاطع مع بعضها البعض.

All Articles