1
1
"use strict" ;
2
2
3
- const { assert } = require ( " chai" ) ;
3
+ const { assert } = require ( ' chai' ) ;
4
4
const PrismLoader = require ( './helper/prism-loader' ) ;
5
5
const { languages } = require ( '../components' ) ;
6
6
7
+
7
8
for ( const lang in languages ) {
8
9
if ( lang === 'meta' ) {
9
10
continue ;
@@ -13,19 +14,57 @@ for (const lang in languages) {
13
14
14
15
const Prism = PrismLoader . createInstance ( lang ) ;
15
16
16
- it ( '- should not match the empty string' , function ( ) {
17
- let lastToken = '<unknown>' ;
17
+ /**
18
+ * Invokes the given function on every pattern in `Prism.languages`.
19
+ *
20
+ * @param {(values: { pattern: RegExp, tokenName: string, name: string, parent: any }) => void } callback
21
+ */
22
+ function forEachPattern ( callback ) {
23
+ /** @type {Map<string, string> } */
24
+ const nameMap = new Map ( ) ;
18
25
19
26
Prism . languages . DFS ( Prism . languages , function ( name , value ) {
20
- if ( typeof this === 'object' && ! Array . isArray ( this ) && name !== 'pattern' ) {
21
- lastToken = name ;
27
+ let path = nameMap . get ( this ) || '<languages>' ;
28
+ if ( / ^ \d + $ / . test ( name ) ) {
29
+ path += `[${ name } ]` ;
30
+ } else if ( / ^ [ a - z ] \w * $ / i. test ( name ) ) {
31
+ path += `.${ name } ` ;
32
+ } else {
33
+ path += `[${ JSON . stringify ( name ) } ]` ;
34
+ }
35
+ if ( Array . isArray ( value ) || Prism . util . type ( value ) === 'Object' ) {
36
+ nameMap . set ( value , path ) ;
22
37
}
23
38
24
39
if ( Prism . util . type ( value ) === 'RegExp' ) {
25
- assert . notMatch ( '' , value , `Token '${ lastToken } ': ${ value } should not match the empty string.` ) ;
40
+ callback ( {
41
+ pattern : value ,
42
+ tokenName : path ,
43
+ name,
44
+ parent : this ,
45
+ } ) ;
26
46
}
27
47
} ) ;
48
+ }
28
49
50
+
51
+ it ( '- should not match the empty string' , function ( ) {
52
+ forEachPattern ( ( { pattern, tokenName } ) => {
53
+ // test for empty string
54
+ assert . notMatch ( '' , pattern , `Token ${ tokenName } : ${ pattern } should not match the empty string.` ) ;
55
+ } ) ;
56
+ } ) ;
57
+
58
+ it ( '- should have a capturing group if lookbehind is set to true' , function ( ) {
59
+ forEachPattern ( ( { pattern, tokenName, name, parent } ) => {
60
+ if ( name === 'pattern' && parent . lookbehind ) {
61
+ const simplifiedSource = pattern . source . replace ( / \\ \D / g, '_' ) . replace ( / \[ [ ^ \] ] * \] / g, '_' ) ;
62
+
63
+ if ( ! / \( (? ! \? ) / . test ( simplifiedSource ) ) {
64
+ assert . fail ( `Token ${ tokenName } : The pattern is set to 'lookbehind: true' but does not have a capturing group.` ) ;
65
+ }
66
+ }
67
+ } ) ;
29
68
} ) ;
30
69
} ) ;
31
70
}
0 commit comments