1+ import type { HighlightOptions } from '../../../extend/syntax_highlight' ;
12import type Hexo from '../../../hexo' ;
23import type { RenderData } from '../../../types' ;
34
45const rBacktick = / ^ ( (?: (?: [ ^ \S \r \n ] * > ) { 0 , 3 } | [ - * + ] | [ 0 - 9 ] + \. ) [ ^ \S \r \n ] * ) ( ` { 3 , } | ~ { 3 , } ) [ ^ \S \r \n ] * ( (?: .* ?[ ^ ` \s ] ) ? ) [ ^ \S \r \n ] * \n ( (?: [ \s \S ] * ?\n ) ? ) (?: (?: [ ^ \S \r \n ] * > ) { 0 , 3 } [ ^ \S \r \n ] * ) \2[ ^ \S \r \n ] ? ( \n + | $ ) / gm;
56const rAllOptions = / ( [ ^ \s ] + ) \s + ( .+ ?) \s + ( h t t p s ? : \/ \/ \S + | \/ \S + ) \s * ( .+ ) ? / ;
67const rLangCaption = / ( [ ^ \s ] + ) \s * ( .+ ) ? / ;
8+ const rAdditionalOptions = / \s ( (?: l i n e _ n u m b e r | l i n e _ t h r e s h o l d | f i r s t _ l i n e | w r a p | m a r k | l a n g u a g e _ a t t r | h i g h l i g h t ) : \S + ) / g;
79
810const escapeSwigTag = ( str : string ) => str . replace ( / { / g, '{' ) . replace ( / } / g, '}' ) ;
911
10- interface Options {
11- lang : string ,
12- caption : string ,
13- lines_length : number ,
14- firstLineNumber ?: string | number
12+ function parseArgs ( args : string ) {
13+ const matches = [ ] ;
14+
15+ let match : RegExpExecArray | null , language_attr : boolean ,
16+ line_number : boolean , line_threshold : number , wrap : boolean ;
17+ let enableHighlight = true ;
18+ while ( ( match = rAdditionalOptions . exec ( args ) ) !== null ) {
19+ matches . push ( match [ 1 ] ) ;
20+ }
21+
22+ const len = matches . length ;
23+ const mark : number [ ] = [ ] ;
24+ let firstLine = 1 ;
25+ for ( let i = 0 ; i < len ; i ++ ) {
26+ const [ key , value ] = matches [ i ] . split ( ':' ) ;
27+
28+ switch ( key ) {
29+ case 'highlight' :
30+ enableHighlight = value === 'true' ;
31+ break ;
32+ case 'line_number' :
33+ line_number = value === 'true' ;
34+ break ;
35+ case 'line_threshold' :
36+ if ( ! isNaN ( Number ( value ) ) ) line_threshold = + value ;
37+ break ;
38+ case 'first_line' :
39+ if ( ! isNaN ( Number ( value ) ) ) firstLine = + value ;
40+ break ;
41+ case 'wrap' :
42+ wrap = value === 'true' ;
43+ break ;
44+ case 'mark' : {
45+ for ( const cur of value . split ( ',' ) ) {
46+ const hyphen = cur . indexOf ( '-' ) ;
47+ if ( hyphen !== - 1 ) {
48+ let a = + cur . slice ( 0 , hyphen ) ;
49+ let b = + cur . slice ( hyphen + 1 ) ;
50+ if ( Number . isNaN ( a ) || Number . isNaN ( b ) ) continue ;
51+ if ( b < a ) { // switch a & b
52+ [ a , b ] = [ b , a ] ;
53+ }
54+
55+ for ( ; a <= b ; a ++ ) {
56+ mark . push ( a ) ;
57+ }
58+ }
59+ if ( ! isNaN ( Number ( cur ) ) ) mark . push ( + cur ) ;
60+ }
61+ break ;
62+ }
63+ case 'language_attr' : {
64+ language_attr = value === 'true' ;
65+ break ;
66+ }
67+ }
68+ }
69+ return {
70+ options : {
71+ language_attr,
72+ firstLine,
73+ line_number,
74+ line_threshold,
75+ mark,
76+ wrap
77+ } ,
78+ enableHighlight,
79+ _args : args . replace ( rAdditionalOptions , '' )
80+ } ;
1581}
1682
1783export = ( ctx : Hexo ) : ( data : RenderData ) => void => {
@@ -26,6 +92,10 @@ export = (ctx: Hexo): (data: RenderData) => void => {
2692 // neither highlight or prismjs is enabled, return escaped content directly.
2793 if ( ! ctx . extend . highlight . query ( ctx . config . syntax_highlighter ) ) return escapeSwigTag ( $0 ) ;
2894
95+ const parsedArgs = parseArgs ( _args ) ;
96+ if ( ! parsedArgs . enableHighlight ) return escapeSwigTag ( $0 ) ;
97+ _args = parsedArgs . _args ;
98+
2999 // Extract language and caption of code blocks
30100 const args = _args . split ( '=' ) . shift ( ) ;
31101 let lang : string , caption : string ;
@@ -54,10 +124,11 @@ export = (ctx: Hexo): (data: RenderData) => void => {
54124 content = content . replace ( regexp , '' ) ;
55125 }
56126
57- const options : Options = {
127+ const options : HighlightOptions = {
58128 lang,
59129 caption,
60- lines_length : content . split ( '\n' ) . length
130+ lines_length : content . split ( '\n' ) . length ,
131+ ...parsedArgs . options
61132 } ;
62133 // setup line number by inline
63134 _args = _args . replace ( '=+' , '=' ) ;
0 commit comments