Skip to content

Commit

Permalink
(fix) Keep parantheses in script tags for which JS is assumed (#224)
Browse files Browse the repository at this point in the history
If a script tag is assumed to be JS, use babel-ts now to format the contents. The formatter prints a little different, keeping parantheses in more places, which fixes #218 . The change is not perfect because it would be better to know for sure that the language is JS, which we cannot know because of the possible language defaults.
  • Loading branch information
dummdidumm committed May 10, 2021
1 parent 69fc702 commit 9d1486e
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* (fix) Don't snip style tag that is inside script tag ([#219](https://github.com/sveltejs/prettier-plugin-svelte/issues/219), [#70](https://github.com/sveltejs/prettier-plugin-svelte/issues/70))
* (fix) Better formatting of long attribute values with mustache tags inbetween ([#221](https://github.com/sveltejs/prettier-plugin-svelte/pull/221))
* (fix) Format properly when using Prettier 2.3.0+ ([#222](https://github.com/sveltejs/prettier-plugin-svelte/pull/222))
* (fix) Keep parantheses in script tags for which JS is assumed ([#218](https://github.com/sveltejs/prettier-plugin-svelte/issues/218))

## 2.2.0

Expand Down
20 changes: 17 additions & 3 deletions src/embed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getLeadingComment,
isIgnoreDirective,
isNodeSupportedLanguage,
isTypeScript,
} from './print/node-helpers';
import { Node } from './print/nodes';

Expand Down Expand Up @@ -40,7 +41,11 @@ export function embed(
}
}

const embedType = (tag: string, parser: 'typescript' | 'css', isTopLevel: boolean) =>
const embedType = (
tag: string,
parser: 'typescript' | 'babel-ts' | 'css',
isTopLevel: boolean,
) =>
embedTag(
tag,
path,
Expand All @@ -49,7 +54,16 @@ export function embed(
isTopLevel,
);

const embedScript = (isTopLevel: boolean) => embedType('script', 'typescript', isTopLevel);
const embedScript = (isTopLevel: boolean) =>
embedType(
'script',
// Use babel-ts as fallback because the absence does not mean the content is not TS,
// the user could have set the default language. babel-ts will format things a little
// bit different though, especially preserving parentheses around dot notation which
// fixes https://github.com/sveltejs/prettier-plugin-svelte/issues/218
isTypeScript(node) ? 'typescript' : 'babel-ts',
isTopLevel,
);
const embedStyle = (isTopLevel: boolean) => embedType('style', 'css', isTopLevel);

switch (node.type) {
Expand Down Expand Up @@ -102,7 +116,7 @@ function getSnippedContent(node: Node) {

function formatBodyContent(
content: string,
parser: 'typescript' | 'css',
parser: 'typescript' | 'babel-ts' | 'css',
textToDoc: (text: string, options: object) => Doc,
options: ParserOptions,
) {
Expand Down
13 changes: 12 additions & 1 deletion src/print/node-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ function getLangAttribute(node: Node): string | null {
}

/**
* Checks whether the node contains a `lang` attribute with a value corresponding to
* Checks whether the node contains a `lang` or `type` attribute with a value corresponding to
* a language we cannot format. This might for example be `<template lang="pug">`.
* If the node does not contain a `lang` attribute, the result is true.
*/
Expand All @@ -236,6 +236,17 @@ export function isNodeSupportedLanguage(node: Node) {
return !(lang && unsupportedLanguages.includes(lang));
}

/**
* Checks whether the node contains a `lang` or `type` attribute which indicates that
* the script contents are written in TypeScript. Note that the absence of the tag
* does not mean it's not TypeScript, because the user could have set the default
* to TypeScript in his settings.
*/
export function isTypeScript(node: Node) {
const lang = getLangAttribute(node) || '';
return ['typescript', 'ts'].includes(lang);
}

export function isLoneMustacheTag(node: true | Node[]): node is [MustacheTagNode] {
return node !== true && node.length === 1 && node[0].type === 'MustacheTag';
}
Expand Down
4 changes: 4 additions & 0 deletions test/printer/samples/jsdoc-parens-in-script.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<script>
const x = /** @type {Foo} */ (a.b).c();
const y = /** @type {Foo} */ a.b.c();
</script>
23 changes: 23 additions & 0 deletions test/printer/samples/typescript-without-lang-attr.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script>
interface A {
b: string;
}
type Foo<T> = T extends true ? A & { b: boolean } : string;
type SeussFish = `${Quantity | Color} fish`;
const a: A = { b: "" };

function foo(a: A): void {
const foo = <Foo<true>>a;
return null as any;
}

const bar: () => void = () => {};

abstract class B<T> {
t: T;
}

enum E {
a = 1,
}
</script>
23 changes: 23 additions & 0 deletions test/printer/samples/typescript.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
interface A {
b: string;
}
type Foo<T> = T extends true ? A & { b: boolean } : string;
type SeussFish = `${Quantity | Color} fish`;
const a: A = { b: "" };

function foo(a: A): void {
const foo = <Foo<true>>a;
return null as any;
}

const bar: () => void = () => {};

abstract class B<T> {
t: T;
}

enum E {
a = 1,
}
</script>

0 comments on commit 9d1486e

Please sign in to comment.