narrowFixRange.mjs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /** @import { Node as PostcssNode } from 'postcss' */
  2. /**
  3. * Make a fix range as narrow as possible by trimming common prefixes and suffixes
  4. *
  5. * @param {PostcssNode} node
  6. * @param {{range: [number, number], text: string}} fixData
  7. * @returns {{range: [number, number], text: string}}
  8. */
  9. export default function narrowFixRange(node, fixData) {
  10. if (!node.source) {
  11. return fixData;
  12. }
  13. let startOffset = fixData.range[0];
  14. let endOffset = fixData.range[1];
  15. const stringRepresentation = node.source.input.css.slice(startOffset, endOffset);
  16. let replacementStartOffset = 0;
  17. for (let i = 0; i < stringRepresentation.length; i++) {
  18. const a = stringRepresentation[i];
  19. const b = fixData.text[i];
  20. if (a !== b) break;
  21. startOffset++;
  22. replacementStartOffset++;
  23. }
  24. let replacementEndOffset = fixData.text.length;
  25. for (let i = 0; i < stringRepresentation.length; i++) {
  26. const ia = stringRepresentation.length - 1 - i;
  27. if (ia < replacementStartOffset) break;
  28. const a = stringRepresentation[ia];
  29. const ib = fixData.text.length - 1 - i;
  30. if (ib < replacementStartOffset) break;
  31. const b = fixData.text[ib];
  32. if (a !== b) break;
  33. endOffset--;
  34. replacementEndOffset--;
  35. }
  36. // Try to have a context size of at least 1
  37. if (startOffset === endOffset) {
  38. if (startOffset > fixData.range[0]) {
  39. startOffset--;
  40. replacementStartOffset--;
  41. } else if (endOffset < fixData.range[1]) {
  42. endOffset++;
  43. replacementEndOffset++;
  44. }
  45. }
  46. return {
  47. text: fixData.text.slice(replacementStartOffset, replacementEndOffset),
  48. range: [startOffset, endOffset],
  49. };
  50. }