1
1
/**
2
2
* @typedef {import('./types.js').Rule } Rule
3
3
* @typedef {import('./types.js').RulePseudo } RulePseudo
4
- * @typedef {import('./types.js').RulePseudoNth } RulePseudoNth
5
4
* @typedef {import('./types.js').RulePseudoSelector } RulePseudoSelector
6
5
* @typedef {import('./types.js').Parent } Parent
7
6
* @typedef {import('./types.js').Selector } Selector
@@ -16,9 +15,14 @@ import {parse as commas} from 'comma-separated-tokens'
16
15
import { hasProperty } from 'hast-util-has-property'
17
16
import { isElement } from 'hast-util-is-element'
18
17
import { whitespace } from 'hast-util-whitespace'
18
+ import fauxEsmNthCheck from 'nth-check'
19
19
import { zwitch } from 'zwitch'
20
20
import { any } from './any.js'
21
21
22
+ /** @type {import('nth-check').default } */
23
+ // @ts -expect-error
24
+ const nthCheck = fauxEsmNthCheck . default || fauxEsmNthCheck
25
+
22
26
/** @type {(rule: Rule | RulePseudo, element: Element, index: number | undefined, parent: Parent | undefined, state: SelectState) => boolean } */
23
27
const handle = zwitch ( 'name' , {
24
28
unknown : unknownPseudo ,
@@ -375,64 +379,66 @@ function onlyChild(query, _1, _2, _3, state) {
375
379
}
376
380
377
381
/**
378
- * @param {RulePseudoNth } query
382
+ * @param {RulePseudo } query
379
383
* @param {Element } _1
380
384
* @param {number | undefined } _2
381
385
* @param {Parent | undefined } _3
382
386
* @param {SelectState } state
383
387
* @returns {boolean }
384
388
*/
385
389
function nthChild ( query , _1 , _2 , _3 , state ) {
390
+ const fn = getCachedNthCheck ( query )
386
391
assertDeep ( state , query )
387
- return (
388
- typeof state . elementIndex === 'number' && query . value ( state . elementIndex )
389
- )
392
+ return typeof state . elementIndex === 'number' && fn ( state . elementIndex )
390
393
}
391
394
392
395
/**
393
- * @param {RulePseudoNth } query
396
+ * @param {RulePseudo } query
394
397
* @param {Element } _1
395
398
* @param {number | undefined } _2
396
399
* @param {Parent | undefined } _3
397
400
* @param {SelectState } state
398
401
* @returns {boolean }
399
402
*/
400
403
function nthLastChild ( query , _1 , _2 , _3 , state ) {
404
+ const fn = getCachedNthCheck ( query )
401
405
assertDeep ( state , query )
402
406
return Boolean (
403
407
typeof state . elementCount === 'number' &&
404
408
typeof state . elementIndex === 'number' &&
405
- query . value ( state . elementCount - state . elementIndex - 1 )
409
+ fn ( state . elementCount - state . elementIndex - 1 )
406
410
)
407
411
}
408
412
409
413
/**
410
- * @param {RulePseudoNth } query
414
+ * @param {RulePseudo } query
411
415
* @param {Element } _1
412
416
* @param {number | undefined } _2
413
417
* @param {Parent | undefined } _3
414
418
* @param {SelectState } state
415
419
* @returns {boolean }
416
420
*/
417
421
function nthOfType ( query , _1 , _2 , _3 , state ) {
422
+ const fn = getCachedNthCheck ( query )
418
423
assertDeep ( state , query )
419
- return typeof state . typeIndex === 'number' && query . value ( state . typeIndex )
424
+ return typeof state . typeIndex === 'number' && fn ( state . typeIndex )
420
425
}
421
426
422
427
/**
423
- * @param {RulePseudoNth } query
428
+ * @param {RulePseudo } query
424
429
* @param {Element } _1
425
430
* @param {number | undefined } _2
426
431
* @param {Parent | undefined } _3
427
432
* @param {SelectState } state
428
433
* @returns {boolean }
429
434
*/
430
435
function nthLastOfType ( query , _1 , _2 , _3 , state ) {
436
+ const fn = getCachedNthCheck ( query )
431
437
assertDeep ( state , query )
432
438
return (
433
439
typeof state . typeCount === 'number' &&
434
440
typeof state . typeIndex === 'number' &&
435
- query . value ( state . typeCount - 1 - state . typeIndex )
441
+ fn ( state . typeCount - 1 - state . typeIndex )
436
442
)
437
443
}
438
444
@@ -517,7 +523,7 @@ function unknownPseudo(query) {
517
523
518
524
/**
519
525
* @param {SelectState } state
520
- * @param {RulePseudo | RulePseudoNth } query
526
+ * @param {RulePseudo } query
521
527
*/
522
528
function assertDeep ( state , query ) {
523
529
if ( state . shallow ) {
@@ -581,3 +587,22 @@ function appendScope(value) {
581
587
582
588
return selector
583
589
}
590
+
591
+ /**
592
+ * @param {RulePseudo } query
593
+ * @returns {(value: number) => boolean }
594
+ */
595
+ function getCachedNthCheck ( query ) {
596
+ /** @type {(value: number) => boolean } */
597
+ // @ts -expect-error: cache.
598
+ let fn = query . _cachedFn
599
+
600
+ if ( ! fn ) {
601
+ // @ts -expect-error: always string.
602
+ fn = nthCheck ( query . value )
603
+ // @ts -expect-error: cache.
604
+ query . _cachedFn = fn
605
+ }
606
+
607
+ return fn
608
+ }
0 commit comments