mitosis icon indicating copy to clipboard operation
mitosis copied to clipboard

Line break character \n causes problem when trying to use it for splitting textarea content into an array with rows

Open TomasJohansson opened this issue 1 year ago • 5 comments

I am interested in helping provide a fix!

No

Which generators are impacted?

  • [ ] All
  • [X] Angular
  • [ ] HTML
  • [ ] Qwik
  • [X] React
  • [X] React-Native
  • [X] Solid
  • [ ] Stencil
  • [X] Svelte
  • [X] Vue
  • [ ] Web components

Reproduction case

https://mitosis.builder.io/?outputTab=IYOw5grgNsBOQ%3D%3D%3D&inputTab=M4NwpgNgLmQ%3D&code=DwZwxgTglgDgLgAgDYEMB2BzAvAIjiHAPgCgEzkBTROCgDzhQgpQGEB7NGzhLBHHANylySKgghsA7iCHkEAEgBc4qSB4Ia9Rs3acKnAHQgYSKHAAUOADpocASgMAzKEhoRzEyT0IqvAQl5%2BOyFgAHpwaHgSYmBNBiYUBGEyACMoNAATRQA3FCQAVwpcAG847VYOLjgAXxwkuU8QXABGAAYcZIQwNiQmnAAmduJQnzkkmPykEjligGJmMAALXzUUNU9qzrlgU0JijbDdzuLQhcXNsMnCIA%3D%3D%3D

Expected Behaviour

The code generation should generate similar code as in the Svelte/sveltosis input code regarding splitting the content of a textarea, i.e. the following line of code should become similar for the other targets: textareaContent.split("\n").filter(row => row != "")

Actual Behaviour

The targets 'react' and 'reactNative' instead generates the following corresponding line of code (with space instead of line break character): textareaContent.split(" ").filter((row) => row != "")

The targets 'angular' and 'vue' instead generates the following corresponding lines of code:

textareaContent.split("
").filter(row => row != "")

(i.e. with an actual line break rather than the line break character \n) Target 'svelte' generates the same result as angular and vue, i.e. when trying to generate from Svelte/sveltosis input to target 'svelte'

The target 'solid' fails with a "SyntaxError: Unterminated string literal" and does not generate any output file.

Additional Information

Svelte/sveltosis input file src\lib\MySveltePage.svelte

<script lang="ts">
    let textareaContent = "";
    let rows;
    $: rows = textareaContent.split("\n").filter(row => row != "");
</script>

<textarea 
    bind:value="{textareaContent}" 
    rows="10"
    cols="20"
/>      

<ul>
    {#each rows as row}
        <li>{row}</li>
    {/each}
</ul>

When generating the outputs I was using this command: pnpm exec mitosis build

pnpm list @builder.io/mitosis 0.0.92 @builder.io/mitosis-cli 0.0.51

pnpm --version 7.29.3

npm --version 9.6.1

node --version v18.15.0

Operating system: Windows 10

TomasJohansson avatar Mar 18 '23 10:03 TomasJohansson

Looking at the generated JSON:

    "rows": {
      "code": "get rows() {\n return state.textareaContent.split(\"\\n\").filter(row => row != \"\")}",
      "type": "getter"
    }

I do see the \n is escaped correctly. It might be our usage of the dedent library which is causing this problem 🤔, I'm not entirely sure...

Easiest way to make sure is add a snapshot test that includes a \n inside of a string, and then play with removing the dedent package from the generators and see if it fixes our issue.

samijaber avatar Apr 11 '23 20:04 samijaber

Confirming that dedent does not respect the escaped \n:

CleanShot 2023-04-11 at 16 26 23@2x

samijaber avatar Apr 11 '23 20:04 samijaber

hello @samijaber I have found the bug with react generator I believe it is because of this function https://github.com/BuilderIO/mitosis/blob/1f80185077cc354316dce7be04b0b40fd13b6856/packages/core/src/helpers/replace-new-lines-in-strings.ts#L1

it is being used in the react generator here https://github.com/BuilderIO/mitosis/blob/1f80185077cc354316dce7be04b0b40fd13b6856/packages/core/src/generators/react/generator.ts#L497

the logic is as follows:

if the char \n is between double quotes or single quotes then replace it with empty space https://github.com/BuilderIO/mitosis/blob/1f80185077cc354316dce7be04b0b40fd13b6856/packages/core/src/helpers/replace-new-lines-in-strings.ts#L6-L10

I used backticks instead of double quotes and the react generator is no longer replacing \n with a space, and the \n is getting replaced with an actual line break just like Vue and Angular generators

question number 1 is how to resolve the react issue. question number 2 is how to resolve the dedent issue.

moaoa avatar Apr 23 '23 12:04 moaoa

I think we solve both by removing all usage of dedent and stripNewLinesInStrings. That should be OK.

samijaber avatar Apr 26 '23 14:04 samijaber

@samijaber I am interested in fixing this issue (to be my first one ever in open source), but may I ask why we used dedent in the first place? and will remove it cause any problems?

Othman2001 avatar Oct 13 '23 13:10 Othman2001