0
# Source Map Support
1
2
Comprehensive source map generation, manipulation, and serialization with inline embedding support for debugging workflows. Provides utilities for converting between different source map formats and generating inline source map comments.
3
4
## Capabilities
5
6
### Source Map Conversion
7
8
Converts source maps to a standardized format with both raw and inline representations.
9
10
```typescript { .api }
11
/**
12
* Converts a source map to standardized format with inline support
13
* @param map - Source map as decoded object or JSON string
14
* @returns SourceMap object with raw and inline representations
15
*/
16
function toSourceMap(map: DecodedSourceMap | string): SourceMap;
17
18
interface SourceMap {
19
/** Raw source map as JSON string */
20
readonly raw: string;
21
/** Inline source map comment for embedding in CSS/JS */
22
readonly inline: string;
23
}
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import { toSourceMap } from "@tailwindcss/node";
30
31
// Convert from JSON string
32
const sourceMapJson = JSON.stringify({
33
version: 3,
34
sources: ["input.css"],
35
names: [],
36
mappings: "AAAA,UAAU,CAAC,KAAK,CAAC"
37
});
38
39
const sourceMap = toSourceMap(sourceMapJson);
40
41
console.log(sourceMap.raw); // Original JSON string
42
console.log(sourceMap.inline); // /*# sourceMappingURL=data:application/json;base64,... */
43
44
// Convert from decoded source map
45
const decodedMap: DecodedSourceMap = {
46
mappings: [
47
{
48
generatedPosition: { line: 1, column: 0 },
49
originalPosition: {
50
line: 1,
51
column: 0,
52
source: { url: "input.css", content: ".container { color: red; }" }
53
}
54
}
55
]
56
};
57
58
const convertedMap = toSourceMap(decodedMap);
59
console.log(convertedMap.raw);
60
```
61
62
### Inline Source Map Usage
63
64
The inline source map format is ready for direct embedding in CSS or JavaScript files:
65
66
```typescript
67
import { toSourceMap, optimize } from "@tailwindcss/node";
68
69
const css = ".container { display: flex; }";
70
const optimized = optimize(css, {
71
minify: true,
72
file: "styles.css"
73
});
74
75
if (optimized.map) {
76
const sourceMap = toSourceMap(optimized.map);
77
78
// Embed inline source map
79
const cssWithSourceMap = optimized.code + "\n" + sourceMap.inline;
80
81
console.log(cssWithSourceMap);
82
// Output:
83
// .container{display:flex}
84
// /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLC... */
85
}
86
```
87
88
## Type Definitions
89
90
### DecodedSourceMap Type
91
92
Represents a decoded source map with detailed mapping information.
93
94
```typescript { .api }
95
interface DecodedSourceMap {
96
/** Array of source mappings between generated and original positions */
97
mappings: Array<{
98
/** Position in generated file */
99
generatedPosition: { line: number; column: number };
100
/** Position in original file (if available) */
101
originalPosition?: {
102
line: number;
103
column: number;
104
source: DecodedSource
105
};
106
/** Original identifier name (if available) */
107
name?: string;
108
}>;
109
}
110
```
111
112
### DecodedSource Type
113
114
Represents source file information within a source map.
115
116
```typescript { .api }
117
interface DecodedSource {
118
/** URL or path to the source file */
119
url: string;
120
/** Original source file content */
121
content: string;
122
}
123
```
124
125
## Advanced Usage
126
127
### Working with Complex Source Maps
128
129
```typescript
130
import { toSourceMap, type DecodedSourceMap, type DecodedSource } from "@tailwindcss/node";
131
132
// Create a complex source map with multiple sources
133
const mainSource: DecodedSource = {
134
url: "components/button.css",
135
content: ".btn { padding: 0.5rem; }"
136
};
137
138
const utilitySource: DecodedSource = {
139
url: "utilities/spacing.css",
140
content: ".p-2 { padding: 0.5rem; }"
141
};
142
143
const complexMap: DecodedSourceMap = {
144
mappings: [
145
{
146
generatedPosition: { line: 1, column: 0 },
147
originalPosition: {
148
line: 1,
149
column: 0,
150
source: mainSource
151
}
152
},
153
{
154
generatedPosition: { line: 2, column: 0 },
155
originalPosition: {
156
line: 1,
157
column: 0,
158
source: utilitySource
159
},
160
name: "utility-class"
161
}
162
]
163
};
164
165
const sourceMap = toSourceMap(complexMap);
166
console.log(sourceMap.raw);
167
```
168
169
### Source Map Serialization Process
170
171
The internal serialization process handles source deduplication and proper formatting:
172
173
```typescript
174
import { toSourceMap } from "@tailwindcss/node";
175
176
// Sources are automatically deduplicated and assigned unique URLs
177
const mapWithDuplicates: DecodedSourceMap = {
178
mappings: [
179
{
180
generatedPosition: { line: 1, column: 0 },
181
originalPosition: {
182
line: 1,
183
column: 0,
184
source: { url: "same.css", content: "content" }
185
}
186
},
187
{
188
generatedPosition: { line: 2, column: 0 },
189
originalPosition: {
190
line: 2,
191
column: 0,
192
source: { url: "same.css", content: "content" } // Same source
193
}
194
}
195
]
196
};
197
198
const result = toSourceMap(mapWithDuplicates);
199
// Sources are properly deduplicated in the output
200
```
201
202
### Handling Missing Sources
203
204
The system gracefully handles mappings with missing source information:
205
206
```typescript
207
import { toSourceMap, type DecodedSourceMap } from "@tailwindcss/node";
208
209
const mapWithMissingSources: DecodedSourceMap = {
210
mappings: [
211
{
212
generatedPosition: { line: 1, column: 0 },
213
// No originalPosition - generates placeholder
214
},
215
{
216
generatedPosition: { line: 2, column: 0 },
217
originalPosition: {
218
line: 1,
219
column: 0,
220
source: null as any // Missing source
221
}
222
}
223
]
224
};
225
226
const result = toSourceMap(mapWithMissingSources);
227
// Missing sources get placeholder names like "<unknown 1>"
228
```
229
230
## Integration with Build Tools
231
232
### Webpack Integration
233
234
```typescript
235
import { toSourceMap } from "@tailwindcss/node";
236
237
// In a webpack loader
238
module.exports = function(source: string) {
239
const callback = this.async();
240
241
// Process CSS...
242
const processed = processCss(source);
243
244
if (processed.map) {
245
const sourceMap = toSourceMap(processed.map);
246
callback(null, processed.code, JSON.parse(sourceMap.raw));
247
} else {
248
callback(null, processed.code);
249
}
250
};
251
```
252
253
### Vite Integration
254
255
```typescript
256
import { toSourceMap } from "@tailwindcss/node";
257
258
// In a Vite plugin
259
export function tailwindNodePlugin() {
260
return {
261
name: "tailwind-node",
262
transform(code: string, id: string) {
263
if (id.endsWith(".css")) {
264
const result = processCss(code);
265
266
if (result.map) {
267
const sourceMap = toSourceMap(result.map);
268
return {
269
code: result.code,
270
map: JSON.parse(sourceMap.raw)
271
};
272
}
273
274
return { code: result.code };
275
}
276
}
277
};
278
}
279
```
280
281
## Browser DevTools Support
282
283
The generated source maps are fully compatible with browser developer tools:
284
285
```typescript
286
import { toSourceMap } from "@tailwindcss/node";
287
288
const sourceMap = toSourceMap(map);
289
290
// The inline format is automatically recognized by browsers
291
const cssWithMap = cssCode + "\n" + sourceMap.inline;
292
293
// Or use external source map file
294
const externalMapUrl = "/*# sourceMappingURL=styles.css.map */";
295
const cssWithExternal = cssCode + "\n" + externalMapUrl;
296
297
// Write the source map file
298
fs.writeFileSync("styles.css.map", sourceMap.raw);
299
```