import postcss from 'postcss' import { parseSourceMaps } from './util/source-maps' import { runWithSourceMaps as run, html, css, map } from './util/run' test('apply generates source maps', async () => { let config = { content: [ { raw: html`
`, }, ], corePlugins: { preflight: false }, } let input = css` .with-declaration { background-color: red; @apply h-4 w-4 bg-green-500; } .with-comment { /* sourcemap will work here too */ @apply h-4 w-4 bg-red-500; } .just-apply { @apply h-4 w-4 bg-black; } ` let result = await run(input, config) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') expect(sources.length).toBe(2) expect(annotations).toMatchInlineSnapshot(` [ "2:4 -> 1:0-65", "2:0 -> 2:0", "3:2-20 -> 3:2-20", "4:2-23 -> 4:2-23", "5:2-57 -> 5:2-57", "6:2-13 -> 6:2-13", "7:2-14 -> 7:2-14", "8:0 -> 8:0", "10:0 -> 10:0", "11:2-20 -> 11:2-20", "12:2-57 -> 12:2-57", "13:2-13 -> 13:2-13", "14:2-14 -> 14:2-14", "15:0 -> 15:0", "17:0 -> 17:0", "18:2-20 -> 18:2-20", "19:2-53 -> 19:2-53", "20:2-13 -> 20:2-13", "21:2-14 -> 21:2-14", "22:0 -> 22:0", ] `) }) test('preflight + base have source maps', async () => { let config = { content: [], } let input = css` @tailwind base; ` let result = await run(input, config) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') expect(sources.length).toBe(2) expect(annotations).toMatchInlineSnapshot(` [ "2:4 -> 1:0-65", "2:0 -> 2:0", "3:2-24 -> 3:2-24", "4:2-25 -> 4:2-25", "5:0 -> 5:0", "7:0 -> 7:0", "8:2-18 -> 8:2-18", "9:0 -> 9:0", "11:0 -> 11:0", "12:2-32 -> 12:2-32", "13:2-13 -> 13:2-13", "14:2-31 -> 14:2-31", "15:2-33 -> 15:2-33", "16:2-121 -> 16:2-121", "17:2-18 -> 17:2-18", "18:0 -> 18:0", "20:0 -> 20:0", "21:2-22 -> 21:2-22", "22:2-11 -> 22:2-11", "23:0 -> 23:0", "25:0 -> 25:0", "26:2-16 -> 26:2-16", "27:2-23 -> 27:2-23", "28:2-11 -> 28:2-11", "29:0 -> 29:0", "31:0 -> 31:0", "32:2-43 -> 32:2-43", "33:2-35 -> 33:2-35", "34:0 -> 34:0", "36:0 -> 36:0", "37:2-20 -> 37:2-20", "38:2-22 -> 38:2-22", "39:0 -> 39:0", "41:0 -> 41:0", "42:2-16 -> 42:2-16", "43:2-34 -> 43:2-34", "44:2-26 -> 44:2-26", "45:0 -> 45:0", "47:0 -> 47:0", "48:2-21 -> 48:2-21", "49:0 -> 49:0", "51:0 -> 51:0", "52:2-109 -> 52:2-109", "53:2-16 -> 53:2-16", "54:0 -> 54:0", "56:0 -> 56:0", "57:2-16 -> 57:2-16", "58:0 -> 58:0", "60:0 -> 60:0", "61:2-26 -> 61:2-26", "62:2-16 -> 62:2-16", "63:2-16 -> 63:2-16", "64:2-20 -> 64:2-20", "65:0 -> 65:0", "67:0 -> 67:0", "68:2-16 -> 68:2-16", "69:0 -> 69:0", "71:0 -> 71:0", "72:2-12 -> 72:2-12", "73:0 -> 73:0", "75:0 -> 75:0", "76:2-16 -> 76:2-16", "77:2-23 -> 77:2-23", "78:2-27 -> 78:2-27", "79:0 -> 79:0", "81:0 -> 81:0", "82:2-32 -> 82:2-32", "83:2-34 -> 83:2-34", "84:2-22 -> 84:2-22", "85:2-17 -> 85:2-17", "86:2-22 -> 86:2-22", "87:2-22 -> 87:2-22", "88:2-16 -> 88:2-16", "89:2-11 -> 89:2-11", "90:2-12 -> 90:2-12", "91:0 -> 91:0", "93:0 -> 93:0", "94:2-22 -> 94:2-22", "95:0 -> 95:0", "97:0 -> 97:0", "98:2-28 -> 98:2-28", "99:2-25 -> 99:2-25", "100:2-24 -> 100:2-24", "101:0 -> 101:0", "103:0 -> 103:0", "104:2-15 -> 104:2-15", "105:0 -> 105:0", "107:0 -> 107:0", "108:2-18 -> 108:2-18", "109:0 -> 109:0", "111:0 -> 111:0", "112:2-26 -> 112:2-26", "113:0 -> 113:0", "115:0 -> 115:0", "116:2-14 -> 116:2-14", "117:0 -> 117:0", "119:0 -> 119:0", "120:2-14 -> 120:2-14", "121:0 -> 121:0", "123:0 -> 123:0", "124:2-31 -> 124:2-31", "125:2-22 -> 125:2-22", "126:0 -> 126:0", "128:0 -> 128:0", "129:2-26 -> 129:2-26", "130:0 -> 130:0", "132:0 -> 132:0", "133:2-28 -> 133:2-28", "134:2-15 -> 134:2-15", "135:0 -> 135:0", "137:0 -> 137:0", "138:2-20 -> 138:2-20", "139:0 -> 139:0", "141:0 -> 141:0", "142:2-11 -> 142:2-11", "143:0 -> 143:0", "145:0 -> 145:0", "146:2-11 -> 146:2-11", "147:2-12 -> 147:2-12", "148:0 -> 148:0", "150:0 -> 150:0", "151:2-12 -> 151:2-12", "152:0 -> 152:0", "154:0 -> 154:0", "155:2-11 -> 155:2-11", "156:2-12 -> 156:2-12", "157:2-18 -> 157:2-18", "158:0 -> 158:0", "160:0 -> 160:0", "161:2-12 -> 161:2-12", "162:0 -> 162:0", "164:0 -> 164:0", "165:2-18 -> 165:2-18", "166:0 -> 166:0", "168:0 -> 168:0", "169:2-12 -> 169:2-12", "170:2-16 -> 170:2-16", "171:0 -> 171:0", "173:0 -> 173:0", "174:2-17 -> 174:2-17", "175:0 -> 175:0", "177:0 -> 177:0", "178:2-17 -> 178:2-17", "179:0 -> 179:0", "181:0 -> 181:0", "182:2-24 -> 182:2-24", "183:2-16 -> 183:2-16", "184:0 -> 184:0", "186:0 -> 186:0", "187:2-17 -> 187:2-17", "188:2-14 -> 188:2-14", "189:0 -> 189:0", "191:0 -> 191:0", "192:2-15 -> 192:2-15", "193:0 -> 193:0", "195:0 -> 195:0", "196:2-26 -> 196:2-26", "197:2-26 -> 197:2-26", "198:2-21 -> 198:2-21", "199:2-21 -> 199:2-21", "200:2-16 -> 200:2-16", "201:2-16 -> 201:2-16", "202:2-16 -> 202:2-16", "203:2-17 -> 203:2-17", "204:2-17 -> 204:2-17", "205:2-14 -> 205:2-14", "206:2-14 -> 206:2-14", "207:2-19 -> 207:2-19", "208:2-40 -> 208:2-40", "209:2-31 -> 209:2-31", "210:2-30 -> 210:2-30", "211:2-29 -> 211:2-29", "212:2-16 -> 212:2-16", "213:2-21 -> 213:2-21", "214:2-23 -> 214:2-23", "215:2-24 -> 215:2-24", "216:2-25 -> 216:2-25", "217:2-19 -> 217:2-19", "218:2-29 -> 218:2-29", "219:2-30 -> 219:2-30", "220:2-28 -> 220:2-28", "221:2-36 -> 221:2-36", "222:2-29 -> 222:2-29", "223:2-24 -> 223:2-24", "224:2-32 -> 224:2-32", "225:2-13 -> 225:2-13", "226:2-19 -> 226:2-19", "227:2-17 -> 227:2-17", "228:2-18 -> 228:2-18", "229:2-19 -> 229:2-19", "230:2-15 -> 230:2-15", "231:2-17 -> 231:2-17", "232:2-14 -> 232:2-14", "233:2-20 -> 233:2-20", "234:2-22 -> 234:2-22", "235:2-28 -> 235:2-28", "236:2-26 -> 236:2-26", "237:2-27 -> 237:2-27", "238:2-28 -> 238:2-28", "239:2-24 -> 239:2-24", "240:2-25 -> 240:2-25", "241:2-26 -> 241:2-26", "242:2-23 -> 242:2-23", "243:0 -> 243:0", "245:0 -> 245:0", "246:2-26 -> 246:2-26", "247:2-26 -> 247:2-26", "248:2-21 -> 248:2-21", "249:2-21 -> 249:2-21", "250:2-16 -> 250:2-16", "251:2-16 -> 251:2-16", "252:2-16 -> 252:2-16", "253:2-17 -> 253:2-17", "254:2-17 -> 254:2-17", "255:2-14 -> 255:2-14", "256:2-14 -> 256:2-14", "257:2-19 -> 257:2-19", "258:2-40 -> 258:2-40", "259:2-31 -> 259:2-31", "260:2-30 -> 260:2-30", "261:2-29 -> 261:2-29", "262:2-16 -> 262:2-16", "263:2-21 -> 263:2-21", "264:2-23 -> 264:2-23", "265:2-24 -> 265:2-24", "266:2-25 -> 266:2-25", "267:2-19 -> 267:2-19", "268:2-29 -> 268:2-29", "269:2-30 -> 269:2-30", "270:2-28 -> 270:2-28", "271:2-36 -> 271:2-36", "272:2-29 -> 272:2-29", "273:2-24 -> 273:2-24", "274:2-32 -> 274:2-32", "275:2-13 -> 275:2-13", "276:2-19 -> 276:2-19", "277:2-17 -> 277:2-17", "278:2-18 -> 278:2-18", "279:2-19 -> 279:2-19", "280:2-15 -> 280:2-15", "281:2-17 -> 281:2-17", "282:2-14 -> 282:2-14", "283:2-20 -> 283:2-20", "284:2-22 -> 284:2-22", "285:2-28 -> 285:2-28", "286:2-26 -> 286:2-26", "287:2-27 -> 287:2-27", "288:2-28 -> 288:2-28", "289:2-24 -> 289:2-24", "290:2-25 -> 290:2-25", "291:2-26 -> 291:2-26", "292:2-23 -> 292:2-23", "293:0 -> 293:0", "295:0 -> 295:0", "296:2-26 -> 296:2-26", "297:2-26 -> 297:2-26", "298:2-21 -> 298:2-21", "299:2-21 -> 299:2-21", "300:2-16 -> 300:2-16", "301:2-16 -> 301:2-16", "302:2-16 -> 302:2-16", "303:2-17 -> 303:2-17", "304:2-17 -> 304:2-17", "305:2-14 -> 305:2-14", "306:2-14 -> 306:2-14", "307:2-19 -> 307:2-19", "308:2-40 -> 308:2-40", "309:2-31 -> 309:2-31", "310:2-30 -> 310:2-30", "311:2-29 -> 311:2-29", "312:2-16 -> 312:2-16", "313:2-21 -> 313:2-21", "314:2-23 -> 314:2-23", "315:2-24 -> 315:2-24", "316:2-25 -> 316:2-25", "317:2-19 -> 317:2-19", "318:2-29 -> 318:2-29", "319:2-30 -> 319:2-30", "320:2-28 -> 320:2-28", "321:2-36 -> 321:2-36", "322:2-29 -> 322:2-29", "323:2-24 -> 323:2-24", "324:2-32 -> 324:2-32", "325:2-13 -> 325:2-13", "326:2-19 -> 326:2-19", "327:2-17 -> 327:2-17", "328:2-18 -> 328:2-18", "329:2-19 -> 329:2-19", "330:2-15 -> 330:2-15", "331:2-17 -> 331:2-17", "332:2-14 -> 332:2-14", "333:2-20 -> 333:2-20", "334:2-22 -> 334:2-22", "335:2-28 -> 335:2-28", "336:2-26 -> 336:2-26", "337:2-27 -> 337:2-27", "338:2-28 -> 338:2-28", "339:2-24 -> 339:2-24", "340:2-25 -> 340:2-25", "341:2-26 -> 341:2-26", "342:2-23 -> 342:2-23", "343:0 -> 343:0", ] `) }) test('utilities have source maps', async () => { let config = { content: [{ raw: `text-red-500` }], } let input = css` @tailwind utilities; ` let result = await run(input, config) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') expect(sources.length).toBe(2) expect(annotations).toMatchInlineSnapshot(` [ "2:4 -> 1:0-65", "2:0 -> 2:0", "3:2-22 -> 3:2-22", "4:2-48 -> 4:2-48", "5:0 -> 5:0", ] `) }) test('components have source maps', async () => { let config = { content: [{ raw: `container` }], } let input = css` @tailwind components; ` let result = await run(input, config) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') expect(sources.length).toBe(2) expect(annotations).toMatchInlineSnapshot(` [ "2:4 -> 1:0-65", "2:0 -> 2:0", "3:2-13 -> 3:2-13", "4:0 -> 4:0", "6:0 -> 6:0", "7:2 -> 7:2", "8:4-20 -> 8:4-20", "9:2 -> 9:2", "10:0 -> 10:0", "12:0 -> 12:0", "13:2 -> 13:2", "14:4-20 -> 14:4-20", "15:2 -> 15:2", "16:0 -> 16:0", "18:0 -> 18:0", "19:2 -> 19:2", "20:4-21 -> 20:4-21", "21:2 -> 21:2", "22:0 -> 22:0", "24:0 -> 24:0", "25:2 -> 25:2", "26:4-21 -> 26:4-21", "27:2 -> 27:2", "28:0 -> 28:0", "30:0 -> 30:0", "31:2 -> 31:2", "32:4-21 -> 32:4-21", "33:2 -> 33:2", "34:0 -> 34:0", ] `) }) test('source maps for layer rules are not rewritten to point to @tailwind directives', async () => { let config = { content: [{ raw: `font-normal foo hover:foo` }], } let utilitiesFile = postcss.parse( css` @tailwind utilities; `, { from: 'components.css', map: { prev: map } } ) let mainCssFile = postcss.parse( css` @layer utilities { .foo { background-color: red; } } `, { from: 'input.css', map: { prev: map } } ) // Just pretend that there's an @import in `mainCssFile` that imports the nodes from `utilitiesFile` let input = postcss.root({ nodes: [...utilitiesFile.nodes, ...mainCssFile.nodes], source: mainCssFile.source, }) let result = await run(input, config) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') // And we should see that the source map for the layer rule is not rewritten // to point to the @tailwind directive but instead points to the original expect(sources.length).toBe(2) expect(sources).toMatchInlineSnapshot(` [ "components.css", "source-maps.test.js%3Ftest=c291cmNlIG1hcHMgZm9yIGxheWVyIHJ1bGVzIGFyZSBub3QgcmV3cml0dGVuIHRvIHBvaW50IHRvIEB0YWlsd2luZCBkaXJlY3RpdmVz", ] `) expect(annotations).toMatchInlineSnapshot(` [ "2:6 -> 1:0-65", "2:0 -> 2:0", "3:2-18 -> 3:2-18", "4:0 -> 4:0", "6:0 -> 6:0", "7:2-23 -> 7:2-23", "8:0 -> 8:0", ] `) }) test('it handles `map: true` correctly', async () => { let config = { content: [{ raw: `text-red-500` }], } let input = css` @tailwind utilities; ` let result = await run(input, config, { map: true, }) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') expect(sources.length).toBe(2) expect(annotations).toMatchInlineSnapshot(` [ "2:4 -> 1:0-65", "2:0 -> 2:0", "3:2-22 -> 3:2-22", "4:2-48 -> 4:2-48", "5:0 -> 5:0", ] `) }) test('it handles `map: { inline: true }` correctly', async () => { let config = { content: [{ raw: `text-red-500` }], } let input = css` @tailwind utilities; ` let result = await run(input, config, { map: { inline: true, }, }) let { sources, annotations } = parseSourceMaps(result) // All CSS generated by Tailwind CSS should be annotated with source maps // And always be able to point to the original source file expect(sources).not.toContain('') expect(sources.length).toBe(2) expect(annotations).toMatchInlineSnapshot(` [ "2:4 -> 1:0-65", "2:0 -> 2:0", "3:2-22 -> 3:2-22", "4:2-48 -> 4:2-48", "5:0 -> 5:0", ] `) })