Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix attribute interpolation using quotes #179

Merged
merged 3 commits into from
Feb 18, 2021
Merged
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
33 changes: 2 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,41 +144,12 @@ These additional options are specific to pug templates and can be configured in
| `pugClassNotation` | choice | `'literal'` | Define how classes should be formatted.<ul><li>`'literal'` -> Forces all valid classes to be printed as literals.<br>Example: `foo.bar.baz`</li><li>~`'attribute'` -> Forces all classes to be printed as attributes.~ _this option is [still in progress](https://github.com/prettier/plugin-pug/issues/167)_<br>Example: `foo(class="bar baz")`</li><li>`'as-is'` -> Disables class formatting.<br>Example: `foo.bar(class="baz")`</li></ul> |
| `pugIdNotation` | choice | `'literal'` | Define how ids should be formatted.<ul><li>`'literal'` -> Forces all valid ids to be printed as literals.<br>Example: `foo#bar`</li><li>~`'attribute'` -> Forces all ids to be printed as attributes.~<br>_this option is [still in progress](https://github.com/prettier/plugin-pug/issues/167)_<br>Example: `foo(id="bar")`</li><li>`'as-is'` -> Disables id formatting.<br>Example: `foo(id="bar")`</li></ul> |

## Workarounds / Known Issues
## Workaround / Known Issue

There are some code examples that are not formatted well with this plugin and can damage your code.
But there are workarounds for it. These generate even better pug code!

### Examples

[Issue 53](https://github.com/prettier/plugin-pug/issues/53)

```pug
input(onClick="methodName(\"" + variable + "\", this)")
// transforms to
input(onClick="methodName(\"\" + variable + \"\", this)")

// In most cases ES6 template strings are a good solution
input(onClick=`methodName("${variable}", this)`)
```

As mentioned in [pugjs.org Attribute Interpolation](https://pugjs.org/language/attributes.html#attribute-interpolation) (2.),
you should prefer ES2015 template strings to simplify your attributes.

[Issue 54](https://github.com/prettier/plugin-pug/issues/54)

```pug
- const id = 42
- const collapsed = true

div(id=id, class='collapse' + (collapsed ? '' : ' show') + ' card-content')
// transforms to
.card-content(id=id, class="collapse' + (collapsed ? '' : ' show') + '")

// better write
.card-content.collapse(id=id, class=collapsed ? '' : 'show')
// Now your js logic is extracted from the plain logic
```
### Example

[Issue 114](https://github.com/prettier/plugin-pug/issues/114)

Expand Down
17 changes: 16 additions & 1 deletion src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,27 @@ export function isStyleAttribute(name: string, val: string): boolean {
* In this case `val` is `route`.
*
* ---
*
* Special cases:
* ```
* a(href='/' + '#')
* a(href="/" + "#")
* ```
*
* These cases should not be treated as quoted.
*
* ---
*
* @param val Value of tag attribute.
* @returns Whether the value is quoted or not.
*/
export function isQuoted(val: string): boolean {
return /^["'](.*)["']$/.test(val);
if(/^(["'])(.*)\1$/.test(val)) {
// Regex for checking if there are any unescaped quotations.
const regex: RegExp = new RegExp(`${val[0]}(?<!\\\\${val[0]})`);
return !regex.test(val.slice(1, -1));
}
return false;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions tests/issues/issue-58/formatted.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- const variable = 'func';
- collapsed = false;
input(onClick='methodName("' + variable + '", this)')
div(id=id, class='collapse' + (collapsed ? '' : ' show') + ' card-content')
14 changes: 14 additions & 0 deletions tests/issues/issue-58/issue-58.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { readFileSync } from 'fs';
import { resolve } from 'path';
import { format } from 'prettier';
import { plugin } from './../../../src/index';

describe('Issues', () => {
test('should treat attribute interpolation using quotes properly', () => {
const expected: string = readFileSync(resolve(__dirname, 'formatted.pug'), 'utf8');
const code: string = readFileSync(resolve(__dirname, 'unformatted.pug'), 'utf8');
const actual: string = format(code, { parser: 'pug', plugins: [plugin] });

expect(actual).toBe(expected);
});
});
4 changes: 4 additions & 0 deletions tests/issues/issue-58/unformatted.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- const variable = 'func'
- collapsed = false
input(onClick="methodName(\"" + variable + "\", this)")
div(id=id, class='collapse' + (collapsed ? '' : ' show') + ' card-content')