source-maps.test.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. import postcss from 'postcss'
  2. import { parseSourceMaps } from './util/source-maps'
  3. import { runWithSourceMaps as run, html, css, map } from './util/run'
  4. test('apply generates source maps', async () => {
  5. let config = {
  6. content: [
  7. {
  8. raw: html`
  9. <div class="with-declaration"></div>
  10. <div class="with-comment"></div>
  11. <div class="just-apply"></div>
  12. `,
  13. },
  14. ],
  15. corePlugins: { preflight: false },
  16. }
  17. let input = css`
  18. .with-declaration {
  19. background-color: red;
  20. @apply h-4 w-4 bg-green-500;
  21. }
  22. .with-comment {
  23. /* sourcemap will work here too */
  24. @apply h-4 w-4 bg-red-500;
  25. }
  26. .just-apply {
  27. @apply h-4 w-4 bg-black;
  28. }
  29. `
  30. let result = await run(input, config)
  31. let { sources, annotations } = parseSourceMaps(result)
  32. // All CSS generated by Tailwind CSS should be annotated with source maps
  33. // And always be able to point to the original source file
  34. expect(sources).not.toContain('<no source>')
  35. expect(sources.length).toBe(2)
  36. expect(annotations).toMatchInlineSnapshot(`
  37. [
  38. "2:4 -> 1:0-65",
  39. "2:0 -> 2:0",
  40. "3:2-20 -> 3:2-20",
  41. "4:2-23 -> 4:2-23",
  42. "5:2-57 -> 5:2-57",
  43. "6:2-13 -> 6:2-13",
  44. "7:2-14 -> 7:2-14",
  45. "8:0 -> 8:0",
  46. "10:0 -> 10:0",
  47. "11:2-20 -> 11:2-20",
  48. "12:2-57 -> 12:2-57",
  49. "13:2-13 -> 13:2-13",
  50. "14:2-14 -> 14:2-14",
  51. "15:0 -> 15:0",
  52. "17:0 -> 17:0",
  53. "18:2-20 -> 18:2-20",
  54. "19:2-53 -> 19:2-53",
  55. "20:2-13 -> 20:2-13",
  56. "21:2-14 -> 21:2-14",
  57. "22:0 -> 22:0",
  58. ]
  59. `)
  60. })
  61. test('preflight + base have source maps', async () => {
  62. let config = {
  63. content: [],
  64. }
  65. let input = css`
  66. @tailwind base;
  67. `
  68. let result = await run(input, config)
  69. let { sources, annotations } = parseSourceMaps(result)
  70. // All CSS generated by Tailwind CSS should be annotated with source maps
  71. // And always be able to point to the original source file
  72. expect(sources).not.toContain('<no source>')
  73. expect(sources.length).toBe(2)
  74. expect(annotations).toMatchInlineSnapshot(`
  75. [
  76. "2:4 -> 1:0-65",
  77. "2:0 -> 2:0",
  78. "3:2-24 -> 3:2-24",
  79. "4:2-25 -> 4:2-25",
  80. "5:0 -> 5:0",
  81. "7:0 -> 7:0",
  82. "8:2-18 -> 8:2-18",
  83. "9:0 -> 9:0",
  84. "11:0 -> 11:0",
  85. "12:2-32 -> 12:2-32",
  86. "13:2-13 -> 13:2-13",
  87. "14:2-31 -> 14:2-31",
  88. "15:2-33 -> 15:2-33",
  89. "16:2-42 -> 16:2-42",
  90. "17:2-121 -> 17:2-121",
  91. "18:2-18 -> 18:2-18",
  92. "19:0 -> 19:0",
  93. "21:0 -> 21:0",
  94. "22:2-22 -> 22:2-22",
  95. "23:2-11 -> 23:2-11",
  96. "24:0 -> 24:0",
  97. "26:0 -> 26:0",
  98. "27:2-16 -> 27:2-16",
  99. "28:2-23 -> 28:2-23",
  100. "29:2-11 -> 29:2-11",
  101. "30:0 -> 30:0",
  102. "32:0 -> 32:0",
  103. "33:2-43 -> 33:2-43",
  104. "34:2-35 -> 34:2-35",
  105. "35:0 -> 35:0",
  106. "37:0 -> 37:0",
  107. "38:2-20 -> 38:2-20",
  108. "39:2-22 -> 39:2-22",
  109. "40:0 -> 40:0",
  110. "42:0 -> 42:0",
  111. "43:2-16 -> 43:2-16",
  112. "44:2-34 -> 44:2-34",
  113. "45:2-26 -> 45:2-26",
  114. "46:0 -> 46:0",
  115. "48:0 -> 48:0",
  116. "49:2-21 -> 49:2-21",
  117. "50:0 -> 50:0",
  118. "52:0 -> 52:0",
  119. "53:2-31 -> 53:2-31",
  120. "54:2-33 -> 54:2-33",
  121. "55:2-109 -> 55:2-109",
  122. "56:2-16 -> 56:2-16",
  123. "57:0 -> 57:0",
  124. "59:0 -> 59:0",
  125. "60:2-16 -> 60:2-16",
  126. "61:0 -> 61:0",
  127. "63:0 -> 63:0",
  128. "64:2-26 -> 64:2-26",
  129. "65:2-16 -> 65:2-16",
  130. "66:2-16 -> 66:2-16",
  131. "67:2-20 -> 67:2-20",
  132. "68:0 -> 68:0",
  133. "70:0 -> 70:0",
  134. "71:2-16 -> 71:2-16",
  135. "72:0 -> 72:0",
  136. "74:0 -> 74:0",
  137. "75:2-12 -> 75:2-12",
  138. "76:0 -> 76:0",
  139. "78:0 -> 78:0",
  140. "79:2-16 -> 79:2-16",
  141. "80:2-23 -> 80:2-23",
  142. "81:2-27 -> 81:2-27",
  143. "82:0 -> 82:0",
  144. "84:0 -> 84:0",
  145. "85:2-32 -> 85:2-32",
  146. "86:2-34 -> 86:2-34",
  147. "87:2-22 -> 87:2-22",
  148. "88:2-17 -> 88:2-17",
  149. "89:2-22 -> 89:2-22",
  150. "90:2-22 -> 90:2-22",
  151. "91:2-16 -> 91:2-16",
  152. "92:2-11 -> 92:2-11",
  153. "93:2-12 -> 93:2-12",
  154. "94:0 -> 94:0",
  155. "96:0 -> 96:0",
  156. "97:2-22 -> 97:2-22",
  157. "98:0 -> 98:0",
  158. "100:0 -> 100:0",
  159. "101:2-28 -> 101:2-28",
  160. "102:2-25 -> 102:2-25",
  161. "103:2-24 -> 103:2-24",
  162. "104:0 -> 104:0",
  163. "106:0 -> 106:0",
  164. "107:2-15 -> 107:2-15",
  165. "108:0 -> 108:0",
  166. "110:0 -> 110:0",
  167. "111:2-18 -> 111:2-18",
  168. "112:0 -> 112:0",
  169. "114:0 -> 114:0",
  170. "115:2-26 -> 115:2-26",
  171. "116:0 -> 116:0",
  172. "118:0 -> 118:0",
  173. "119:2-14 -> 119:2-14",
  174. "120:0 -> 120:0",
  175. "122:0 -> 122:0",
  176. "123:2-14 -> 123:2-14",
  177. "124:0 -> 124:0",
  178. "126:0 -> 126:0",
  179. "127:2-31 -> 127:2-31",
  180. "128:2-22 -> 128:2-22",
  181. "129:0 -> 129:0",
  182. "131:0 -> 131:0",
  183. "132:2-26 -> 132:2-26",
  184. "133:0 -> 133:0",
  185. "135:0 -> 135:0",
  186. "136:2-28 -> 136:2-28",
  187. "137:2-15 -> 137:2-15",
  188. "138:0 -> 138:0",
  189. "140:0 -> 140:0",
  190. "141:2-20 -> 141:2-20",
  191. "142:0 -> 142:0",
  192. "144:0 -> 144:0",
  193. "145:2-11 -> 145:2-11",
  194. "146:0 -> 146:0",
  195. "148:0 -> 148:0",
  196. "149:2-11 -> 149:2-11",
  197. "150:2-12 -> 150:2-12",
  198. "151:0 -> 151:0",
  199. "153:0 -> 153:0",
  200. "154:2-12 -> 154:2-12",
  201. "155:0 -> 155:0",
  202. "157:0 -> 157:0",
  203. "158:2-11 -> 158:2-11",
  204. "159:2-12 -> 159:2-12",
  205. "160:2-18 -> 160:2-18",
  206. "161:0 -> 161:0",
  207. "163:0 -> 163:0",
  208. "164:2-12 -> 164:2-12",
  209. "165:0 -> 165:0",
  210. "167:0 -> 167:0",
  211. "168:2-18 -> 168:2-18",
  212. "169:0 -> 169:0",
  213. "171:0 -> 171:0",
  214. "172:2-12 -> 172:2-12",
  215. "173:2-16 -> 173:2-16",
  216. "174:0 -> 174:0",
  217. "176:0 -> 176:0",
  218. "177:2-17 -> 177:2-17",
  219. "178:0 -> 178:0",
  220. "180:0 -> 180:0",
  221. "181:2-17 -> 181:2-17",
  222. "182:0 -> 182:0",
  223. "184:0 -> 184:0",
  224. "185:2-24 -> 185:2-24",
  225. "186:2-16 -> 186:2-16",
  226. "187:0 -> 187:0",
  227. "189:0 -> 189:0",
  228. "190:2-17 -> 190:2-17",
  229. "191:2-14 -> 191:2-14",
  230. "192:0 -> 192:0",
  231. "194:0 -> 194:0",
  232. "195:2-15 -> 195:2-15",
  233. "196:0 -> 196:0",
  234. "198:0 -> 198:0",
  235. "199:2-26 -> 199:2-26",
  236. "200:2-26 -> 200:2-26",
  237. "201:2-21 -> 201:2-21",
  238. "202:2-21 -> 202:2-21",
  239. "203:2-16 -> 203:2-16",
  240. "204:2-16 -> 204:2-16",
  241. "205:2-16 -> 205:2-16",
  242. "206:2-17 -> 206:2-17",
  243. "207:2-17 -> 207:2-17",
  244. "208:2-14 -> 208:2-14",
  245. "209:2-14 -> 209:2-14",
  246. "210:2-19 -> 210:2-19",
  247. "211:2-40 -> 211:2-40",
  248. "212:2-31 -> 212:2-31",
  249. "213:2-30 -> 213:2-30",
  250. "214:2-29 -> 214:2-29",
  251. "215:2-16 -> 215:2-16",
  252. "216:2-21 -> 216:2-21",
  253. "217:2-23 -> 217:2-23",
  254. "218:2-24 -> 218:2-24",
  255. "219:2-25 -> 219:2-25",
  256. "220:2-19 -> 220:2-19",
  257. "221:2-29 -> 221:2-29",
  258. "222:2-30 -> 222:2-30",
  259. "223:2-28 -> 223:2-28",
  260. "224:2-36 -> 224:2-36",
  261. "225:2-29 -> 225:2-29",
  262. "226:2-24 -> 226:2-24",
  263. "227:2-32 -> 227:2-32",
  264. "228:2-13 -> 228:2-13",
  265. "229:2-19 -> 229:2-19",
  266. "230:2-17 -> 230:2-17",
  267. "231:2-18 -> 231:2-18",
  268. "232:2-19 -> 232:2-19",
  269. "233:2-15 -> 233:2-15",
  270. "234:2-17 -> 234:2-17",
  271. "235:2-14 -> 235:2-14",
  272. "236:2-20 -> 236:2-20",
  273. "237:2-22 -> 237:2-22",
  274. "238:2-28 -> 238:2-28",
  275. "239:2-26 -> 239:2-26",
  276. "240:2-27 -> 240:2-27",
  277. "241:2-28 -> 241:2-28",
  278. "242:2-24 -> 242:2-24",
  279. "243:2-25 -> 243:2-25",
  280. "244:2-26 -> 244:2-26",
  281. "245:2-23 -> 245:2-23",
  282. "246:0 -> 246:0",
  283. "248:0 -> 248:0",
  284. "249:2-26 -> 249:2-26",
  285. "250:2-26 -> 250:2-26",
  286. "251:2-21 -> 251:2-21",
  287. "252:2-21 -> 252:2-21",
  288. "253:2-16 -> 253:2-16",
  289. "254:2-16 -> 254:2-16",
  290. "255:2-16 -> 255:2-16",
  291. "256:2-17 -> 256:2-17",
  292. "257:2-17 -> 257:2-17",
  293. "258:2-14 -> 258:2-14",
  294. "259:2-14 -> 259:2-14",
  295. "260:2-19 -> 260:2-19",
  296. "261:2-40 -> 261:2-40",
  297. "262:2-31 -> 262:2-31",
  298. "263:2-30 -> 263:2-30",
  299. "264:2-29 -> 264:2-29",
  300. "265:2-16 -> 265:2-16",
  301. "266:2-21 -> 266:2-21",
  302. "267:2-23 -> 267:2-23",
  303. "268:2-24 -> 268:2-24",
  304. "269:2-25 -> 269:2-25",
  305. "270:2-19 -> 270:2-19",
  306. "271:2-29 -> 271:2-29",
  307. "272:2-30 -> 272:2-30",
  308. "273:2-28 -> 273:2-28",
  309. "274:2-36 -> 274:2-36",
  310. "275:2-29 -> 275:2-29",
  311. "276:2-24 -> 276:2-24",
  312. "277:2-32 -> 277:2-32",
  313. "278:2-13 -> 278:2-13",
  314. "279:2-19 -> 279:2-19",
  315. "280:2-17 -> 280:2-17",
  316. "281:2-18 -> 281:2-18",
  317. "282:2-19 -> 282:2-19",
  318. "283:2-15 -> 283:2-15",
  319. "284:2-17 -> 284:2-17",
  320. "285:2-14 -> 285:2-14",
  321. "286:2-20 -> 286:2-20",
  322. "287:2-22 -> 287:2-22",
  323. "288:2-28 -> 288:2-28",
  324. "289:2-26 -> 289:2-26",
  325. "290:2-27 -> 290:2-27",
  326. "291:2-28 -> 291:2-28",
  327. "292:2-24 -> 292:2-24",
  328. "293:2-25 -> 293:2-25",
  329. "294:2-26 -> 294:2-26",
  330. "295:2-23 -> 295:2-23",
  331. "296:0 -> 296:0",
  332. ]
  333. `)
  334. })
  335. test('utilities have source maps', async () => {
  336. let config = {
  337. content: [{ raw: `text-red-500` }],
  338. }
  339. let input = css`
  340. @tailwind utilities;
  341. `
  342. let result = await run(input, config)
  343. let { sources, annotations } = parseSourceMaps(result)
  344. // All CSS generated by Tailwind CSS should be annotated with source maps
  345. // And always be able to point to the original source file
  346. expect(sources).not.toContain('<no source>')
  347. expect(sources.length).toBe(2)
  348. expect(annotations).toMatchInlineSnapshot(`
  349. [
  350. "2:4 -> 1:0-65",
  351. "2:0 -> 2:0",
  352. "3:2-22 -> 3:2-22",
  353. "4:2-48 -> 4:2-48",
  354. "5:0 -> 5:0",
  355. ]
  356. `)
  357. })
  358. test('components have source maps', async () => {
  359. let config = {
  360. content: [{ raw: `container` }],
  361. }
  362. let input = css`
  363. @tailwind components;
  364. `
  365. let result = await run(input, config)
  366. let { sources, annotations } = parseSourceMaps(result)
  367. // All CSS generated by Tailwind CSS should be annotated with source maps
  368. // And always be able to point to the original source file
  369. expect(sources).not.toContain('<no source>')
  370. expect(sources.length).toBe(2)
  371. expect(annotations).toMatchInlineSnapshot(`
  372. [
  373. "2:4 -> 1:0-65",
  374. "2:0 -> 2:0",
  375. "3:2-13 -> 3:2-13",
  376. "4:0 -> 4:0",
  377. "6:0 -> 6:0",
  378. "7:2 -> 7:2",
  379. "8:4-20 -> 8:4-20",
  380. "9:2 -> 9:2",
  381. "10:0 -> 10:0",
  382. "12:0 -> 12:0",
  383. "13:2 -> 13:2",
  384. "14:4-20 -> 14:4-20",
  385. "15:2 -> 15:2",
  386. "16:0 -> 16:0",
  387. "18:0 -> 18:0",
  388. "19:2 -> 19:2",
  389. "20:4-21 -> 20:4-21",
  390. "21:2 -> 21:2",
  391. "22:0 -> 22:0",
  392. "24:0 -> 24:0",
  393. "25:2 -> 25:2",
  394. "26:4-21 -> 26:4-21",
  395. "27:2 -> 27:2",
  396. "28:0 -> 28:0",
  397. "30:0 -> 30:0",
  398. "31:2 -> 31:2",
  399. "32:4-21 -> 32:4-21",
  400. "33:2 -> 33:2",
  401. "34:0 -> 34:0",
  402. ]
  403. `)
  404. })
  405. test('source maps for layer rules are not rewritten to point to @tailwind directives', async () => {
  406. let config = {
  407. content: [{ raw: `font-normal foo hover:foo lg:foo` }],
  408. }
  409. let utilitiesFile = postcss.parse(
  410. css`
  411. @tailwind utilities;
  412. `,
  413. { from: 'components.css', map: { prev: map } }
  414. )
  415. let mainCssFile = postcss.parse(
  416. css`
  417. @layer utilities {
  418. .foo {
  419. background-color: red;
  420. }
  421. }
  422. `,
  423. { from: 'input.css', map: { prev: map } }
  424. )
  425. // Just pretend that there's an @import in `mainCssFile` that imports the nodes from `utilitiesFile`
  426. let input = postcss.root({
  427. nodes: [...utilitiesFile.nodes, ...mainCssFile.nodes],
  428. source: mainCssFile.source,
  429. })
  430. let result = await run(input, config)
  431. let { sources, annotations } = parseSourceMaps(result)
  432. // All CSS generated by Tailwind CSS should be annotated with source maps
  433. // And always be able to point to the original source file
  434. expect(sources).not.toContain('<no source>')
  435. // And we should see that the source map for the layer rule is not rewritten
  436. // to point to the @tailwind directive but instead points to the original
  437. expect(sources.length).toBe(2)
  438. expect(sources).toMatchInlineSnapshot(`
  439. [
  440. "components.css",
  441. "source-maps.test.js%3Ftest=c291cmNlIG1hcHMgZm9yIGxheWVyIHJ1bGVzIGFyZSBub3QgcmV3cml0dGVuIHRvIHBvaW50IHRvIEB0YWlsd2luZCBkaXJlY3RpdmVz",
  442. ]
  443. `)
  444. expect(annotations).toMatchInlineSnapshot(`
  445. [
  446. "2:6 -> 1:0-65",
  447. "2:0 -> 2:0",
  448. "3:2-18 -> 3:2-18",
  449. "4:0 -> 4:0",
  450. "6:0 -> 6:0",
  451. "7:2-23 -> 7:2-23",
  452. "8:0 -> 8:0",
  453. "10:0 -> 10:0",
  454. "11:2 -> 11:2",
  455. "12:4-25 -> 12:4-25",
  456. "13:2 -> 13:2",
  457. "14:0 -> 14:0",
  458. ]
  459. `)
  460. })
  461. test('it handles `map: true` correctly', async () => {
  462. let config = {
  463. content: [{ raw: `text-red-500` }],
  464. }
  465. let input = css`
  466. @tailwind utilities;
  467. `
  468. let result = await run(input, config, {
  469. map: true,
  470. })
  471. let { sources, annotations } = parseSourceMaps(result)
  472. // All CSS generated by Tailwind CSS should be annotated with source maps
  473. // And always be able to point to the original source file
  474. expect(sources).not.toContain('<no source>')
  475. expect(sources.length).toBe(2)
  476. expect(annotations).toMatchInlineSnapshot(`
  477. [
  478. "2:4 -> 1:0-65",
  479. "2:0 -> 2:0",
  480. "3:2-22 -> 3:2-22",
  481. "4:2-48 -> 4:2-48",
  482. "5:0 -> 5:0",
  483. ]
  484. `)
  485. })
  486. test('it handles `map: { inline: true }` correctly', async () => {
  487. let config = {
  488. content: [{ raw: `text-red-500` }],
  489. }
  490. let input = css`
  491. @tailwind utilities;
  492. `
  493. let result = await run(input, config, {
  494. map: {
  495. inline: true,
  496. },
  497. })
  498. let { sources, annotations } = parseSourceMaps(result)
  499. // All CSS generated by Tailwind CSS should be annotated with source maps
  500. // And always be able to point to the original source file
  501. expect(sources).not.toContain('<no source>')
  502. expect(sources.length).toBe(2)
  503. expect(annotations).toMatchInlineSnapshot(`
  504. [
  505. "2:4 -> 1:0-65",
  506. "2:0 -> 2:0",
  507. "3:2-22 -> 3:2-22",
  508. "4:2-48 -> 4:2-48",
  509. "5:0 -> 5:0",
  510. ]
  511. `)
  512. })