← ब्लॉग

console.log में React रेंडर करना

Text.js, React ऐप को DevTools कंसोल में हर फ़्रेम पर एक स्टाइल वाली console.log कॉल के रूप में दिखाता है।

Adam

Text.js, Chrome DevTools कंसोल में React ऐप रेंडर करता है। छिपे हुए इनपुट के अलावा, पेज पर कोई UI नहीं है। ऐप का हर फ़्रेम एक console.log कॉल है।

डिस्प्ले के रूप में कंसोल

console.log एक फ़ॉर्मैट स्ट्रिंग लेता है। हर %c अगले आर्ग्युमेंट की CSS को अपने बाद के टेक्स्ट पर, अगले %c तक लागू करता है:

console.log("%c▼ Text.js%c ready", "color:#ededed;font-weight:700", "color:#45a557");

ये स्टाइल रंग, बैकग्राउंड, बोल्ड, इटैलिक और अंडरलाइन सेट कर सकती हैं, और कंसोल का फ़ॉन्ट मोनोस्पेस है (macOS पर Menlo)। मोनोस्पेस फ़ॉन्ट और कैरेक्टर के हर रन पर बदल सकने वाले रंगों के साथ, कंसोल स्टाइल वाले कैरेक्टर सेल के ग्रिड की तरह काम करता है। इस पर बॉर्डर, पैनल, इनपुट और चार्ट सभी बनाए जा सकते हैं।

फ़्रेम सेल का एक ग्रिड है

रेंडरर हर फ़्रेम को एक CellBuffer में रखता है। कैरेक्टर एक टाइप्ड ऐरे में, फ़ोरग्राउंड और बैकग्राउंड के रंग दो अन्य ऐरे में, और बोल्ड व अंडरलाइन जैसे एट्रिब्यूट चौथे ऐरे में रहते हैं। दिए गए साइज़ के लिए ऐरे एक बार एलोकेट होते हैं और हर फ़्रेम में दोबारा इस्तेमाल होते हैं।

फ़्रेम लॉग करने के लिए, ड्राइवर हर पंक्ति से गुज़रकर एक जैसी स्टाइल वाले आस-पास के सेल को रन में ग्रुप करता है। हर रन एक %c span बनता है, और पंक्तियां \n से जुड़ती हैं। हमारा 100×32 टेस्ट डैशबोर्ड, जिसमें 3,200 सेल हैं, लगभग 200 span में एनकोड होता है।

हर फ़्रेम के लिए एक कॉल

हर पंक्ति को अलग मैसेज के रूप में लॉग करना काम नहीं करता। DevTools में हर मैसेज को अपना बॉर्डर और सोर्स लिंक मिलता है, और DevTools लगातार आने वाले एक जैसे मैसेज को रिपीट काउंटर के पीछे समेट देता है, इसलिए टेबल की दो एक जैसी पंक्तियां एक में मिल जाएंगी। एक मैसेज के रूप में लॉग किया गया फ़्रेम एक साथ बना रहता है।

टेक्स्ट में दो चीज़ों को पहले एस्केप करना ज़रूरी है। लिटरल % को %% लिखा जाता है, ताकि 100% जैसा टेक्स्ट किसी स्टाइल आर्ग्युमेंट का इस्तेमाल न कर सके। DevTools, URL को लिंक में भी बदलता है और उन्हें अपने रंगों में दोबारा पेंट करता है, इसलिए :// और www. में एक word joiner (U+2060) जोड़ा जाता है, जिसकी कोई चौड़ाई नहीं होती:

export function escapeConsoleText(text: string, allowLink = false): string {  let s = text;  if (s.includes("%")) s = s.replaceAll("%", "%%");  if (!allowLink) {    if (s.includes(LINK_SCHEME)) s = s.replaceAll(LINK_SCHEME, LINK_SCHEME_SAFE);    if (s.includes(WWW) || s.includes("WWW.")) s = s.replace(/www\./gi, (m) => `${m.slice(0, 3)}\u2060.`);  }  return s;}

निष्क्रिय फ़्रेम कुछ लॉग नहीं करते

बफ़र की हर पंक्ति का हैश बनता है। अगर पिछले फ़्रेम के बाद कोई हैश नहीं बदला, तो ड्राइवर स्ट्रिंग बनाने से पहले ही लौट जाता है और कंसोल को छूता तक नहीं। इनपुट का इंतज़ार कर रहा ऐप कोई कॉल नहीं करता।

जब कोई पंक्ति बदलती है, तो ड्राइवर कंसोल साफ़ करता है और नया फ़्रेम लॉग करता है:

const { frame, dirtyRows } = this.encode(buffer, options);if (frame === null) return SKIPPED;if (this.clearEachFrame) target.clear();target.log(frame.format, ...frame.args);

सिर्फ़ वे पंक्तियां दोबारा एनकोड होती हैं जिनका हैश बदला है। बाकी पंक्तियां पिछले फ़्रेम के span दोबारा इस्तेमाल करती हैं।

इनपुट

कंसोल को कीस्ट्रोक नहीं मिलते, इसलिए पेज उन्हें इकट्ठा करता है। एक छिपा हुआ <textarea> कुंजियां दबाने, पेस्ट और IME कंपोज़िशन के इनपुट लेकर उन्हें ऐप के लिए की इवेंट में बदलता है। पेज पर क्लिक करने से उस पर फ़ोकस आता है।

आगे

npm पर @textjs/core के 0.0.x प्रोटोटाइप सब कुछ एक पैकेज में रखते हैं। Text.js 0.1 यहां बताए गए रेंडरर को @textjs/core में, React रिकंसाइलर को @textjs/react में ले जाता है, और एक App Router जोड़ता है।