test.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. var test = require("tape");
  2. var styleSearch = require("./index");
  3. function styleSearchResults(options) {
  4. const results = [];
  5. styleSearch(options, function(match) {
  6. results.push(match.startIndex);
  7. });
  8. return results;
  9. }
  10. test("default options", function(t) {
  11. t.deepEqual(styleSearchResults({
  12. source: "abc cba",
  13. target: "c",
  14. }), [ 2, 4 ]);
  15. t.deepEqual(styleSearchResults({
  16. source: "abc cb",
  17. target: "a",
  18. }), [0]);
  19. t.deepEqual(styleSearchResults({
  20. source: "abc cba",
  21. target: "b",
  22. }), [ 1, 5 ]);
  23. t.deepEqual(styleSearchResults({
  24. source: "abc \"var(--cba)\"",
  25. target: "a",
  26. }), [0]);
  27. t.end();
  28. });
  29. test("once", function(t) {
  30. t.deepEqual(styleSearchResults({
  31. source: "abc cba",
  32. target: "c",
  33. once: true,
  34. }), [2]);
  35. t.deepEqual(styleSearchResults({
  36. source: "abc cba",
  37. target: "a",
  38. once: true,
  39. }), [0]);
  40. t.deepEqual(styleSearchResults({
  41. source: "abc cba",
  42. target: "b",
  43. once: false,
  44. }), [ 1, 5 ]);
  45. t.end();
  46. });
  47. test("functionArguments: 'only'", function(t) {
  48. t.deepEqual(styleSearchResults({
  49. source: "abc var(--cba)",
  50. target: "c",
  51. functionArguments: "only",
  52. }), [10]);
  53. t.deepEqual(styleSearchResults({
  54. source: "abc var(--cba)",
  55. target: "a",
  56. functionArguments: "only",
  57. }), [12]);
  58. t.deepEqual(styleSearchResults({
  59. source: "abc \"var(--cba)\"",
  60. target: "a",
  61. functionArguments: "only",
  62. }), []);
  63. t.deepEqual(styleSearchResults({
  64. source: "translate(1px, calc(1px * 2))",
  65. target: "1",
  66. functionArguments: "only",
  67. }), [ 10, 20 ]);
  68. t.deepEqual(styleSearchResults({
  69. source: "var(--horse)",
  70. target: "v",
  71. functionArguments: "only",
  72. }), []);
  73. t.deepEqual(styleSearchResults({
  74. source: "abc (abc)",
  75. target: "b",
  76. functionArguments: "only",
  77. }), [], "parens without function is not interpreted as a function");
  78. t.deepEqual(styleSearchResults({
  79. source: "de$(abc)fg",
  80. target: "b",
  81. functionArguments: "only",
  82. }), [], "parens preceded by `$`, for postcss-simple-vars interpolation, not interpreted as a function");
  83. t.deepEqual(styleSearchResults({
  84. source: "de$(abc)fg",
  85. target: ")",
  86. functionArguments: "only",
  87. }), [], "closing paren of non-function is ignored");
  88. t.end();
  89. });
  90. test("functionArguments: 'skip'", function(t) {
  91. t.deepEqual(styleSearchResults({
  92. source: "abc var(--cba)",
  93. target: "c",
  94. functionArguments: "skip",
  95. }), [2]);
  96. t.deepEqual(styleSearchResults({
  97. source: "abc var(--cba)",
  98. target: "a",
  99. functionArguments: "skip",
  100. }), [0]);
  101. t.deepEqual(styleSearchResults({
  102. source: "abc \"a var(--cba)\"",
  103. target: "a",
  104. functionArguments: "skip",
  105. }), [0]);
  106. t.deepEqual(styleSearchResults({
  107. source: "translate(1px, calc(1px * 2))",
  108. target: "1",
  109. functionArguments: "skip",
  110. }), []);
  111. t.deepEqual(styleSearchResults({
  112. source: "var(--horse)",
  113. target: "v",
  114. functionArguments: "skip",
  115. }), []);
  116. t.deepEqual(styleSearchResults({
  117. source: "abc (def)",
  118. target: "e",
  119. functionArguments: "skip",
  120. }), [6], "parens without function is not interpreted as a function");
  121. t.end();
  122. });
  123. test("parentheticals: 'skip'", function(t) {
  124. t.deepEqual(styleSearchResults({
  125. source: "abc var(--cba)",
  126. target: "c",
  127. parentheticals: "skip",
  128. }), [2]);
  129. t.deepEqual(styleSearchResults({
  130. source: "abc var(--cba)",
  131. target: "a",
  132. parentheticals: "skip",
  133. }), [0]);
  134. t.deepEqual(styleSearchResults({
  135. source: "abc \"a var(--cba)\"",
  136. target: "a",
  137. parentheticals: "skip",
  138. }), [0]);
  139. t.deepEqual(styleSearchResults({
  140. source: "translate(1px, calc(1px * 2))",
  141. target: "1",
  142. parentheticals: "skip",
  143. }), []);
  144. t.deepEqual(styleSearchResults({
  145. source: "var(--horse)",
  146. target: "v",
  147. parentheticals: "skip",
  148. }), []);
  149. t.deepEqual(styleSearchResults({
  150. source: "abc (def)",
  151. target: "e",
  152. parentheticals: "skip",
  153. }), [], "parens without function are still ignored");
  154. t.end();
  155. });
  156. test("ignores matches inside single-quote strings", function(t) {
  157. t.deepEqual(styleSearchResults({
  158. source: "abc 'abc'",
  159. target: "c",
  160. }), [2]);
  161. t.deepEqual(styleSearchResults({
  162. source: "abc 'abc' cba",
  163. target: "c",
  164. }), [ 2, 10 ]);
  165. t.end();
  166. });
  167. test("ignores matches inside double-quote strings", function(t) {
  168. t.deepEqual(styleSearchResults({
  169. source: 'abc "abc"',
  170. target: "c",
  171. }), [2]);
  172. t.deepEqual(styleSearchResults({
  173. source: 'abc "abc" cba',
  174. target: "c",
  175. }), [ 2, 10 ]);
  176. t.end();
  177. });
  178. test("strings: 'check'", function(t) {
  179. t.deepEqual(styleSearchResults({
  180. source: "abc 'abc'",
  181. target: "b",
  182. strings: "check",
  183. }), [ 1, 6 ]);
  184. t.deepEqual(styleSearchResults({
  185. source: "abc /* 'abc' */",
  186. target: "b",
  187. strings: "check",
  188. }), [1], "no strings inside comments");
  189. t.end();
  190. });
  191. test("strings: 'only'", function(t) {
  192. t.deepEqual(styleSearchResults({
  193. source: 'abc "abc"',
  194. target: "b",
  195. strings: "only",
  196. }), [6]);
  197. t.deepEqual(styleSearchResults({
  198. source: "p[href^='https://']:before { content: \"\/*\"; \n top: 0;\n}",
  199. target: "\n",
  200. strings: "only",
  201. }), [], "comments do not start inside strings");
  202. t.end();
  203. });
  204. test("ignores matches inside comments", function(t) {
  205. t.deepEqual(styleSearchResults({
  206. source: "abc/*comment*/",
  207. target: "m",
  208. }), []);
  209. t.deepEqual(styleSearchResults({
  210. source: "abc/*command*/",
  211. target: "a",
  212. }), [0]);
  213. t.end();
  214. });
  215. test("comments: 'check'", function(t) {
  216. t.deepEqual(styleSearchResults({
  217. source: "abc/*abc*/",
  218. target: "b",
  219. comments: "check",
  220. }), [ 1, 6 ]);
  221. t.end();
  222. });
  223. test("comments: 'only'", function(t) {
  224. t.deepEqual(styleSearchResults({
  225. source: "abc/*abc*/",
  226. target: "b",
  227. comments: "only",
  228. }), [6]);
  229. t.deepEqual(styleSearchResults({
  230. source: "abc/*/abc*/",
  231. target: "b",
  232. comments: "only",
  233. }), [7]);
  234. t.deepEqual(styleSearchResults({
  235. source: "ab'c/*abc*/c'",
  236. target: "b",
  237. comments: "only",
  238. }), [], "no comments inside strings");
  239. t.end();
  240. });
  241. test("ignores matches inside single-line comment", function(t) {
  242. t.deepEqual(styleSearchResults({
  243. source: "abc // comment",
  244. target: "m",
  245. }), []);
  246. t.deepEqual(styleSearchResults({
  247. source: "abc // command",
  248. target: "a",
  249. }), [0]);
  250. // Triple-slash comments are used for sassdoc
  251. t.deepEqual(styleSearchResults({
  252. source: "abc /// it's all ok",
  253. target: "a",
  254. }), [0]);
  255. t.end();
  256. });
  257. test("handles escaped double-quotes in double-quote strings", function(t) {
  258. t.deepEqual(styleSearchResults({
  259. source: 'abc "ab\\"c"',
  260. target: "c",
  261. }), [2]);
  262. t.deepEqual(styleSearchResults({
  263. source: 'abc "a\\"bc" foo cba',
  264. target: "c",
  265. }), [ 2, 16 ]);
  266. t.end();
  267. });
  268. test("handles escaped double-quotes in single-quote strings", function(t) {
  269. t.deepEqual(styleSearchResults({
  270. source: "abc 'ab\\'c'",
  271. target: "c",
  272. }), [2]);
  273. t.deepEqual(styleSearchResults({
  274. source: "abc 'a\\'bc' foo cba",
  275. target: "c",
  276. }), [ 2, 16 ]);
  277. t.end();
  278. });
  279. test("count", function(t) {
  280. const endCounts = []
  281. styleSearch({ source: "123 123 123", target: "1" }, function(index, count) {
  282. endCounts.push(count);
  283. });
  284. t.deepEqual(endCounts, [ 1, 2, 3 ]);
  285. t.end();
  286. });
  287. test("finds parentheses", function(t) {
  288. t.deepEqual(styleSearchResults({
  289. source: "a { color: rgb(0,0,0); }",
  290. target: "(",
  291. }), [14]);
  292. t.deepEqual(styleSearchResults({
  293. source: "a { color: rgb(0,0,0); }",
  294. target: ")",
  295. }), [20]);
  296. t.end();
  297. });
  298. test("functionNames: 'check'", function(t) {
  299. t.deepEqual(styleSearchResults({
  300. source: "a { color: rgb(0,0,0); }",
  301. target: "rgb",
  302. }), []);
  303. t.deepEqual(styleSearchResults({
  304. source: "a { color: rgb(0,0,0); }",
  305. target: "rgb",
  306. functionNames: "check"
  307. }), [11]);
  308. t.end();
  309. });
  310. test("non-single-character target", function(t) {
  311. t.deepEqual(styleSearchResults({
  312. source: "abc cba",
  313. target: "abc",
  314. }), [0]);
  315. t.deepEqual(styleSearchResults({
  316. source: "abc cba",
  317. target: "cb",
  318. }), [4]);
  319. t.deepEqual(styleSearchResults({
  320. source: "abc cba",
  321. target: "c c",
  322. }), [2]);
  323. t.deepEqual(styleSearchResults({
  324. source: "abc cba abc",
  325. target: "abc",
  326. }), [ 0, 8 ]);
  327. t.deepEqual(styleSearchResults({
  328. source: "abc cba 'abc'",
  329. target: "abc",
  330. }), [0]);
  331. t.deepEqual(styleSearchResults({
  332. source: "abc cb",
  333. target: "aa",
  334. }), []);
  335. t.end();
  336. });
  337. test("array target", function(t) {
  338. t.deepEqual(styleSearchResults({
  339. source: "abc cba",
  340. target: [ "a", "b" ],
  341. }), [ 0, 1, 5, 6 ]);
  342. t.deepEqual(styleSearchResults({
  343. source: "abc cba",
  344. target: [ "c", "b" ],
  345. }), [ 1, 2, 4, 5 ]);
  346. t.deepEqual(styleSearchResults({
  347. source: "abc cba",
  348. target: [ "bc", "a" ],
  349. }), [ 0, 1, 6 ]);
  350. t.deepEqual(styleSearchResults({
  351. source: "abc cba",
  352. target: [ "abc", "f" ],
  353. }), [0]);
  354. t.deepEqual(styleSearchResults({
  355. source: "abc cba",
  356. target: [ 0, 1, 2 ],
  357. }), []);
  358. t.end();
  359. });
  360. test("match object", function(t) {
  361. styleSearch({ source: "abc", target: "bc" }, function(match) {
  362. t.equal(match.startIndex, 1);
  363. t.equal(match.endIndex, 3);
  364. t.equal(match.target, "bc");
  365. t.equal(match.insideFunctionArguments, false);
  366. t.equal(match.insideComment, false);
  367. });
  368. const twoMatches = []
  369. styleSearch({ source: "abc bca", target: [ "bc ", "ca" ] }, function(match) {
  370. twoMatches.push(match);
  371. });
  372. const firstMatch = twoMatches[0]
  373. const secondMatch = twoMatches[1]
  374. t.equal(firstMatch.startIndex, 1);
  375. t.equal(firstMatch.endIndex, 4);
  376. t.equal(firstMatch.target, "bc ");
  377. t.equal(firstMatch.insideFunctionArguments, false);
  378. t.equal(firstMatch.insideComment, false);
  379. t.equal(secondMatch.startIndex, 5);
  380. t.equal(secondMatch.endIndex, 7);
  381. t.equal(secondMatch.target, "ca");
  382. t.equal(secondMatch.insideFunctionArguments, false);
  383. t.equal(secondMatch.insideComment, false);
  384. t.end();
  385. });
  386. test("match inside a function", function(t) {
  387. styleSearch({ source: "a { color: rgb(0, 0, 1); }", target: "1" }, function(match) {
  388. t.equal(match.insideFunctionArguments, true);
  389. t.equal(match.insideComment, false);
  390. t.end();
  391. });
  392. });
  393. test("match inside a comment", function(t) {
  394. styleSearch({
  395. source: "a { color: /* 1 */ pink; }",
  396. target: "1",
  397. comments: "check"
  398. }, function(match) {
  399. t.equal(match.insideFunctionArguments, false);
  400. t.equal(match.insideComment, true);
  401. t.end();
  402. });
  403. });
  404. test("match inside a block comment", function(t) {
  405. styleSearch({
  406. source: "a { color:\n/**\n * 0\n * 1\n */\npink; }",
  407. target: "1",
  408. comments: "check"
  409. }, function(match) {
  410. t.equal(match.insideFunctionArguments, false);
  411. t.equal(match.insideComment, true);
  412. t.end();
  413. });
  414. });
  415. test("match inside a comment inside function", function(t) {
  416. styleSearch({
  417. source: "a { color: rgb(0, 0, 0 /* 1 */); }",
  418. target: "1",
  419. comments: "check"
  420. }, function(match) {
  421. t.equal(match.insideFunctionArguments, true);
  422. t.equal(match.insideComment, true);
  423. t.end();
  424. });
  425. });
  426. test("error on multiple 'only' options", function(t) {
  427. t.throws(function() {
  428. styleSearch({
  429. source: "a {}",
  430. target: "a",
  431. comments: "only",
  432. strings: "only",
  433. }, function(match) {});
  434. }, /Only one syntax/);
  435. t.end();
  436. });