Skip to content
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
5 changes: 4 additions & 1 deletion blank.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,10 @@ function substituteSelfClosingComponent(
if (sourceLen < minLen) {
return false;
}
const inner = ' '.repeat(sourceLen - minLen);
// Keep the span's newlines inside the element, so later lines keep
// their line numbers.
const newlines = ctx.content.slice(elementStart, elementEnd).replace(/[^\r\n]/g, '').slice(0, sourceLen - minLen);
const inner = newlines + ' '.repeat(sourceLen - minLen - newlines.length);
ctx.renames.push([elementStart, elementEnd, openTag + inner + closeTag]);
ctx.fullyBlankedRanges.push([elementStart, elementEnd]);
ctx.dynamicContentOffsets.push(elementStart);
Expand Down
14 changes: 14 additions & 0 deletions examples/multiline-self-closing-consumer.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// The self-closing call spans five lines. The untyped `<button>` after
// it must be reported on its own source line.
import InfoPopover from '../test/glint-fixtures/info-popover-leaf.gts';

<template>
<section>
<InfoPopover
@popoverId='equipment-info-popover-for-the-selected-row'
@label='Details about the equipment in the selected row of the table'
class='mt-2'
/>
<button>Save</button>
</section>
</template>
17 changes: 17 additions & 0 deletions test/glint-fixtures/info-popover-leaf.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// A non-void root with a long literal open tag. A self-closing call
// substitutes to `<div popover='auto' class='…'></div>`, which is longer
// than the first line of a multi-line call.
import type { TemplateOnlyComponent } from '@ember/component/template-only';

interface InfoPopoverSig {
Element: HTMLDivElement;
Args: { popoverId: string; label: string };
}

const InfoPopover: TemplateOnlyComponent<InfoPopoverSig> = <template>
<div popover='auto' id={{@popoverId}} class='m-0 w-72 rounded-xl bg-white p-4 text-sm text-gray-900' ...attributes>
{{@label}}
</div>
</template>;

export default InfoPopover;
13 changes: 13 additions & 0 deletions test/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,19 @@ describe('end-to-end fixtures', () => {
}
});

it.each(['1', '0'])('multiline-self-closing-consumer: a substituted self-closing call keeps its newlines, so later errors report the source line (HVE_GLINT=%s)', async (glint) => {
const prevGlint = process.env['HVE_GLINT'];
process.env['HVE_GLINT'] = glint;
try {
const r = await validate('multiline-self-closing-consumer.gts');
const buttonType = r.messages.filter((m) => m.rule === 'no-implicit-button-type');
expect(buttonType.map((m) => `${m.line}:${m.column}`), JSON.stringify(r.messages)).toEqual(['12:6']);
} finally {
if (prevGlint === undefined) delete process.env['HVE_GLINT'];
else process.env['HVE_GLINT'] = prevGlint;
}
});

it('multi-yield-table-consumer: wrapper with multi-yield template (different ancestors per named block) substitutes to outer wrapper, not first yield-ancestor', async () => {
// Mirrors HDS `<HdsTable>` shape — its template yields to BOTH
// `to="head"` (inside `<thead>`) and `to="body"` (inside
Expand Down
Loading