11"use strict" ;
22
3- const { assert } = require ( " chai" ) ;
3+ const { assert } = require ( ' chai' ) ;
44const PrismLoader = require ( './helper/prism-loader' ) ;
55const { languages } = require ( '../components' ) ;
66
7+
78for ( const lang in languages ) {
89 if ( lang === 'meta' ) {
910 continue ;
@@ -13,19 +14,57 @@ for (const lang in languages) {
1314
1415 const Prism = PrismLoader . createInstance ( lang ) ;
1516
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 ( ) ;
1825
1926 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 ) ;
2237 }
2338
2439 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+ } ) ;
2646 }
2747 } ) ;
48+ }
2849
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+ } ) ;
2968 } ) ;
3069 } ) ;
3170}
0 commit comments