RivasCVA/react-native-code-editor

Cursor Misaligning from the Text

RivasCVA opened this issue ยท 8 comments

There is a small ongoing issue involving the cursor misaligning from the text. This is due to the fact that a text input is rendered on top of the syntax highlighter text. This issue varies depending on the fontFamilychosen.

You may resolve the issue by fine tuning the fontSize, inputLineHeight, and highlighterLineHeight styles until the input text aligns with the syntax highlighter text.

You can use the inputColor and highlighterColor styles to help you align the input text with the syntax highlighter text.

Make sure to check that the text stays aligned after inserting many new lines or until the text become scrollable.

Issue Example

Leaving fontSize: 20 alone produces the following effect.

<CodeEditor
    style={{
        fontFamily: 'Menlo-Regular',
        fontSize: 20,
    }}
    language="javascript"
    syntaxStyle={CodeEditorSyntaxStyles.atomOneDark}
    showLineNumbers
/>

Adding inputLineHeight: 26 and highlighterLineHeight: 26 fixes the issue.

<CodeEditor
    style={{
        fontFamily: 'Menlo-Regular',
        fontSize: 20,
        inputLineHeight: 26,
        highlighterLineHeight: 26,
    }}
    language="javascript"
    syntaxStyle={CodeEditorSyntaxStyles.atomOneDark}
    showLineNumbers
/>

Note: The values for inputLineHeight and highlighterLineHeight may vary depending on the fontFamily chosen. You will have to play around with the styles until the issue resolves. With some fonts setting only one will work, with other fonts not setting either will also work.

Help would be appreciated to resolve this issue globally so that developers do not have to play around with inputLineHeight and highlighterLineHeight with any fontFamily chosen.

That's an interesting problem, a little bit of research lead me to this library which is maybe worth exploring.

any updates on this? unfortunately the fix only seem to work on iOS and not on android, at least for me.

@suXXVI There hasn't been any resolution for this. The best approach is to use different fontSize, inputLineHeight, and highlighterLineHeight values for iOS and different ones for Android.

I got a fix, but Iโ€™m gonna need to make some adjustments before submitting a PR

770c9f86-2576-4d09-a473-7423509937a1.mp4

Keep me updated. Excited to see a possible fix ๐ŸŽ‰

Sorry for the late reply, I've been out on Company holiday shenanigans, I first got it working with a flatlist implementation (because I thought hey virtualization here would be cool) but somehow that ended up becoming less performant? so next week I'll get back into this with a different approach

well the code that was working before has now stopped scrolling which has become a bit of a roadblock at the moment

@RivasCVA to resolve this issue please make changes as per below and it's working perfect

  1. Set the style as shown in attached code

<CodeEditor initialValue={fileContent} onChange={newContent => setFileContent(newContent)} showLineNumbers style={{ ...{ fontSize: 18, inputLineHeight: 18, highlighterLineHeight: 18, }, }} />

  1. In node_modules/@rivascva/react-native-code-editor/src/CodeEditor.tsx file add line as below mentioned
    return ( <View style={{ width, height, marginTop, marginBottom }}> <ScrollView showsHorizontalScrollIndicator={true} horizontal={true}> <SyntaxHighlighter language={language} addedStyle={addedStyle} syntaxStyle={syntaxStyle} scrollEnabled={false} showLineNumbers={showLineNumbers} ref={highlighterRef} > {value} </SyntaxHighlighter> <TextInput style={[ styles.input, { lineHeight: inputLineHeight, color: inputColor, fontFamily: fontFamily, fontSize: fontSize, padding, paddingTop: padding, paddingLeft: lineNumbersPadding, }, ]} value={value} onChangeText={handleChangeText} onScroll={handleScroll} onKeyPress={handleKeyPress} onSelectionChange={handleSelectionChange} autoCapitalize="none" autoComplete="off" autoCorrect={false} autoFocus={autoFocus} keyboardType="ascii-capable" editable={!readOnly} ref={inputRef} multiline /> </ScrollView> </View> );

  2. In file node_modules/@rivascva/react-native-code-editor/src/SyntaxHighlighter.tsx make changes as per below code
    const renderNode = (nodes: Node[], key = '0') => nodes.reduce<React.ReactNode[]>((acc, node, index) => { if (node.children) { const textElement = ( <Text numberOfLines={1} key={${key}.${index}} style={[ { color: highlighterColor || stylesheet.hljs.color, }, ...(node.properties?.className || []).map((c) => stylesheet[c]), { lineHeight: highlighterLineHeight, fontFamily, fontSize, paddingLeft: lineNumbersPadding ?? padding, }, ]} > {renderNode(node.children, ${key}.${index}`)}

    );

             const lineNumberElement =
                 key !== '0' || index >= nodes.length - 2 ? undefined : (
                     <Text
                         numberOfLines={1}
                         key={`$line.${index}`}
                         style={{
                             position: 'absolute',
                             top: 5,
                             bottom: 0,
                             paddingHorizontal: nodes.length - 2 < 100 ? 5 : 0,
                             textAlign: 'center',
                             color: lineNumbersColor,
                             fontFamily,
                             fontSize: lineNumbersFontSize,
                             // width: lineNumbersPadding ? lineNumbersPadding - 5 : 0,
                         }}
                     >
                         {index + 1}
                     </Text>
                 );
    
             acc.push(
                 showLineNumbers && lineNumberElement ? (
                     <View key={`view.line.${index}`}>
                         {lineNumberElement}
                         {textElement}
                     </View>
                 ) : (
                     textElement
                 )
             );
         }
    
         if (node.value) {
             // To prevent an empty line after each string
             node.value = node.value.replace('\n', '');
             // To render blank lines at an equal font height
             node.value = node.value.length ? node.value : ' ';
             acc.push(node.value);
         }
    
         return acc;
     }, []);`