Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ import {
unwrapLineFeeds,
} from './utils/common';
import { getScriptParserName } from './utils/script-mime-types';
import { getStyleParserName } from './utils/style-mime-types';
import { isSvelteInterpolation } from './utils/svelte';
import {
isVueEventBinding,
Expand Down Expand Up @@ -1983,7 +1984,9 @@ export class PugPrinter {
}

case 'style': {
parser = 'css';
parser = getStyleParserName(
previousTypeAttributeToken(this.tokens, this.currentIndex),
);
break;
}

Expand Down
46 changes: 46 additions & 0 deletions src/utils/style-mime-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { BuiltInParserName } from 'prettier';
import type { AttributeToken } from 'pug-lexer';

const wrappingQuotesRe: RegExp = /(^(["'`]))|((["'`])$)/g;

// Matches style types to the required parser for them
// Note: Types not listed here (e.g. `sass` or `stylus`) are left unformatted,
// because there is no builtin prettier parser for them
const styleTypeToParserMap: Map<string, BuiltInParserName> = new Map([
['css', 'css'],
['text/css', 'css'],
['less', 'less'],
['text/less', 'less'],
['scss', 'scss'],
['text/scss', 'scss'],
]);

/**
* Decides which parser to format style contents with.
*
* @param typeAttrToken Type token of the style tag.
* @returns Parser name to parse contents with.
*/
export function getStyleParserName(
typeAttrToken?: AttributeToken,
): BuiltInParserName | undefined {
// Omission means CSS
if (!typeAttrToken) {
return 'css';
}

const typeRaw: string | boolean = typeAttrToken.val;
// If it's not a string, best not do anything
if (typeof typeRaw !== 'string') {
return;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (if-minor): line 35 and 42 are both uncovered, do you think we can add test cases for them?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be all set. Let me know what you think!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused myself, but the Coverage Report -> File Coverage -> src/utils/script-mime-types.ts now shows 42, 49 👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea. I think those lines have coverage. I'll investigate more tomorrow. Thanks!

}

const type: string = typeRaw.replaceAll(wrappingQuotesRe, '').toLowerCase();

// Empty type is equivalent to omission
if (!type) {
return 'css';
}

return styleTypeToParserMap.get(type);
}
41 changes: 41 additions & 0 deletions tests/issues/issue-532/formatted.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//- Stays unchanged, because no loaded plugin provides a parser for sass
style(type="sass").
:host
display: inline

//- Formatted with the builtin scss parser
style(type="text/scss").
:host {
.a {
display: inline;
}
}

//- Formatted with the builtin less parser
style(type="less").
@color: red;
.a {
color: @color;
}

//- Formatted with the builtin css parser
style(type="text/css").
:host {
display: inline;
}

//- Without a type, formatted with the builtin css parser
style.
:host {
display: inline;
}

//- An empty type is formatted with the builtin css parser
style(type="").
:host {
display: inline;
}

//- Stays unchanged, because a type without a value is not a string
style(type).
:host { display:inline }
11 changes: 11 additions & 0 deletions tests/issues/issue-532/issue-532.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { compareFiles } from 'tests/common';
import { describe, expect, it } from 'vitest';

describe('Issues', () => {
describe('issue #532', () => {
it('should format style tags based on their type attribute', async () => {
const { actual, expected } = await compareFiles(import.meta.url);
expect(actual).toBe(expected);
});
});
});
31 changes: 31 additions & 0 deletions tests/issues/issue-532/unformatted.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//- Stays unchanged, because no loaded plugin provides a parser for sass
style(type="sass").
:host
display: inline

//- Formatted with the builtin scss parser
style(type='text/scss').
:host {
.a { display:inline }
}

//- Formatted with the builtin less parser
style(type="less").
@color: red;
.a { color:@color }

//- Formatted with the builtin css parser
style(type="text/css").
:host { display:inline }

//- Without a type, formatted with the builtin css parser
style.
:host { display:inline }

//- An empty type is formatted with the builtin css parser
style(type="").
:host { display:inline }

//- Stays unchanged, because a type without a value is not a string
style(type).
:host { display:inline }
Loading