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
33 changes: 12 additions & 21 deletions src/parse/preprocess.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
getBuffer,
parse,
type Range,
replaceContents,
sliceByteRange,
} from '../utils/content-tag.js';
import { parse, type Range, sliceByteRange } from '../utils/content-tag.js';

export interface Template {
contentRange: Range;
Expand All @@ -17,8 +11,6 @@ export interface Template {
};
}

const PLACEHOLDER = '~';

/**
* Replace the template with a parsable placeholder that takes up the same
* range.
Expand All @@ -27,6 +19,9 @@ export function preprocessTemplateRange(
template: Template,
code: string,
): string {
const { start, end } = template.utf16Range;
const after = code.slice(end);

let prefix: string;
let suffix: string;

Expand All @@ -39,7 +34,7 @@ export function preprocessTemplateRange(
prefix = '{/*';
suffix = '*/}';

const nextToken = sliceByteRange(code, template.range.endByte).match(/\S+/);
const nextToken = after.match(/\S+/);

if (nextToken && (nextToken[0] === 'as' || nextToken[0] === 'satisfies')) {
// Replace with parenthesized ObjectExpression
Expand All @@ -48,18 +43,14 @@ export function preprocessTemplateRange(
}
}

// We need to replace forward slash with _something else_, because
// forward slash breaks the parsed templates.
const contents = template.contents.replaceAll('/', PLACEHOLDER);
const before = code.slice(0, start);
const spaces = code
.slice(start + prefix.length, end - suffix.length)
// Replace everything except `\n` with space, so the line and column remain correct
// Prettier normalized EOL to `\n`, so we don't need worry about `\r` and `\r\n`
.replaceAll(/[^\n]/g, ' ');

const templateLength = template.range.endByte - template.range.startByte;
const spaces =
templateLength - getBuffer(contents).length - prefix.length - suffix.length;

return replaceContents(code, {
contents: [prefix, contents, ' '.repeat(spaces), suffix].join(''),
range: template.range,
});
return before + prefix + spaces + suffix + after;
}

/** Pre-processes the template info, parsing the template content to Glimmer AST. */
Expand Down
16 changes: 0 additions & 16 deletions src/utils/content-tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,6 @@ export function parse(
return preprocessor.parse(file, options);
}

export function replaceContents(
file: string,
options: {
contents: string;
range: Range;
},
): string {
const { contents, range } = options;

return [
sliceByteRange(file, 0, range.startByte),
contents,
sliceByteRange(file, range.endByte),
].join('');
}

export function sliceByteRange(
string_: string,
indexStart: number,
Expand Down
22 changes: 11 additions & 11 deletions tests/unit-tests/preprocess.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,40 @@ import {
const TEST_CASES = [
{
code: '<template>hi</template>',
expected: [`{/*hi */}`],
expected: [`{/* */}`],
},
{
code: '<template>/* hi */</template>',
expected: [`{/*~* hi *~ */}`],
expected: [`{/* */}`],
},
{
code: '<template><div>hi</div></template>',
expected: [`{/*<div>hi<~div> */}`],
expected: [`{/* */}`],
},
{
code: '<template>{{#if true}}hi{{/if}}</template>',
expected: [`{/*{{#if true}}hi{{~if}} */}`],
expected: [`{/* */}`],
},
{
code: '<template>////////////////</template>',
expected: [`{/*~~~~~~~~~~~~~~~~ */}`],
code: '<template>////////\n////////</template>',
expected: [`{/* \n */}`],
},
{
code: '<template>💩</template>',
expected: [`{/*💩 */}`],
expected: [`{/* */}`],
},
{
code: 'const a = <template>foo</template>; const b = <template>bar</template>;',
expected: [
`const a = {/*foo */}; const b = <template>bar</template>;`,
`const a = <template>foo</template>; const b = {/*bar */};`,
`const a = {/* */}; const b = <template>bar</template>;`,
`const a = <template>foo</template>; const b = {/* */};`,
],
},
{
code: `const a = <template>💩💩💩💩💩💩💩</template>; const b = <template>💩</template>`,
expected: [
`const a = {/*💩💩💩💩💩💩💩 */}; const b = <template>💩</template>`,
`const a = <template>💩💩💩💩💩💩💩</template>; const b = {/*💩 */}`,
`const a = {/* */}; const b = <template>💩</template>`,
`const a = <template>💩💩💩💩💩💩💩</template>; const b = {/* */}`,
],
},
];
Expand Down