1- import { Preprocessor } from 'content-tag' ;
1+ import {
2+ getBuffer ,
3+ parse ,
4+ type Range ,
5+ replaceContents ,
6+ sliceByteRange ,
7+ } from '../utils/content-tag.js' ;
28
39export interface Template {
10+ contentRange : Range ;
411 contents : string ;
5- type : string ;
6- range : {
7- start : number ;
8- end : number ;
9- } ;
12+ range : Range ;
13+ type : 'class-member' | 'expression' ;
1014 utf16Range : {
11- start : number ;
1215 end : number ;
16+ start : number ;
1317 } ;
1418}
1519
16- const BufferMap : Map < string , Buffer > = new Map ( ) ;
17-
1820const PLACEHOLDER = '~' ;
1921
20- function getBuffer ( s : string ) : Buffer {
21- let buf = BufferMap . get ( s ) ;
22- if ( ! buf ) {
23- buf = Buffer . from ( s ) ;
24- BufferMap . set ( s , buf ) ;
25- }
26- return buf ;
27- }
28-
29- /** Slice string using byte range */
30- function sliceByteRange ( s : string , a : number , b ?: number ) : string {
31- const buf = getBuffer ( s ) ;
32- return buf . subarray ( a , b ) . toString ( ) ;
33- }
34-
35- /** Converts byte index to js char index (utf16) */
36- function byteToCharIndex ( s : string , byteOffset : number ) : number {
37- const buf = getBuffer ( s ) ;
38- return buf . subarray ( 0 , byteOffset ) . toString ( ) . length ;
39- }
40-
41- /** Calculate byte length */
42- function byteLength ( s : string ) : number {
43- return getBuffer ( s ) . length ;
44- }
45-
46- function replaceRange (
47- s : string ,
48- start : number ,
49- end : number ,
50- substitute : string ,
51- ) : string {
52- return sliceByteRange ( s , 0 , start ) + substitute + sliceByteRange ( s , end ) ;
53- }
54-
5522/**
5623 * Replace the template with a parsable placeholder that takes up the same
5724 * range.
@@ -72,7 +39,7 @@ export function preprocessTemplateRange(
7239 prefix = '{/*' ;
7340 suffix = '*/}' ;
7441
75- const nextToken = code . slice ( template . range . end ) . toString ( ) . match ( / \S + / ) ;
42+ const nextToken = sliceByteRange ( code , template . range . endByte ) . match ( / \S + / ) ;
7643
7744 if ( nextToken && ( nextToken [ 0 ] === 'as' || nextToken [ 0 ] === 'satisfies' ) ) {
7845 // Replace with parenthesized ObjectExpression
@@ -83,32 +50,38 @@ export function preprocessTemplateRange(
8350
8451 // We need to replace forward slash with _something else_, because
8552 // forward slash breaks the parsed templates.
86- const content = template . contents . replaceAll ( '/' , PLACEHOLDER ) ;
53+ const contents = template . contents . replaceAll ( '/' , PLACEHOLDER ) ;
8754
88- const tplLength = template . range . end - template . range . start ;
55+ const templateLength = template . range . endByte - template . range . startByte ;
8956 const spaces =
90- tplLength - byteLength ( content ) - prefix . length - suffix . length ;
91- const total = prefix + content + ' ' . repeat ( spaces ) + suffix ;
57+ templateLength - getBuffer ( contents ) . length - prefix . length - suffix . length ;
9258
93- return replaceRange ( code , template . range . start , template . range . end , total ) ;
59+ return replaceContents ( code , {
60+ contents : [ prefix , contents , ' ' . repeat ( spaces ) , suffix ] . join ( '' ) ,
61+ range : template . range ,
62+ } ) ;
9463}
9564
96- const p = new Preprocessor ( ) ;
97-
9865/** Pre-processes the template info, parsing the template content to Glimmer AST. */
9966export function codeToGlimmerAst ( code : string , filename : string ) : Template [ ] {
100- const rawTemplates = p . parse ( code , { filename } ) ;
101-
102- const templates : Template [ ] = rawTemplates . map ( ( r ) => ( {
103- type : r . type ,
104- range : r . range ,
105- contentRange : r . contentRange ,
106- contents : r . contents ,
107- utf16Range : {
108- start : byteToCharIndex ( code , r . range . start ) ,
109- end : byteToCharIndex ( code , r . range . end ) ,
110- } ,
111- } ) ) ;
67+ const contentTags = parse ( code , { filename } ) ;
68+
69+ const templates : Template [ ] = contentTags . map ( ( contentTag ) => {
70+ const { contentRange, contents, range, type } = contentTag ;
71+
72+ const utf16Range = {
73+ end : sliceByteRange ( code , 0 , range . endByte ) . length ,
74+ start : sliceByteRange ( code , 0 , range . startByte ) . length ,
75+ } ;
76+
77+ return {
78+ contentRange,
79+ contents,
80+ range,
81+ type,
82+ utf16Range,
83+ } ;
84+ } ) ;
11285
11386 return templates ;
11487}
0 commit comments