You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
32 KiB

4 years ago
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.default = tokenizer;
  4. var SINGLE_QUOTE = '\''.charCodeAt(0);
  5. var DOUBLE_QUOTE = '"'.charCodeAt(0);
  6. var BACKSLASH = '\\'.charCodeAt(0);
  7. var SLASH = '/'.charCodeAt(0);
  8. var NEWLINE = '\n'.charCodeAt(0);
  9. var SPACE = ' '.charCodeAt(0);
  10. var FEED = '\f'.charCodeAt(0);
  11. var TAB = '\t'.charCodeAt(0);
  12. var CR = '\r'.charCodeAt(0);
  13. var OPEN_SQUARE = '['.charCodeAt(0);
  14. var CLOSE_SQUARE = ']'.charCodeAt(0);
  15. var OPEN_PARENTHESES = '('.charCodeAt(0);
  16. var CLOSE_PARENTHESES = ')'.charCodeAt(0);
  17. var OPEN_CURLY = '{'.charCodeAt(0);
  18. var CLOSE_CURLY = '}'.charCodeAt(0);
  19. var SEMICOLON = ';'.charCodeAt(0);
  20. var ASTERISK = '*'.charCodeAt(0);
  21. var COLON = ':'.charCodeAt(0);
  22. var AT = '@'.charCodeAt(0);
  23. var RE_AT_END = /[ \n\t\r\f{}()'"\\;/[\]#]/g;
  24. var RE_WORD_END = /[ \n\t\r\f(){}:;@!'"\\\][#]|\/(?=\*)/g;
  25. var RE_BAD_BRACKET = /.[\\/("'\n]/;
  26. var RE_HEX_ESCAPE = /[a-f0-9]/i;
  27. function tokenizer(input, options) {
  28. if (options === void 0) {
  29. options = {};
  30. }
  31. var css = input.css.valueOf();
  32. var ignore = options.ignoreErrors;
  33. var code, next, quote, lines, last, content, escape;
  34. var nextLine, nextOffset, escaped, escapePos, prev, n, currentToken;
  35. var length = css.length;
  36. var offset = -1;
  37. var line = 1;
  38. var pos = 0;
  39. var buffer = [];
  40. var returned = [];
  41. function position() {
  42. return pos;
  43. }
  44. function unclosed(what) {
  45. throw input.error('Unclosed ' + what, line, pos - offset);
  46. }
  47. function endOfFile() {
  48. return returned.length === 0 && pos >= length;
  49. }
  50. function nextToken(opts) {
  51. if (returned.length) return returned.pop();
  52. if (pos >= length) return;
  53. var ignoreUnclosed = opts ? opts.ignoreUnclosed : false;
  54. code = css.charCodeAt(pos);
  55. if (code === NEWLINE || code === FEED || code === CR && css.charCodeAt(pos + 1) !== NEWLINE) {
  56. offset = pos;
  57. line += 1;
  58. }
  59. switch (code) {
  60. case NEWLINE:
  61. case SPACE:
  62. case TAB:
  63. case CR:
  64. case FEED:
  65. next = pos;
  66. do {
  67. next += 1;
  68. code = css.charCodeAt(next);
  69. if (code === NEWLINE) {
  70. offset = next;
  71. line += 1;
  72. }
  73. } while (code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED);
  74. currentToken = ['space', css.slice(pos, next)];
  75. pos = next - 1;
  76. break;
  77. case OPEN_SQUARE:
  78. case CLOSE_SQUARE:
  79. case OPEN_CURLY:
  80. case CLOSE_CURLY:
  81. case COLON:
  82. case SEMICOLON:
  83. case CLOSE_PARENTHESES:
  84. var controlChar = String.fromCharCode(code);
  85. currentToken = [controlChar, controlChar, line, pos - offset];
  86. break;
  87. case OPEN_PARENTHESES:
  88. prev = buffer.length ? buffer.pop()[1] : '';
  89. n = css.charCodeAt(pos + 1);
  90. if (prev === 'url' && n !== SINGLE_QUOTE && n !== DOUBLE_QUOTE && n !== SPACE && n !== NEWLINE && n !== TAB && n !== FEED && n !== CR) {
  91. next = pos;
  92. do {
  93. escaped = false;
  94. next = css.indexOf(')', next + 1);
  95. if (next === -1) {
  96. if (ignore || ignoreUnclosed) {
  97. next = pos;
  98. break;
  99. } else {
  100. unclosed('bracket');
  101. }
  102. }
  103. escapePos = next;
  104. while (css.charCodeAt(escapePos - 1) === BACKSLASH) {
  105. escapePos -= 1;
  106. escaped = !escaped;
  107. }
  108. } while (escaped);
  109. currentToken = ['brackets', css.slice(pos, next + 1), line, pos - offset, line, next - offset];
  110. pos = next;
  111. } else {
  112. next = css.indexOf(')', pos + 1);
  113. content = css.slice(pos, next + 1);
  114. if (next === -1 || RE_BAD_BRACKET.test(content)) {
  115. currentToken = ['(', '(', line, pos - offset];
  116. } else {
  117. currentToken = ['brackets', content, line, pos - offset, line, next - offset];
  118. pos = next;
  119. }
  120. }
  121. break;
  122. case SINGLE_QUOTE:
  123. case DOUBLE_QUOTE:
  124. quote = code === SINGLE_QUOTE ? '\'' : '"';
  125. next = pos;
  126. do {
  127. escaped = false;
  128. next = css.indexOf(quote, next + 1);
  129. if (next === -1) {
  130. if (ignore || ignoreUnclosed) {
  131. next = pos + 1;
  132. break;
  133. } else {
  134. unclosed('string');
  135. }
  136. }
  137. escapePos = next;
  138. while (css.charCodeAt(escapePos - 1) === BACKSLASH) {
  139. escapePos -= 1;
  140. escaped = !escaped;
  141. }
  142. } while (escaped);
  143. content = css.slice(pos, next + 1);
  144. lines = content.split('\n');
  145. last = lines.length - 1;
  146. if (last > 0) {
  147. nextLine = line + last;
  148. nextOffset = next - lines[last].length;
  149. } else {
  150. nextLine = line;
  151. nextOffset = offset;
  152. }
  153. currentToken = ['string', css.slice(pos, next + 1), line, pos - offset, nextLine, next - nextOffset];
  154. offset = nextOffset;
  155. line = nextLine;
  156. pos = next;
  157. break;
  158. case AT:
  159. RE_AT_END.lastIndex = pos + 1;
  160. RE_AT_END.test(css);
  161. if (RE_AT_END.lastIndex === 0) {
  162. next = css.length - 1;
  163. } else {
  164. next = RE_AT_END.lastIndex - 2;
  165. }
  166. currentToken = ['at-word', css.slice(pos, next + 1), line, pos - offset, line, next - offset];
  167. pos = next;
  168. break;
  169. case BACKSLASH:
  170. next = pos;
  171. escape = true;
  172. while (css.charCodeAt(next + 1) === BACKSLASH) {
  173. next += 1;
  174. escape = !escape;
  175. }
  176. code = css.charCodeAt(next + 1);
  177. if (escape && code !== SLASH && code !== SPACE && code !== NEWLINE && code !== TAB && code !== CR && code !== FEED) {
  178. next += 1;
  179. if (RE_HEX_ESCAPE.test(css.charAt(next))) {
  180. while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) {
  181. next += 1;
  182. }
  183. if (css.charCodeAt(next + 1) === SPACE) {
  184. next += 1;
  185. }
  186. }
  187. }
  188. currentToken = ['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset];
  189. pos = next;
  190. break;
  191. default:
  192. if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) {
  193. next = css.indexOf('*/', pos + 2) + 1;
  194. if (next === 0) {
  195. if (ignore || ignoreUnclosed) {
  196. next = css.length;
  197. } else {
  198. unclosed('comment');
  199. }
  200. }
  201. content = css.slice(pos, next + 1);
  202. lines = content.split('\n');
  203. last = lines.length - 1;
  204. if (last > 0) {
  205. nextLine = line + last;
  206. nextOffset = next - lines[last].length;
  207. } else {
  208. nextLine = line;
  209. nextOffset = offset;
  210. }
  211. currentToken = ['comment', content, line, pos - offset, nextLine, next - nextOffset];
  212. offset = nextOffset;
  213. line = nextLine;
  214. pos = next;
  215. } else {
  216. RE_WORD_END.lastIndex = pos + 1;
  217. RE_WORD_END.test(css);
  218. if (RE_WORD_END.lastIndex === 0) {
  219. next = css.length - 1;
  220. } else {
  221. next = RE_WORD_END.lastIndex - 2;
  222. }
  223. currentToken = ['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset];
  224. buffer.push(currentToken);
  225. pos = next;
  226. }
  227. break;
  228. }
  229. pos++;
  230. return currentToken;
  231. }
  232. function back(token) {
  233. returned.push(token);
  234. }
  235. return {
  236. back: back,
  237. nextToken: nextToken,
  238. endOfFile: endOfFile,
  239. position: position
  240. };
  241. }
  242. module.exports = exports.default;
  243. //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRva2VuaXplLmVzNiJdLCJuYW1lcyI6WyJTSU5HTEVfUVVPVEUiLCJjaGFyQ29kZUF0IiwiRE9VQkxFX1FVT1RFIiwiQkFDS1NMQVNIIiwiU0xBU0giLCJORVdMSU5FIiwiU1BBQ0UiLCJGRUVEIiwiVEFCIiwiQ1IiLCJPUEVOX1NRVUFSRSIsIkNMT1NFX1NRVUFSRSIsIk9QRU5fUEFSRU5USEVTRVMiLCJDTE9TRV9QQVJFTlRIRVNFUyIsIk9QRU5fQ1VSTFkiLCJDTE9TRV9DVVJMWSIsIlNFTUlDT0xPTiIsIkFTVEVSSVNLIiwiQ09MT04iLCJBVCIsIlJFX0FUX0VORCIsIlJFX1dPUkRfRU5EIiwiUkVfQkFEX0JSQUNLRVQiLCJSRV9IRVhfRVNDQVBFIiwidG9rZW5pemVyIiwiaW5wdXQiLCJvcHRpb25zIiwiY3NzIiwidmFsdWVPZiIsImlnbm9yZSIsImlnbm9yZUVycm9ycyIsImNvZGUiLCJuZXh0IiwicXVvdGUiLCJsaW5lcyIsImxhc3QiLCJjb250ZW50IiwiZXNjYXBlIiwibmV4dExpbmUiLCJuZXh0T2Zmc2V0IiwiZXNjYXBlZCIsImVzY2FwZVBvcyIsInByZXYiLCJuIiwiY3VycmVudFRva2VuIiwibGVuZ3RoIiwib2Zmc2V0IiwibGluZSIsInBvcyIsImJ1ZmZlciIsInJldHVybmVkIiwicG9zaXRpb24iLCJ1bmNsb3NlZCIsIndoYXQiLCJlcnJvciIsImVuZE9mRmlsZSIsIm5leHRUb2tlbiIsIm9wdHMiLCJwb3AiLCJpZ25vcmVVbmNsb3NlZCIsInNsaWNlIiwiY29udHJvbENoYXIiLCJTdHJpbmciLCJmcm9tQ2hhckNvZGUiLCJpbmRleE9mIiwidGVzdCIsInNwbGl0IiwibGFzdEluZGV4IiwiY2hhckF0IiwicHVzaCIsImJhY2siLCJ0b2tlbiJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQU1BLFlBQVksR0FBRyxLQUFLQyxVQUFMLENBQWdCLENBQWhCLENBQXJCO0FBQ0EsSUFBTUMsWUFBWSxHQUFHLElBQUlELFVBQUosQ0FBZSxDQUFm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