Repository: prettier/prettier (JavaScript)
Date: 2018-11-09 05:32:21+00:00
Task type: Bug Fix

Issue:
[Markdown] CRLFs in codeblock are duplicated
Originally reported by @paolovanini in prettier/prettier-vscode#624

**Prettier 1.15.1**
~~Playground link~~(not reproducible on playground)
```sh
--parser markdown
```

(`<cr>` `<lf>` represent `\r` `\n`)

**Input:**
````md
```<cr><lf>
<cr><lf>
```<cr><lf>
````

**Output:**
````md
```<cr><lf>
<cr><cr><lf>
<cr><cr><lf>
```<cr><lf>
````

**Expected behavior:**
No duplicate.


Issue discussion:

Solution patch:
diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js
index 4a7477d1d131..f37cb99b094b 100644
--- a/src/language-markdown/printer-markdown.js
+++ b/src/language-markdown/printer-markdown.js
@@ -209,7 +209,7 @@ function genericPrint(path, options, print) {
         const alignment = " ".repeat(4);
         return align(
           alignment,
-          concat([alignment, join(hardline, node.value.split("\n"))])
+          concat([alignment, replaceNewlinesWith(node.value, hardline)])
         );
       }
 
@@ -225,9 +225,9 @@ function genericPrint(path, options, print) {
         style,
         node.lang || "",
         hardline,
-        join(
-          hardline,
-          getFencedCodeBlockValue(node, options.originalText).split("\n")
+        replaceNewlinesWith(
+          getFencedCodeBlockValue(node, options.originalText),
+          hardline
         ),
         hardline,
         style
@@ -469,7 +469,7 @@ function getNthListSiblingIndex(node, parentNode) {
 }
 
 function replaceNewlinesWith(str, doc) {
-  return join(doc, str.split("\n"));
+  return join(doc, str.replace(/\r\n?/g, "\n").split("\n"));
 }
 
 function getNthSiblingIndex(node, parentNode, condition) {
diff --git a/src/language-markdown/utils.js b/src/language-markdown/utils.js
index 83736b602727..b15d92c720d0 100644
--- a/src/language-markdown/utils.js
+++ b/src/language-markdown/utils.js
@@ -148,7 +148,7 @@ function getFencedCodeBlockValue(node, originalText) {
   const leadingSpaceCount = text.match(/^\s*/)[0].length;
   const replaceRegex = new RegExp(`^\\s{0,${leadingSpaceCount}}`);
 
-  const lineContents = text.split("\n");
+  const lineContents = text.replace(/\r\n?/g, "\n").split("\n");
 
   const markerStyle = text[leadingSpaceCount]; // ` or ~
   const marker = text


Test patch:
diff --git a/tests_integration/__tests__/__snapshots__/format.js.snap b/tests_integration/__tests__/__snapshots__/format.js.snap
index c9c6108d2f9a..e25b72a35c66 100644
--- a/tests_integration/__tests__/__snapshots__/format.js.snap
+++ b/tests_integration/__tests__/__snapshots__/format.js.snap
@@ -2,6 +2,8 @@
 
 exports[`html parser should handle CRLF correctly 1`] = `"\\"<!--\\\\r\\\\n  test\\\\r\\\\n  test\\\\r\\\\n-->\\\\r\\\\n\\""`;
 
+exports[`markdown parser should handle CRLF correctly 1`] = `"\\"\`\`\`\\\\r\\\\n\\\\r\\\\n\\\\r\\\\n\`\`\`\\\\r\\\\n\\""`;
+
 exports[`typescript parser should throw the first error when both JSX and non-JSX mode failed 1`] = `
 "Expression expected. (9:7)
    7 | );
diff --git a/tests_integration/__tests__/format.js b/tests_integration/__tests__/format.js
index ca790730f511..bf4d30ff62bd 100644
--- a/tests_integration/__tests__/format.js
+++ b/tests_integration/__tests__/format.js
@@ -33,3 +33,11 @@ test("html parser should handle CRLF correctly", () => {
     JSON.stringify(prettier.format(input, { parser: "html" }))
   ).toMatchSnapshot();
 });
+
+test("markdown parser should handle CRLF correctly", () => {
+  const input = "```\r\n\r\n\r\n```";
+  expect(
+    // use JSON.stringify to observe CRLF
+    JSON.stringify(prettier.format(input, { parser: "markdown" }))
+  ).toMatchSnapshot();
+});