sourceMap.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { SourceMapGenerator } from 'source-map-js/lib/source-map-generator.js';
  2. const trackNodes = new Set(['Atrule', 'Selector', 'Declaration']);
  3. export function generateSourceMap(handlers) {
  4. const map = new SourceMapGenerator();
  5. const generated = {
  6. line: 1,
  7. column: 0
  8. };
  9. const original = {
  10. line: 0, // should be zero to add first mapping
  11. column: 0
  12. };
  13. const activatedGenerated = {
  14. line: 1,
  15. column: 0
  16. };
  17. const activatedMapping = {
  18. generated: activatedGenerated
  19. };
  20. let line = 1;
  21. let column = 0;
  22. let sourceMappingActive = false;
  23. const origHandlersNode = handlers.node;
  24. handlers.node = function(node) {
  25. if (node.loc && node.loc.start && trackNodes.has(node.type)) {
  26. const nodeLine = node.loc.start.line;
  27. const nodeColumn = node.loc.start.column - 1;
  28. if (original.line !== nodeLine ||
  29. original.column !== nodeColumn) {
  30. original.line = nodeLine;
  31. original.column = nodeColumn;
  32. generated.line = line;
  33. generated.column = column;
  34. if (sourceMappingActive) {
  35. sourceMappingActive = false;
  36. if (generated.line !== activatedGenerated.line ||
  37. generated.column !== activatedGenerated.column) {
  38. map.addMapping(activatedMapping);
  39. }
  40. }
  41. sourceMappingActive = true;
  42. map.addMapping({
  43. source: node.loc.source,
  44. original,
  45. generated
  46. });
  47. }
  48. }
  49. origHandlersNode.call(this, node);
  50. if (sourceMappingActive && trackNodes.has(node.type)) {
  51. activatedGenerated.line = line;
  52. activatedGenerated.column = column;
  53. }
  54. };
  55. const origHandlersEmit = handlers.emit;
  56. handlers.emit = function(value, type, auto) {
  57. for (let i = 0; i < value.length; i++) {
  58. if (value.charCodeAt(i) === 10) { // \n
  59. line++;
  60. column = 0;
  61. } else {
  62. column++;
  63. }
  64. }
  65. origHandlersEmit(value, type, auto);
  66. };
  67. const origHandlersResult = handlers.result;
  68. handlers.result = function() {
  69. if (sourceMappingActive) {
  70. map.addMapping(activatedMapping);
  71. }
  72. return {
  73. css: origHandlersResult(),
  74. map
  75. };
  76. };
  77. return handlers;
  78. };