Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Indent multiline fixes (fixes #120) #124

Merged
merged 5 commits into from
Oct 22, 2019
Merged

Fix: Indent multiline fixes (fixes #120) #124

merged 5 commits into from
Oct 22, 2019

Conversation

btmills
Copy link
Member

@btmills btmills commented Oct 8, 2019

Thanks to @lydell for discovering this bug and writing the tests to reproduce it in #120.

If I lint the following Markdown source text containing a JS code block inside a blockquote:

This is Markdown.

>   ```js
>   console.log('Hello, \
>   world!');
>   ```

What ESLint sees is this:

console.log('Hello, \
world!');

The fix text sent to the processor will contain the string, now with double quotes, and preserving the newline as-is:

"Hello, \\\nworld!"

The fix would then be applied incorrectly because it didn't account for the leading > in the Markdown source text:

This is Markdown.

>   ```js
>   console.log("Hello, \
world!" world!');
>   ```

This change tracks the leading text that precedes the first line of any fenced code block and inserts the same prefix after any newline in a fix, so the fix text in the above example would become:

"Hello, \\\n>   world!"

lydell and others added 2 commits September 7, 2019 10:05
If the replacement text of an autofix contains newlines, all lines but
the first in the replacement text will unexpectedly have 0 indentation
if a code block is indented. I guess not only the _range_ of fixes but
also the _text_ of fixes need to be adjusted.

If the code block is placed within a blockquote, a `>` character also
needs to be inserted.

This issue was found while investigating
lydell/eslint-plugin-simple-import-sort#22.  That plugin several lines
of imports in one go. This means that most of the imports will have too
little indentation after autofix if the code block is indented (such as
when placed in a list).
@btmills btmills added the bug label Oct 8, 2019
" ```js",
" console.log(\"Hello, world!\")",
" console.log(\"Hello, \\",
" world!\")",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not 100% sure how leading whitespace works in weird code blocks like this, but didn’t we cause one more space to appear in the JS string here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed 80edd59 that adds comments explaining why this occurs for the benefit of future readers of these tests.

When a line inside a fenced code block is indented less than the opening fence, Markdown treats it as having 0 indent, even though its indent in the source is negative. The parser doesn't provide any information to distinguish lines that begin at the same level as the opening fence from those that are underindented. Whenever one of those lines gets autofixed, it gets shifted to align with the opening fence. Lines that that have positive indentation inside the code fence retain their original indentation because those are representable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this case in https://spec.commonmark.org/dingus/ and the actual and expected code snippets produce the same rendered JS, with the same amount of spaces between "Hello," and "world!".

">",
"> > ```js",
"> > console.log(\"Hello, \\",
"> > world!\")",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here? Is this 1–2 too many spaces?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, same cause. I added comments in 80edd59 and explained further in #124 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this case in https://spec.commonmark.org/dingus/ and the actual and expected code snippets produce the same rendered JS, with the same amount of spaces between "Hello," and "world!".

@lydell
Copy link
Contributor

lydell commented Oct 8, 2019

Btw, I’d be fine not bothering with the two potential edge cases above. It’s better to fix the bug in the common case, and leave the very uncommon case for later.

@lydell
Copy link
Contributor

lydell commented Oct 11, 2019

Looks like this is ready to go, then?

@lydell
Copy link
Contributor

lydell commented Oct 13, 2019

As mentioned in the inline comments above, after checking on https://spec.commonmark.org/dingus/ there seems to be no problem with the current implementation! 🎉

@btmills btmills merged commit fb0b5a3 into master Oct 22, 2019
@btmills btmills deleted the issue120 branch October 22, 2019 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants