diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js
index ff929e712220..2e5322ac4179 100644
--- a/src/language-html/parser-html.js
+++ b/src/language-html/parser-html.js
@@ -281,6 +281,7 @@ function locEnd(node) {
function createParser({ recognizeSelfClosing }) {
return {
+ preprocess: text => text.replace(/\r\n?/g, "\n"),
parse: (text, parsers, options) =>
_parse(text, options, recognizeSelfClosing),
hasPragma,
diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js
index fb5f58c328ff..39d5e2fbb93c 100644
--- a/src/language-html/printer-html.js
+++ b/src/language-html/printer-html.js
@@ -442,20 +442,25 @@ function printChildren(path, options, print) {
return print(childPath);
}
const child = childPath.getValue();
- return concat([
- printOpeningTagPrefix(child),
- options.originalText.slice(
- options.locStart(child) +
- (child.prev && needsToBorrowNextOpeningTagStartMarker(child.prev)
- ? printOpeningTagStartMarker(child).length
- : 0),
- options.locEnd(child) -
- (child.next && needsToBorrowPrevClosingTagEndMarker(child.next)
- ? printClosingTagEndMarker(child).length
- : 0),
+ return concat(
+ [].concat(
+ printOpeningTagPrefix(child),
+ replaceNewlines(
+ options.originalText.slice(
+ options.locStart(child) +
+ (child.prev && needsToBorrowNextOpeningTagStartMarker(child.prev)
+ ? printOpeningTagStartMarker(child).length
+ : 0),
+ options.locEnd(child) -
+ (child.next && needsToBorrowPrevClosingTagEndMarker(child.next)
+ ? printClosingTagEndMarker(child).length
+ : 0)
+ ),
+ literalline
+ ),
printClosingTagSuffix(child)
)
- ]);
+ );
}
function printBetweenLine(prevNode, nextNode) {
@@ -544,9 +549,14 @@ function printOpeningTag(path, options, print) {
return path.map(attrPath => {
const attr = attrPath.getValue();
return hasPrettierIgnoreAttribute(attr)
- ? options.originalText.slice(
- options.locStart(attr),
- options.locEnd(attr)
+ ? concat(
+ replaceNewlines(
+ options.originalText.slice(
+ options.locStart(attr),
+ options.locEnd(attr)
+ ),
+ literalline
+ )
)
: print(attrPath);
}, "attrs");
diff --git a/tests_integration/__tests__/__snapshots__/format.js.snap b/tests_integration/__tests__/__snapshots__/format.js.snap
index ce4f8aea5dca..c9c6108d2f9a 100644
--- a/tests_integration/__tests__/__snapshots__/format.js.snap
+++ b/tests_integration/__tests__/__snapshots__/format.js.snap
@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`html parser should handle CRLF correctly 1`] = `"\\"\\\\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 1320e5ba7ae3..ca790730f511 100644
--- a/tests_integration/__tests__/format.js
+++ b/tests_integration/__tests__/format.js
@@ -25,3 +25,11 @@ label:
prettier.format(input, { parser: "typescript" })
).toThrowErrorMatchingSnapshot();
});
+
+test("html parser should handle CRLF correctly", () => {
+ const input = "";
+ expect(
+ // use JSON.stringify to observe CRLF
+ JSON.stringify(prettier.format(input, { parser: "html" }))
+ ).toMatchSnapshot();
+});