Skip to content

Commit b534580

Browse files
authored
refactor: add detailed comments for mapping (#316)
1 parent f5a008a commit b534580

1 file changed

Lines changed: 160 additions & 45 deletions

File tree

packages/core/src/dts-generator.ts

Lines changed: 160 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -106,28 +106,7 @@ export function generateDts(cssModule: CSSModule, options: GenerateDtsOptions):
106106
}
107107
}
108108

109-
/**
110-
* Generate a d.ts file with named exports.
111-
* @example
112-
* If the CSS module file is:
113-
* ```css
114-
* @import './a.module.css';
115-
* @value local1: string;
116-
* @value imported1, imported2 as aliasedImported2 from './b.module.css';
117-
* .local2 { color: red }
118-
* ```
119-
* The d.ts file would be:
120-
* ```ts
121-
* // @ts-nocheck
122-
* export var local1: string;
123-
* export var local2: string;
124-
* export * from './a.module.css';
125-
* export {
126-
* imported1,
127-
* imported2 as aliasedImported2,
128-
* } from './b.module.css';
129-
* ```
130-
*/
109+
/** Generate a d.ts file with named exports. */
131110
function generateNamedExportsDts(
132111
localTokens: Token[],
133112
tokenImporters: TokenImporter[],
@@ -149,6 +128,25 @@ function generateNamedExportsDts(
149128
let text = `// @ts-nocheck\n`;
150129

151130
for (const token of localTokens) {
131+
/**
132+
* The mapping is created as follows:
133+
* a.module.css:
134+
* 1 | .a_1 { color: red; }
135+
* | ^ mapping.sourceOffsets[0]
136+
* |
137+
* 2 | .a_2 { color: blue; }
138+
* | ^ mapping.sourceOffsets[1]
139+
* |
140+
*
141+
* a.module.css.d.ts:
142+
* 1 | // @ts-nocheck
143+
* 2 | export var a_1: string;
144+
* | ^ mapping.generatedOffsets[0]
145+
* |
146+
* 3 | export var a_2: string;
147+
* | ^ mapping.generatedOffsets[1]
148+
*/
149+
152150
text += `export var `;
153151
mapping.sourceOffsets.push(token.loc.start.offset);
154152
mapping.generatedOffsets.push(text.length);
@@ -157,12 +155,71 @@ function generateNamedExportsDts(
157155
}
158156
for (const tokenImporter of tokenImporters) {
159157
if (tokenImporter.type === 'import') {
158+
/**
159+
* The mapping is created as follows:
160+
* a.module.css:
161+
* 1 | @import './b.module.css';
162+
* | ^ mapping.sourceOffsets[0]
163+
* |
164+
* 2 | @import './c.module.css';
165+
* | ^ mapping.sourceOffsets[1]
166+
* |
167+
*
168+
* a.module.css.d.ts:
169+
* 1 | // @ts-nocheck
170+
* 2 | export * from './b.module.css';
171+
* | ^ mapping.generatedOffsets[0]
172+
* |
173+
* 3 | export * from './c.module.css';
174+
* | ^ mapping.generatedOffsets[1]
175+
*
176+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
177+
*/
178+
160179
text += `export * from `;
161180
mapping.sourceOffsets.push(tokenImporter.fromLoc.start.offset - 1);
162181
mapping.lengths.push(tokenImporter.from.length + 2);
163182
mapping.generatedOffsets.push(text.length);
164183
text += `'${tokenImporter.from}';\n`;
165184
} else {
185+
/**
186+
* The mapping is created as follows:
187+
* a.module.css:
188+
* 1 | @value b_1, b_2 from './b.module.css';
189+
* | ^ ^ ^ mapping.sourceOffsets[2]
190+
* | ^ ^ mapping.sourceOffsets[1]
191+
* | ^ mapping.sourceOffsets[0]
192+
* |
193+
* 2 | @value c_1 as aliased_c_1 from './c.module.css';
194+
* | ^ ^ ^ mapping.sourceOffsets[5]
195+
* | ^ ^ mapping.sourceOffsets[4]
196+
* | ^ mapping.sourceOffsets[3]
197+
* |
198+
*
199+
* a.module.css.d.ts:
200+
* 1 | // @ts-nocheck
201+
* 2 | export {
202+
* 3 | b_1,
203+
* | ^ mapping.generatedOffsets[0]
204+
* |
205+
* 4 | b_2,
206+
* | ^ mapping.generatedOffsets[1]
207+
* |
208+
* 5 | } from './b.module.css';
209+
* | ^ mapping.generatedOffsets[2]
210+
* |
211+
* 6 | export {
212+
* 7 | c_1 as aliased_c_1,
213+
* | ^ ^ mapping.generatedOffsets[4], linkedCodeMapping.sourceOffsets[0]
214+
* | ^ mapping.generatedOffsets[3], linkedCodeMapping.generatedOffsets[0]
215+
* |
216+
* 8 | } from './c.module.css';
217+
* | ^ mapping.generatedOffsets[5]
218+
*
219+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
220+
* NOTE: linkedCodeMapping is only generated for tokens that have a `localName` (i.e., aliased tokens).
221+
*/
222+
166223
text += `export {\n`;
167224
// eslint-disable-next-line no-loop-func
168225
tokenImporter.values.forEach((value) => {
@@ -203,29 +260,7 @@ function generateNamedExportsDts(
203260
return { text, mapping, linkedCodeMapping };
204261
}
205262

206-
/**
207-
* Generate a d.ts file with a default export.
208-
* @example
209-
* If the CSS module file is:
210-
* ```css
211-
* @import './a.module.css';
212-
* @value local1: string;
213-
* @value imported1, imported2 as aliasedImported2 from './b.module.css';
214-
* .local2 { color: red }
215-
* ```
216-
* The d.ts file would be:
217-
* ```ts
218-
* // @ts-nocheck
219-
* const styles = {
220-
* local1: '' as readonly string,
221-
* local2: '' as readonly string,
222-
* ...(await import('./a.module.css')).default,
223-
* imported1: (await import('./b.module.css')).default.imported1,
224-
* aliasedImported2: (await import('./b.module.css')).default.imported2,
225-
* };
226-
* export default styles;
227-
* ```
228-
*/
263+
/** Generate a d.ts file with a default export. */
229264
function generateDefaultExportDts(
230265
localTokens: Token[],
231266
tokenImporters: TokenImporter[],
@@ -256,6 +291,27 @@ function generateDefaultExportDts(
256291

257292
text += `declare const ${STYLES_EXPORT_NAME} = {\n`;
258293
for (const token of localTokens) {
294+
/**
295+
* The mapping is created as follows:
296+
* a.module.css:
297+
* 1 | .a_1 { color: red; }
298+
* | ^ mapping.sourceOffsets[0]
299+
* |
300+
* 2 | .a_2 { color: blue; }
301+
* | ^ mapping.sourceOffsets[1]
302+
* |
303+
*
304+
* a.module.css.d.ts:
305+
* 1 | declare const styles = {
306+
* 2 | a_1: '' as readonly string,
307+
* | ^ mapping.generatedOffsets[0]
308+
* |
309+
* 3 | a_2: '' as readonly string,
310+
* | ^ mapping.generatedOffsets[1]
311+
* |
312+
* 4 | };
313+
*/
314+
259315
text += ` `;
260316
mapping.sourceOffsets.push(token.loc.start.offset);
261317
mapping.generatedOffsets.push(text.length);
@@ -264,12 +320,71 @@ function generateDefaultExportDts(
264320
}
265321
for (const tokenImporter of tokenImporters) {
266322
if (tokenImporter.type === 'import') {
323+
/**
324+
* The mapping is created as follows:
325+
* a.module.css:
326+
* 1 | @import './b.module.css';
327+
* | ^ mapping.sourceOffsets[0]
328+
* |
329+
* 2 | @import './c.module.css';
330+
* | ^ mapping.sourceOffsets[1]
331+
* |
332+
*
333+
* a.module.css.d.ts:
334+
* 1 | declare const styles = {
335+
* 2 | ...blockErrorType((await import('./b.module.css')).default),
336+
* | ^ mapping.generatedOffsets[0]
337+
* |
338+
* 3 | ...blockErrorType((await import('./c.module.css')).default),
339+
* | ^ mapping.generatedOffsets[1]
340+
* |
341+
* 4 | };
342+
*
343+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
344+
*/
345+
267346
text += ` ...blockErrorType((await import(`;
268347
mapping.sourceOffsets.push(tokenImporter.fromLoc.start.offset - 1);
269348
mapping.lengths.push(tokenImporter.from.length + 2);
270349
mapping.generatedOffsets.push(text.length);
271350
text += `'${tokenImporter.from}')).default),\n`;
272351
} else {
352+
/**
353+
* The mapping is created as follows:
354+
* a.module.css:
355+
* 1 | @value b_1, b_2 from './b.module.css';
356+
* | ^ ^ ^ mapping.sourceOffsets[1]
357+
* | ^ ^ mapping.sourceOffsets[3], mapping.sourceOffsets[4]
358+
* | ^ mapping.sourceOffsets[0], mapping.sourceOffsets[2]
359+
* |
360+
* 2 | @value c_1 as aliased_c_1 from './c.module.css';
361+
* | ^ ^ ^ mapping.sourceOffsets[6]
362+
* | ^ ^ mapping.sourceOffsets[5]
363+
* | ^ mapping.sourceOffsets[7]
364+
* |
365+
*
366+
* a.module.css.d.ts:
367+
* 1 | declare const styles = {
368+
* 2 | b_1: (await import('./b.module.css')).default.b_1,
369+
* | ^ ^ ^ mapping.generatedOffsets[2], linkedCodeMapping.generatedOffsets[0]
370+
* | ^ ^ mapping.generatedOffsets[1]
371+
* | ^ mapping.generatedOffsets[0], linkedCodeMapping.sourceOffsets[0]
372+
* |
373+
* 3 | b_2: (await import('./b.module.css')).default.b_2,
374+
* | ^ ^ mapping.generatedOffsets[4], linkedCodeMapping.generatedOffsets[1]
375+
* | ^ mapping.generatedOffsets[3], linkedCodeMapping.sourceOffsets[1]
376+
* |
377+
* 4 | aliased_c_1: (await import('./c.module.css')).default.c_1,
378+
* | ^ ^ ^ mapping.generatedOffsets[7], linkedCodeMapping.generatedOffsets[2]
379+
* | ^ ^ mapping.generatedOffsets[6]
380+
* | ^ mapping.generatedOffsets[5], linkedCodeMapping.sourceOffsets[2]
381+
* |
382+
* 5 | };
383+
*
384+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
385+
* TODO: Stop generating unnecessary mappings for tokens that do not have a `localName`.
386+
*/
387+
273388
// eslint-disable-next-line no-loop-func
274389
tokenImporter.values.forEach((value, i) => {
275390
const localName = value.localName ?? value.name;

0 commit comments

Comments
 (0)