Skip to content

Commit

Permalink
Merge pull request #707 from ember-template-lint/fix-706
Browse files Browse the repository at this point in the history
revert: Fix the scenario where block params are on a new line
  • Loading branch information
dcyriller authored Dec 10, 2021
2 parents ccab3b5 + cb4c0cc commit eb1e093
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 156 deletions.
85 changes: 34 additions & 51 deletions src/parse-result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,34 +550,42 @@ describe('ember-template-recast', function () {
`);
});

test('adding attribute to ElementNode preserves block param formatting (`\\nas |foo|`)', function () {
let template = `<Foo\nas |bar|></Foo>`;
test('issue 706', function () {
let template = `<div
class="pt-2 pb-4 {{this.foo}}"
>
{{#each this.data as |chunks|}}
{{#each chunks as |chunk|}}
{{#if (this.shouldShowImage chunk)}}
<p class="px-4">foo</p>
{{else}}
<p>bar</p>
{{/if}}
{{/each}}
{{/each}}
</div>`;

let ast = parse(template);
let element = ast.body[0] as AST.ElementNode;
element.attributes.push(builders.attr('data-test', builders.text('wheee')));

expect(print(ast)).toEqual(`<Foo data-test="wheee"\nas |bar|></Foo>`);
});

test('an attribute containing `as |foo|` does not confuse updates 😈', function () {
let template = `<Foo data-whatever="as |foo|" as |bar|></Foo>`;

let ast = parse(template);
let element = ast.body[0] as AST.ElementNode;
element.attributes.push(builders.attr('data-test', builders.text('wheee')));

expect(print(ast)).toEqual(`<Foo data-whatever="as |foo|" data-test="wheee" as |bar|></Foo>`);
});

test('adding attribute to ElementNode preserves block param formatting (`\n as\\n |bar|`)', function () {
let template = `<Foo \n as\n |bar|></Foo>`;

let ast = parse(template);
let element = ast.body[0] as AST.ElementNode;
element.attributes.push(builders.attr('data-test', builders.text('wheee')));

expect(print(ast)).toEqual(`<Foo data-test="wheee" \n as\n |bar|></Foo>`);
let block1 = (ast.body[0] as AST.ElementNode).children[1] as AST.BlockStatement;
let block2 = block1.program.body[1] as AST.BlockStatement;
let block3 = block2.program.body[1] as AST.BlockStatement;
let element = block3.program.body[1] as AST.ElementNode;
let attribute = element.attributes[0] as AST.AttrNode;
(attribute.value as AST.TextNode).chars = 'foo';

expect(print(ast)).toEqual(`<div
class="pt-2 pb-4 {{this.foo}}"
>
{{#each this.data as |chunks|}}
{{#each chunks as |chunk|}}
{{#if (this.shouldShowImage chunk)}}
<p class="foo">foo</p>
{{else}}
<p>bar</p>
{{/if}}
{{/each}}
{{/each}}
</div>`);
});
});

Expand Down Expand Up @@ -1173,31 +1181,6 @@ describe('ember-template-recast', function () {
{{/foo-bar}}
`);
});

test('modifying attribute of BlockStatement preserves block param formatting (`\\n\\n as\\n |bar|`)', function () {
let template = `{{#foo-bar
class="thing"
as
|bar|
}}
{{/foo-bar}}`;

let ast = parse(template) as any;
ast.body[0].hash.pairs[0].key = '@class';

expect(print(ast)).toEqual(`{{#foo-bar
@class="thing"
as
|bar|
}}
{{/foo-bar}}`);
});
});

describe('AttrNode', function () {
Expand Down
22 changes: 16 additions & 6 deletions src/parse-result.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { preprocess, builders, print as _print, traverse, ASTv1 as AST } from '@glimmer/syntax';
import { getLines, sortByLoc, sourceForLoc } from './utils';
import {
QuoteType,
AnnotatedAttrNode,
AnnotatedStringLiteral,
useCustomPrinter,
} from './custom-nodes';
import { getLines, sortByLoc, sourceForLoc, rangeOfBlockParam, getBlockParams } from './utils';

const leadingWhitespace = /(^\s+)/;
const attrNodeParts = /(^[^=]+)(\s+)?(=)?(\s+)?(['"])?(\S+)?/;
Expand Down Expand Up @@ -506,9 +506,13 @@ export default class ParseResult {
let blockParamsSource = '';
let postBlockParamsWhitespace = '';
if (element.blockParams.length > 0) {
blockParamsSource = getBlockParams(nodeInfo.source);
const blockParamStartIndex = nodeInfo.source.indexOf('as |');
const blockParamsEndIndex = nodeInfo.source.indexOf('|', blockParamStartIndex + 4);
blockParamsSource = nodeInfo.source.substring(
blockParamStartIndex,
blockParamsEndIndex + 1
);

const [, blockParamsEndIndex] = rangeOfBlockParam(nodeInfo.source);
const closeOpenIndex = nodeInfo.source.indexOf(selfClosing ? '/>' : '>');
postBlockParamsWhitespace = nodeInfo.source.substring(
blockParamsEndIndex + 1,
Expand Down Expand Up @@ -740,9 +744,14 @@ export default class ParseResult {
end: original.loc.end,
});

blockParamsSource = getBlockParams(blockParamsSourceScratch);
const indexOfAsPipe = blockParamsSourceScratch.indexOf('as |');
const indexOfEndPipe = blockParamsSourceScratch.indexOf('|', indexOfAsPipe + 4);

blockParamsSource = blockParamsSourceScratch.substring(
indexOfAsPipe,
indexOfEndPipe + 1
);

const [, indexOfEndPipe] = rangeOfBlockParam(blockParamsSourceScratch);
const postBlockParamsWhitespaceMatch = blockParamsSourceScratch
.substring(indexOfEndPipe + 1)
.match(leadingWhitespace);
Expand All @@ -764,7 +773,8 @@ export default class ParseResult {

let startingOffset = 0;
if (hadProgramBlockParams) {
const [, indexOfEndPipe] = rangeOfBlockParam(openEndSourceScratch);
const indexOfAsPipe = openEndSourceScratch.indexOf('as |');
const indexOfEndPipe = openEndSourceScratch.indexOf('|', indexOfAsPipe + 4);

startingOffset = indexOfEndPipe + 1;
}
Expand Down
27 changes: 0 additions & 27 deletions src/smoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,33 +606,6 @@ describe('"real life" smoke tests', function () {
<hr>
`);
});

test('supports block param on a new line', function () {
let template = stripIndent`
<SomeComponent @arg={{property}} as
|foo|>
</SomeComponent>
`;

let { code } = transform(template, (env) => {
let { builders: b } = env.syntax;
return {
AttrNode(node) {
if (node.value.type === 'MustacheStatement') {
node.value = b.mustache(`this.property`);
}
},
};
});

expect(code).toEqual(
stripIndent`
<SomeComponent @arg={{this.property}} as
|foo|>
</SomeComponent>
`
);
});
});

describe('angle-bracket-codemod mockup', function () {
Expand Down
32 changes: 1 addition & 31 deletions src/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sortByLoc, getBlockParams } from './utils';
import { sortByLoc } from './utils';
import { builders } from '.';

describe('utils', function () {
Expand Down Expand Up @@ -32,34 +32,4 @@ describe('utils', function () {
expect(actual.map((i) => i.key)).toEqual(['a', 'c', 'b']);
});
});

describe('getBlockParams', function () {
describe('given an ElementNode', function () {
test('returns the source of a simple block param', function () {
const element = '<Component as |bar|></Component>';

expect(getBlockParams(element)).toEqual('as |bar|');
});

test('returns the source of a block param while there is a named argument containing `as |foo|`', function () {
const element = '<Component data-foo="as |foo|" as |bar|></Component>';

expect(getBlockParams(element)).toEqual('as |bar|');
});
});

describe('given a BlockStatement', function () {
test('returns the source of a block param', function () {
const block = '{{#BlockStatement as |bar|}}{{/BlockStatement}}';

expect(getBlockParams(block)).toEqual('as |bar|');
});

test('returns the source of a block param while there is a named argument containing `as |foo|`', function () {
const block = '{{#BlockStatement data-foo="as |foo|" as |bar|}}{{/BlockStatement}}';

expect(getBlockParams(block)).toEqual('as |bar|');
});
});
});
});
40 changes: 0 additions & 40 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,43 +95,3 @@ export function getLines(source: string): string[] {

return result.slice(0, -1);
}

/*
* This function takes a string (the source of an ElementNode or a
* BlockStatement) and returns the range of the last possible block param's
* range.
*
* If the block param is not found, the function will return [-1, -1];
*
* For example:
* ```
* rangeOfBlockParam('<Component data-foo="as |foo|" as |bar|></Component>') // => [31, 38]
* rangeOfBlockParam('{{#BlockStatement data-foo="as |foo|" as |bar|}}{{/BlockStatement}}') // => [38, 45]
* ```
*/
export function rangeOfBlockParam(source: string): [number, number] {
let matches = Array.from(source.matchAll(/as\s+\|[^|]+\|/g));
let match = matches[matches.length - 1] as any;
if (!match) {
return [-1, -1];
}

return [match.index, match.index + match[0].length - 1];
}

/*
* This function takes a string (the source of an ElementNode or a
* BlockStatement) and returns its block param.
*
* If the block param is not found, the function will return "";
*
* For example:
* ```
* getBlockParams("<Component as |bar|></Component>") // => "as |bar|"
* getBlockParams("{{#BlockStatement as |bar|}}{{/BlockStatement}}") // => "as |bar|"
* ```
*/
export function getBlockParams(source: string): string {
const [indexOfAsPipe, indexOfEndPipe] = rangeOfBlockParam(source);
return source.substring(indexOfAsPipe, indexOfEndPipe + 1);
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"declarationMap": true,
"sourceMap": true,
"target": "es2019",
"lib": ["es2019", "es2020.string", "dom"],
"lib": ["es2019", "dom"],
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
Expand Down

0 comments on commit eb1e093

Please sign in to comment.