Skip to content

Commit 8af6094

Browse files
authored
(fix) format everything except text in pre (#267)
Fixes #266 It remains to be seen if this is the desired behavior, but let's go with it for now. Prettier core won't touch pre tags at all, so we differ a little from them here.
1 parent d524893 commit 8af6094

File tree

7 files changed

+76
-13
lines changed

7 files changed

+76
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* (fix) Better handling of destructured values with defaults in each and await blocks ([#269](https://github.com/sveltejs/prettier-plugin-svelte/issues/269))
66
* (fix) Prevent script/style contents from being erased in certain cases ([#268](https://github.com/sveltejs/prettier-plugin-svelte/issues/268))
7+
* (fix) Format mustache tags inside `<pre>` tags ([#266](https://github.com/sveltejs/prettier-plugin-svelte/issues/266))
78

89
## 2.5.0
910

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const parsers: Record<string, Parser> = {
2626
parse: (text) => {
2727
try {
2828
return <ASTNode>{ ...require(`svelte/compiler`).parse(text), __isRoot: true };
29-
} catch (err) {
29+
} catch (err: any) {
3030
if (err.start != null && err.end != null) {
3131
// Prettier expects error objects to have loc.start and loc.end fields.
3232
// Svelte uses start and end directly on the error.

src/print/doc-helpers.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@ function deepEqual(x: any, y: any): boolean {
3333
}
3434
}
3535

36+
function isDocCommand(doc: Doc): doc is doc.builders.DocCommand {
37+
return typeof doc === 'object' && doc !== null;
38+
}
39+
3640
export function isLine(docToCheck: Doc): boolean {
3741
return (
3842
isHardline(docToCheck) ||
39-
(typeof docToCheck === 'object' && docToCheck.type === 'line') ||
40-
(typeof docToCheck === 'object' &&
43+
(isDocCommand(docToCheck) && docToCheck.type === 'line') ||
44+
(isDocCommand(docToCheck) &&
4145
docToCheck.type === 'concat' &&
42-
docToCheck.parts.every(isLine))
46+
docToCheck.parts.every(isLine)) ||
47+
// Since Prettier 2.3.0, concats are represented as flat arrays
48+
(Array.isArray(docToCheck) && docToCheck.every(isLine))
4349
);
4450
}
4551

@@ -51,7 +57,7 @@ export function isEmptyDoc(doc: Doc): boolean {
5157
return doc.length === 0;
5258
}
5359

54-
if (doc.type === 'line') {
60+
if (isDocCommand(doc) && doc.type === 'line') {
5561
return !doc.keepIfLonely;
5662
}
5763

src/print/index.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
240240
? () => line
241241
: () => (bracketSameLine ? softline : '');
242242
} else if (isPreTagContent(path)) {
243-
body = () => printRaw(node, options.originalText);
243+
body = () => printPre(node, options.originalText, path, print);
244244
} else if (!isSupportedLanguage) {
245245
body = () => printRaw(node, options.originalText, true);
246246
} else if (isInlineElement(path, options, node) && !isPreTagContent(path)) {
@@ -267,7 +267,7 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
267267
];
268268

269269
if (!isSupportedLanguage && !isEmpty) {
270-
// Format template tags so that there's a hardline but no intendation.
270+
// Format template tags so that there's a hardline but no indention.
271271
// That way the `lang="X"` and the closing `>` of the start tag stay in one line
272272
// which is the 99% use case.
273273
return groupConcat([
@@ -758,13 +758,36 @@ function printSvelteBlockChildren(path: FastPath, print: PrintFn, options: Parse
758758
]);
759759
}
760760

761+
function printPre(
762+
node: Parameters<typeof printRaw>[0],
763+
originalText: string,
764+
path: FastPath,
765+
print: PrintFn,
766+
): Doc {
767+
const result: Doc = [];
768+
const length = node.children.length;
769+
for (let i = 0; i < length; i++) {
770+
const child = node.children[i];
771+
if (child.type === 'Text') {
772+
const lines = originalText.substring(child.start, child.end).split(/\r?\n/);
773+
lines.forEach((line, j) => {
774+
if (j > 0) result.push(literalline);
775+
result.push(line);
776+
});
777+
} else {
778+
result.push(path.call(print, 'children', i));
779+
}
780+
}
781+
return concat(result);
782+
}
783+
761784
function printChildren(path: FastPath, print: PrintFn, options: ParserOptions): Doc {
762785
if (isPreTagContent(path)) {
763786
return concat(path.map(print, 'children'));
764787
}
765788

766789
const childNodes: Node[] = prepareChildren(path.getValue().children, path, print);
767-
// modifiy original array because it's accessed later through map(print, 'children', idx)
790+
// modify original array because it's accessed later through map(print, 'children', idx)
768791
path.getValue().children = childNodes;
769792
if (childNodes.length === 0) {
770793
return '';
@@ -838,7 +861,7 @@ function printChildren(path: FastPath, print: PrintFn, options: ParserOptions):
838861
(nextChild.type !== 'Text' ||
839862
// Only handle text which starts with a whitespace and has text afterwards,
840863
// or is empty but followed by an inline element. The latter is done
841-
// so that if the children break, the inline element afterwards is in a seperate line.
864+
// so that if the children break, the inline element afterwards is in a separate line.
842865
((!isEmptyTextNode(nextChild) ||
843866
(childNodes[idx + 2] && isInlineElement(path, options, childNodes[idx + 2]))) &&
844867
!isTextNodeStartingWithLinebreak(nextChild)))
@@ -850,7 +873,7 @@ function printChildren(path: FastPath, print: PrintFn, options: ParserOptions):
850873

851874
/**
852875
* Print text child. First/last child white space handling
853-
* is done in parent already. By defintion of the Svelte AST,
876+
* is done in parent already. By definition of the Svelte AST,
854877
* a text node always is inbetween other tags. Add hardlines
855878
* if the users wants to have them inbetween.
856879
* If the text is trimmed right, toggle flag telling
@@ -907,7 +930,7 @@ function printChildren(path: FastPath, print: PrintFn, options: ParserOptions):
907930

908931
/**
909932
* `svelte:options` is part of the html part but needs to be snipped out and handled
910-
* seperately to reorder it as configured. The comment above it should be moved with it.
933+
* separately to reorder it as configured. The comment above it should be moved with it.
911934
* Do that here.
912935
*/
913936
function prepareChildren(children: Node[], path: FastPath, print: PrintFn): Node[] {

src/print/node-helpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ export function trimTextNodeLeft(node: TextNode): void {
335335

336336
/**
337337
* Remove all leading whitespace up until the first non-empty text node,
338-
* and all trailing whitepsace from the last non-empty text node onwards.
338+
* and all trailing whitespace from the last non-empty text node onwards.
339339
*/
340340
export function trimChildren(children: Node[], path: FastPath): void {
341341
let firstNonEmptyNode = children.findIndex(
@@ -370,7 +370,7 @@ export function trimChildren(children: Node[], path: FastPath): void {
370370
}
371371

372372
/**
373-
* Check if given node's starg tag should hug its first child. This is the case for inline elements when there's
373+
* Check if given node's start tag should hug its first child. This is the case for inline elements when there's
374374
* no whitespace between the `>` and the first child.
375375
*/
376376
export function shouldHugStart(
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<pre>Hello,
2+
world! {JSON.stringify({ foo:'bar'},null,
3+
2)}Goodbye.
4+
this text goes waaaaaaaaaaaaaaaaaaaaaaaaaaaaaayyyyyyyyyyyyyyyyyyyyyyyyyyy above the print width {{a: true}} and the mustache should split it
5+
<code>const asd = {
6+
variable };</code>
7+
<code>nested
8+
9+
should
10+
11+
stay
12+
13+
as is
14+
</code>
15+
this line is intended using tabs which should be preserved
16+
</pre>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<pre>Hello,
2+
world! {JSON.stringify({ foo: "bar" }, null, 2)}Goodbye.
3+
this text goes waaaaaaaaaaaaaaaaaaaaaaaaaaaaaayyyyyyyyyyyyyyyyyyyyyyyyyyy above the print width {{
4+
a: true,
5+
}} and the mustache should split it
6+
<code>const asd = {variable};</code>
7+
<code
8+
>nested
9+
10+
should
11+
12+
stay
13+
14+
as is
15+
</code>
16+
this line is intended using tabs which should be preserved
17+
</pre>

0 commit comments

Comments
 (0)