1- import { Tag , isTruthy , Value , TokenizationError } from 'liquidjs'
1+ import {
2+ Tag ,
3+ isTruthy ,
4+ Value ,
5+ TokenizationError ,
6+ type TagToken ,
7+ type Context ,
8+ type Emitter ,
9+ type Template ,
10+ type TopLevelToken ,
11+ } from 'liquidjs'
212import versionSatisfiesRange from '@/versions/lib/version-satisfies-range'
3- import supportedOperators from './ifversion-supported-operators'
13+ import supportedOperators , {
14+ type IfversionSupportedOperator ,
15+ } from './ifversion-supported-operators'
16+
17+ interface Branch {
18+ cond : string
19+ templates : Template [ ]
20+ }
21+
22+ interface VersionObj {
23+ shortName : string
24+ hasNumberedReleases ?: boolean
25+ currentRelease ?: string
26+ internalLatestRelease ?: string
27+ }
428
529const SyntaxHelp =
630 "Syntax Error in 'ifversion' with range - Valid syntax: ifversion [plan] [operator] [releaseNumber]"
@@ -14,15 +38,20 @@ const notRegex = /(?:^|\s)not\s/
1438// using semver to evaluate release numbers instead of doing standard number comparisons, which
1539// don't work the way we want because they evaluate 3.2 > 3.10 = true.
1640export default class extends Tag {
41+ tagToken : TagToken
42+ branches : Branch [ ]
43+ elseTemplates : Template [ ]
44+ currentVersionObj : VersionObj | null = null
45+
1746 // The following is verbatim from https://github.com/harttle/liquidjs/blob/v9.22.1/src/builtin/tags/if.ts
18- constructor ( tagToken , remainTokens , liquid ) {
47+ constructor ( tagToken : TagToken , remainTokens : TopLevelToken [ ] , liquid : any ) {
1948 super ( tagToken , remainTokens , liquid )
2049
2150 this . tagToken = tagToken
2251 this . branches = [ ]
2352 this . elseTemplates = [ ]
2453
25- let p
54+ let p : Template [ ]
2655 const stream = this . liquid . parser
2756 . parseStream ( remainTokens )
2857 . on ( 'start' , ( ) =>
@@ -31,15 +60,15 @@ export default class extends Tag {
3160 templates : ( p = [ ] ) ,
3261 } ) ,
3362 )
34- . on ( 'tag:elsif' , ( token ) => {
63+ . on ( 'tag:elsif' , ( token : any ) => {
3564 this . branches . push ( {
3665 cond : token . args ,
3766 templates : ( p = [ ] ) ,
3867 } )
3968 } )
4069 . on ( 'tag:else' , ( ) => ( p = this . elseTemplates ) )
4170 . on ( 'tag:endif' , ( ) => stream . stop ( ) )
42- . on ( 'template' , ( tpl ) => p . push ( tpl ) )
71+ . on ( 'template' , ( tpl : Template ) => p . push ( tpl ) )
4372 . on ( 'end' , ( ) => {
4473 throw new Error ( `tag ${ tagToken . getText ( ) } not closed` )
4574 } )
@@ -49,10 +78,10 @@ export default class extends Tag {
4978
5079 // The following is _mostly_ verbatim from https://github.com/harttle/liquidjs/blob/v9.22.1/src/builtin/tags/if.ts
5180 // The additions here are the handleNots(), handleOperators(), and handleVersionNames() calls.
52- * render ( ctx , emitter ) {
81+ * render ( ctx : Context , emitter : Emitter ) : Generator < any , void , unknown > {
5382 const r = this . liquid . renderer
5483
55- this . currentVersionObj = ctx . environments . currentVersionObj
84+ this . currentVersionObj = ( ctx . environments as any ) . currentVersionObj
5685
5786 for ( const branch of this . branches ) {
5887 let resolvedBranchCond = branch . cond
@@ -67,8 +96,8 @@ export default class extends Tag {
6796 // Resolve version names to boolean values for Markdown API context.
6897 // This will replace syntax like `fpt or ghec` with `true or false` based on current version.
6998 // Only apply this transformation in Markdown API context to avoid breaking existing functionality.
70- if ( ctx . environments . markdownRequested ) {
71- resolvedBranchCond = this . handleVersionNames ( resolvedBranchCond , ctx )
99+ if ( ( ctx . environments as any ) . markdownRequested ) {
100+ resolvedBranchCond = this . handleVersionNames ( resolvedBranchCond )
72101 }
73102
74103 // Use Liquid's native function for the final evaluation.
@@ -82,13 +111,13 @@ export default class extends Tag {
82111 yield r . renderTemplates ( this . elseTemplates , ctx , emitter )
83112 }
84113
85- handleNots ( resolvedBranchCond ) {
114+ handleNots ( resolvedBranchCond : string ) : string {
86115 if ( ! notRegex . test ( resolvedBranchCond ) ) return resolvedBranchCond
87116
88117 const condArray = resolvedBranchCond . split ( ' ' )
89118
90119 // Find the first index in the array that contains "not".
91- const notIndex = condArray . findIndex ( ( el ) => el === 'not' )
120+ const notIndex = condArray . findIndex ( ( el : string ) => el === 'not' )
92121
93122 // E.g., ['not', 'fpt']
94123 const condParts = condArray . slice ( notIndex , notIndex + 2 )
@@ -99,10 +128,10 @@ export default class extends Tag {
99128 // If the current version is the version being evaluated in the conditional,
100129 // that is negated and resolved to false. If it's NOT the version being
101130 // evaluated, that resolves to true.
102- const resolvedBoolean = ! ( versionToEvaluate === this . currentVersionObj . shortName )
131+ const resolvedBoolean = ! ( versionToEvaluate === this . currentVersionObj ! . shortName )
103132
104133 // Replace syntax like `not fpt` with `true` or `false`.
105- resolvedBranchCond = resolvedBranchCond . replace ( condParts . join ( ' ' ) , resolvedBoolean )
134+ resolvedBranchCond = resolvedBranchCond . replace ( condParts . join ( ' ' ) , String ( resolvedBoolean ) )
106135
107136 // Run this function recursively until we've resolved all the nots.
108137 if ( notRegex . test ( resolvedBranchCond ) ) {
@@ -112,14 +141,16 @@ export default class extends Tag {
112141 return resolvedBranchCond
113142 }
114143
115- handleOperators ( resolvedBranchCond ) {
144+ handleOperators ( resolvedBranchCond : string ) : string {
116145 if ( ! supportedOperatorsRegex . test ( resolvedBranchCond ) ) return resolvedBranchCond
117146
118147 // If this conditional contains multiple parts using `or` or `and`, get only the conditional with operators.
119148 const condArray = resolvedBranchCond . split ( ' ' )
120149
121150 // Find the first index in the array that contains an operator.
122- const operatorIndex = condArray . findIndex ( ( el ) => supportedOperators . find ( ( op ) => el === op ) )
151+ const operatorIndex = condArray . findIndex ( ( el : string ) =>
152+ supportedOperators . find ( ( op : string ) => el === op ) ,
153+ )
123154
124155 // E.g., ['ghes', '<', '3.1']
125156 const condParts = condArray . slice ( operatorIndex - 1 , operatorIndex + 2 )
@@ -129,7 +160,8 @@ export default class extends Tag {
129160
130161 // Make sure the operator is supported and the release number matches `\d\d?\.\d\d?`
131162 const syntaxError =
132- ! supportedOperators . includes ( operator ) || ! releaseRegex . test ( releaseToEvaluate )
163+ ! supportedOperators . includes ( operator as IfversionSupportedOperator ) ||
164+ ! releaseRegex . test ( releaseToEvaluate )
133165
134166 if ( syntaxError ) {
135167 throw new TokenizationError ( SyntaxHelp , this . tagToken )
@@ -154,25 +186,25 @@ export default class extends Tag {
154186 ? this . currentVersionObj . currentRelease
155187 : this . currentVersionObj . internalLatestRelease
156188
157- let resolvedBoolean
189+ let resolvedBoolean : boolean
158190 if ( operator === '!=' ) {
159191 // If this is the current plan, compare the release numbers. (Our semver package doesn't handle !=.)
160192 // If it's not the current version, it's always true.
161193 resolvedBoolean =
162- versionShortName === this . currentVersionObj . shortName
194+ versionShortName === this . currentVersionObj ! . shortName
163195 ? releaseToEvaluate !== currentRelease
164196 : true
165197 } else {
166198 // If this is the current plan, evaluate the operator using semver.
167199 // If it's not the current plan, it's always false.
168200 resolvedBoolean =
169- versionShortName === this . currentVersionObj . shortName
170- ? versionSatisfiesRange ( currentRelease , `${ operator } ${ releaseToEvaluate } ` )
201+ versionShortName === this . currentVersionObj ! . shortName
202+ ? versionSatisfiesRange ( currentRelease ! , `${ operator } ${ releaseToEvaluate } ` )
171203 : false
172204 }
173205
174206 // Replace syntax like `fpt or ghes < 3.0` with `fpt or true` or `fpt or false`.
175- resolvedBranchCond = resolvedBranchCond . replace ( condParts . join ( ' ' ) , resolvedBoolean )
207+ resolvedBranchCond = resolvedBranchCond . replace ( condParts . join ( ' ' ) , String ( resolvedBoolean ) )
176208
177209 // Run this function recursively until we've resolved all the special operators.
178210 if ( supportedOperatorsRegex . test ( resolvedBranchCond ) ) {
@@ -182,21 +214,21 @@ export default class extends Tag {
182214 return resolvedBranchCond
183215 }
184216
185- handleVersionNames ( resolvedBranchCond , ctx ) {
217+ handleVersionNames ( resolvedBranchCond : string ) : string {
186218 if ( ! this . currentVersionObj ) {
187219 console . warn ( 'currentVersionObj not found in ifversion context.' )
188220 return resolvedBranchCond
189221 }
190222
191223 // Split the condition into tokens for processing
192224 const tokens = resolvedBranchCond . split ( / \s + / )
193- const processedTokens = tokens . map ( ( token ) => {
225+ const processedTokens = tokens . map ( ( token : string ) => {
194226 // Check if the token is a version short name (fpt, ghec, ghes, ghae)
195227 const versionShortNames = [ 'fpt' , 'ghec' , 'ghes' , 'ghae' ]
196228 if ( versionShortNames . includes ( token ) ) {
197229 // Transform version names to boolean values for Markdown API
198230 // This fixes the original issue where version names were undefined in API context
199- return token === this . currentVersionObj . shortName ? 'true' : 'false'
231+ return token === this . currentVersionObj ! . shortName ? 'true' : 'false'
200232 }
201233 // Return the token unchanged if it's not a version name
202234 return token
0 commit comments