inline-comment.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /* eslint-disable import/no-extraneous-dependencies, no-param-reassign */
  2. const tokenizer = require('postcss/lib/tokenize');
  3. const Input = require('postcss/lib/input');
  4. module.exports = {
  5. isInlineComment(token) {
  6. if (token[0] === 'word' && token[1].slice(0, 2) === '//') {
  7. const first = token;
  8. const bits = [];
  9. let endOffset;
  10. let remainingInput;
  11. while (token) {
  12. if (/\r?\n/.test(token[1])) {
  13. // If there are quotes, fix tokenizer creating one token from start quote to end quote
  14. if (/['"].*\r?\n/.test(token[1])) {
  15. // Add string before newline to inline comment token
  16. bits.push(token[1].substring(0, token[1].indexOf('\n')));
  17. // Get remaining input and retokenize
  18. remainingInput = token[1].substring(token[1].indexOf('\n'));
  19. const untokenizedRemainingInput = this.input.css
  20. .valueOf()
  21. .substring(this.tokenizer.position());
  22. remainingInput += untokenizedRemainingInput;
  23. endOffset = token[3] + untokenizedRemainingInput.length - remainingInput.length;
  24. } else {
  25. // If the tokenizer went to the next line go back
  26. this.tokenizer.back(token);
  27. }
  28. break;
  29. }
  30. bits.push(token[1]);
  31. // eslint-disable-next-line prefer-destructuring
  32. endOffset = token[2];
  33. token = this.tokenizer.nextToken({ ignoreUnclosed: true });
  34. }
  35. const newToken = ['comment', bits.join(''), first[2], endOffset];
  36. this.inlineComment(newToken);
  37. // Replace tokenizer to retokenize the rest of the string
  38. // we need replace it after we added new token with inline comment because token position is calculated for old input (#145)
  39. if (remainingInput) {
  40. this.input = new Input(remainingInput);
  41. this.tokenizer = tokenizer(this.input);
  42. }
  43. return true;
  44. } else if (token[1] === '/') {
  45. // issue #135
  46. const next = this.tokenizer.nextToken({ ignoreUnclosed: true });
  47. if (next[0] === 'comment' && /^\/\*/.test(next[1])) {
  48. next[0] = 'word';
  49. next[1] = next[1].slice(1);
  50. token[1] = '//';
  51. this.tokenizer.back(next);
  52. return module.exports.isInlineComment.bind(this)(token);
  53. }
  54. }
  55. return false;
  56. }
  57. };