Skip to content

Commit 9eca25c

Browse files
authored
Enhance quoting conversion on various pug statements (#578)
1 parent b09e029 commit 9eca25c

32 files changed

+537
-66
lines changed

src/printer.ts

Lines changed: 95 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,13 +2091,21 @@ export class PugPrinter {
20912091
return `${this.computedIndent}:${token.val}`;
20922092
}
20932093

2094-
private call(token: CallToken): string {
2094+
private async call(token: CallToken): Promise<string> {
20952095
let result: string = `${this.computedIndent}+${token.val}`;
20962096
let args: string | null = token.args;
20972097
if (args) {
2098-
args = args.trim();
2099-
args = args.replaceAll(/\s\s+/g, ' ');
2100-
result += `(${args})`;
2098+
args = args.trim().replaceAll(/\s\s+/g, ' ');
2099+
// Place an x at the beginning to preserve brackets,
2100+
// then remove the x after format.
2101+
args = await format(`x(${args})`, {
2102+
parser: 'babel',
2103+
...this.codeInterpolationOptions,
2104+
semi: false,
2105+
});
2106+
args = args.trim().slice(1);
2107+
2108+
result += args;
21012109
}
21022110

21032111
this.currentLineLength += result.length;
@@ -2106,23 +2114,48 @@ export class PugPrinter {
21062114
return result;
21072115
}
21082116

2109-
private mixin(token: MixinToken): string {
2117+
private async mixin(token: MixinToken): Promise<string> {
21102118
let result: string = `${this.computedIndent}mixin ${token.val}`;
21112119
let args: string | null = token.args;
21122120
if (args) {
2113-
args = args.trim();
2114-
args = args.replaceAll(/\s\s+/g, ' ');
2115-
result += `(${args})`;
2121+
args = args.trim().replaceAll(/\s\s+/g, ' ');
2122+
2123+
// Let args act as args of js function during format.
2124+
args = await format(`function x(${args}) {}`, {
2125+
parser: 'babel',
2126+
...this.codeInterpolationOptions,
2127+
});
2128+
args = args.trim().slice(10, -3);
2129+
2130+
result += args;
21162131
}
21172132

21182133
return result;
21192134
}
21202135

2121-
private if(token: IfToken): string {
2136+
private async if(token: IfToken): Promise<string> {
21222137
let result: string = this.computedIndent;
21232138
const match: RegExpExecArray | null = /^!\((.*)\)$/.exec(token.val);
21242139
logger.debug('[PugPrinter]:', match);
2125-
result += match ? `unless ${match[1]}` : `if ${token.val}`;
2140+
2141+
let append: string = 'if ';
2142+
let code: string | undefined = token.val;
2143+
2144+
if (match) {
2145+
append = 'unless ';
2146+
code = match[1];
2147+
}
2148+
2149+
result += append;
2150+
2151+
if (typeof code === 'string') {
2152+
code = await format(code, {
2153+
parser: '__js_expression',
2154+
...this.codeInterpolationOptions,
2155+
});
2156+
}
2157+
2158+
result += String(code).trim();
21262159
return result;
21272160
}
21282161

@@ -2134,8 +2167,13 @@ export class PugPrinter {
21342167
return `${this.computedIndent}else`;
21352168
}
21362169

2137-
private ['&attributes'](token: AndAttributesToken): string {
2138-
const result: string = `&attributes(${token.val})`;
2170+
private async ['&attributes'](token: AndAttributesToken): Promise<string> {
2171+
const code: string = await format(token.val, {
2172+
parser: '__js_expression',
2173+
...this.codeInterpolationOptions,
2174+
});
2175+
2176+
const result: string = `&attributes(${code})`;
21392177
this.currentLineLength += result.length;
21402178
return result;
21412179
}
@@ -2159,13 +2197,21 @@ export class PugPrinter {
21592197
return `${this.computedIndent}${token.val}`;
21602198
}
21612199

2162-
private each(token: EachToken): string {
2200+
private async each(token: EachToken): Promise<string> {
21632201
let result: string = `${this.computedIndent}each ${token.val}`;
2202+
21642203
if (token.key !== null) {
21652204
result += `, ${token.key}`;
21662205
}
21672206

2168-
result += ` in ${token.code}`;
2207+
const code: string = await format(token.code, {
2208+
parser: '__js_expression',
2209+
...this.codeInterpolationOptions,
2210+
semi: false,
2211+
});
2212+
2213+
result += ` in ${code}`;
2214+
21692215
return result;
21702216
}
21712217

@@ -2181,20 +2227,41 @@ export class PugPrinter {
21812227
}
21822228

21832229
value = unwrapLineFeeds(value);
2184-
const code: string = token.code.trim();
2230+
let code: string = await format(token.code, {
2231+
parser: '__js_expression',
2232+
...this.codeInterpolationOptions,
2233+
semi: true,
2234+
});
2235+
code = code.trim();
2236+
21852237
return `${this.computedIndent}each ${value} of ${code}`;
21862238
}
21872239

2188-
private while(token: WhileToken): string {
2189-
return `${this.computedIndent}while ${token.val}`;
2240+
private async while(token: WhileToken): Promise<string> {
2241+
const code: string = await format(token.val, {
2242+
parser: '__js_expression',
2243+
...this.codeInterpolationOptions,
2244+
});
2245+
2246+
return `${this.computedIndent}while ${code.trim()}`;
21902247
}
21912248

2192-
private case(token: CaseToken): string {
2193-
return `${this.computedIndent}case ${token.val}`;
2249+
private async case(token: CaseToken): Promise<string> {
2250+
const code: string = await format(token.val, {
2251+
parser: '__js_expression',
2252+
...this.codeInterpolationOptions,
2253+
});
2254+
2255+
return `${this.computedIndent}case ${code.trim()}`;
21942256
}
21952257

2196-
private when(token: WhenToken): string {
2197-
return `${this.computedIndent}when ${token.val}`;
2258+
private async when(token: WhenToken): Promise<string> {
2259+
const code: string = await format(token.val, {
2260+
parser: '__js_expression',
2261+
...this.codeInterpolationOptions,
2262+
});
2263+
2264+
return `${this.computedIndent}when ${code.trim()}`;
21982265
}
21992266

22002267
private [':'](token: ColonToken): string {
@@ -2207,8 +2274,13 @@ export class PugPrinter {
22072274
return `${this.computedIndent}default`;
22082275
}
22092276

2210-
private ['else-if'](token: ElseIfToken): string {
2211-
return `${this.computedIndent}else if ${token.val}`;
2277+
private async ['else-if'](token: ElseIfToken): Promise<string> {
2278+
const code: string = await format(token.val, {
2279+
parser: '__js_expression',
2280+
...this.codeInterpolationOptions,
2281+
});
2282+
2283+
return `${this.computedIndent}else if ${code.trim()}`;
22122284
}
22132285

22142286
private blockcode(token: BlockcodeToken): string {

tests/frameworks/svelte/formatted.pug

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ main
77
| to learn how to build Svelte
88
| apps.
99
p
10-
+each('cats as cat')
10+
+each("cats as cat")
1111
a(href="{ cat.id }") { cat.name }
1212
| !{ ' ' }
1313

1414
p
15-
+if('!user.loggedIn')
15+
+if("!user.loggedIn")
1616
button(on:click="{ toggle }")
1717
| Log out

tests/issues/issue-11/formatted.pug

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ html
66
head
77
title Test
88
body
9-
+stylesheet('test')
9+
+stylesheet("test")

tests/mixins/formatted.pug

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ mixin list
1818
mixin pet(name)
1919
li.pet= name
2020
ul
21-
+pet('cat')
22-
+pet('dog')
23-
+pet('pig')
21+
+pet("cat")
22+
+pet("dog")
23+
+pet("pig")
2424

2525
mixin article(title)
2626
.article
@@ -31,19 +31,29 @@ mixin list
3131
else
3232
p No content provided
3333

34-
+article('Hello world')
34+
+article("Hello world")
3535

36-
+article('Hello world')
36+
+article("Hello world")
3737
p This is my
3838
p Amazing article
3939

4040
mixin link(href, name)
4141
//- attributes == {class: "btn"}
4242
a(class!=attributes.class, href=href)= name
4343

44-
+link('/foo', 'foo').btn
44+
+link("/foo", "foo").btn
4545

4646
mixin link2(href, name)
4747
a(href=href)&attributes(attributes)= name
4848

49-
+link2('/foo', 'foo').btn
49+
+link2("/foo", "foo").btn
50+
51+
//- Params have default values
52+
mixin coords(x = { x1: 1, x2: 2 }, y = { y1: 1, y2: 2 })
53+
p= "coords"
54+
55+
//- Args keep parentheses after prettier format
56+
+coords((2 + 2) * 2, 2 * (2 + 2))
57+
58+
//- Args include object
59+
+coords({ x1: 1, x2: 2 }, { y1: 1, y2: 2 })

tests/mixins/unformatted.pug

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,13 @@ mixin link2(href, name)
4747
a(href=href)&attributes(attributes)= name
4848

4949
+link2('/foo', 'foo')(class="btn")
50+
51+
//- Params have default values
52+
mixin coords(x={x1: 1, x2: 2}, y={y1: 1, y2: 2})
53+
p= 'coords'
54+
55+
//- Args keep parentheses after prettier format
56+
+coords((2 + 2) * 2, 2 * (2 + 2))
57+
58+
//- Args include object
59+
+coords({x1: 1, x2: 2}, {y1: 1, y2: 2})

tests/options/singleQuote/single-false-pug-false/formatted.pug

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ div(:class="{ 'pt-2': !dense }", test="blah")
1111
p= `${name}`
1212
p= "single quoted"
1313

14-
each quote of ["quote1", 'quote2']
14+
each quote of ["quote1", "quote2"]
1515
p= quote
1616

1717
div(data-tab=name ? name : "The 'Rock'")

tests/options/singleQuote/single-false-pug-true/formatted.pug

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,53 @@ div(:class='{ "pt-2": !dense }', test='blah')
1111
p= `${name}`
1212
p= 'single quoted'
1313

14-
each quote of ["quote1", 'quote2']
14+
each quote of ['quote1', 'quote2']
1515
p= quote
1616

1717
div(data-tab=name ? name : "The 'Rock'")
1818

19-
if name === "test"
19+
if name === 'test'
2020
p= name
21+
22+
//- Case statement
23+
case 'red'
24+
when 'red'
25+
p It is red
26+
default
27+
p It is not red
28+
29+
//- Conditionals
30+
if 'red' === "'red'"
31+
p Red is red
32+
else if 'blue' === '"blue"'
33+
p Blue is blue
34+
35+
unless 'blue' !== '"blue"'
36+
p Blue is blue
37+
38+
//- Iteration
39+
each val in ['One', 'Two']
40+
p= val
41+
42+
while 'red' === "'blue'"
43+
- break
44+
45+
//- Mixin def
46+
mixin element(el = 'button')
47+
p= el
48+
49+
//- Mixin call
50+
+element('button')
51+
52+
//- &attributes
53+
div&attributes({ x: 'x', y: 'y' })
54+
55+
.grey--text {{ $t("my-language-key.title") }}
56+
v-text-field(
57+
:label='$t("my-language-key")',
58+
type='text',
59+
name='aName',
60+
v-model='model',
61+
:rules='[(model.values !== null && model.values.length <= 15) || $t("my-other-language-key.error")]',
62+
:disabled='invalid'
63+
)

tests/options/singleQuote/single-false-pug-true/unformatted.pug

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,46 @@ div(data-tab=name ? name : "The 'Rock'")
1818

1919
if name === "test"
2020
p= name
21+
22+
//- Case statement
23+
case "red"
24+
when "red"
25+
p It is red
26+
default
27+
p It is not red
28+
29+
//- Conditionals
30+
if "red" === '\'red\''
31+
p Red is red
32+
else if "blue" === '"blue"'
33+
p Blue is blue
34+
35+
unless "blue" !== "\"blue\""
36+
p Blue is blue
37+
38+
//- Iteration
39+
each val in ['One', "Two"]
40+
p= val
41+
42+
while "red" === "'blue'"
43+
- break
44+
45+
//- Mixin def
46+
mixin element(el="button")
47+
p= el
48+
49+
//- Mixin call
50+
+element("button")
51+
52+
//- &attributes
53+
div&attributes({ x: "x", y: "y" })
54+
55+
.grey--text {{ $t("my-language-key.title") }}
56+
v-text-field(
57+
:label="$t('my-language-key')",
58+
type="text",
59+
name="aName",
60+
v-model="model",
61+
:rules="[ (model.values !== null && model.values.length <= 15) || $t('my-other-language-key.error')]",
62+
:disabled="invalid"
63+
)

0 commit comments

Comments
 (0)