RivasCVA / react-native-code-editor

A code editor with syntax highlighting built for React Native applications.
MIT License
54 stars 18 forks source link

Cursor Misaligning from the Text #1

Open RivasCVA opened 2 years ago

RivasCVA commented 2 years ago

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.

mattperls-code commented 2 years ago

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

suXXVI commented 1 year ago

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

RivasCVA commented 1 year ago

@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.

jdmg94 commented 10 months ago

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

https://github.com/RivasCVA/react-native-code-editor/assets/4754734/63a25afb-03bb-4d47-a137-696e1d03d83c

RivasCVA commented 9 months ago

Keep me updated. Excited to see a possible fix 🎉

jdmg94 commented 9 months ago

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

jdmg94 commented 8 months ago

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

commencementtech commented 3 months ago

@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 }}> {value}
    </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;
    }, []);`