Skip to content

Commit 1d55948

Browse files
authored
Migrate 7 content-linter files to TypeScript (#58001)
1 parent fc1ff19 commit 1d55948

File tree

7 files changed

+70
-45
lines changed

7 files changed

+70
-45
lines changed

src/content-linter/lib/linting-rules/liquid-ifversion-versions.js renamed to src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't provide TypeScript declarations
12
import { addError } from 'markdownlint-rule-helpers'
23

34
import {
@@ -17,14 +18,15 @@ import {
1718
isInAllGhes,
1819
} from '@/ghes-releases/scripts/version-utils'
1920
import { deprecated, oldestSupported } from '@/versions/lib/enterprise-server-releases'
21+
import type { RuleParams, RuleErrorCallback } from '@/content-linter/types'
2022

2123
export const liquidIfversionVersions = {
2224
names: ['GHD022', 'liquid-ifversion-versions'],
2325
description:
2426
'Liquid `ifversion`, `elsif`, and `else` tags should be valid and not contain unsupported versions.',
2527
tags: ['liquid', 'versioning'],
2628
asynchronous: true,
27-
function: async (params, onError) => {
29+
function: async (params: RuleParams, onError: RuleErrorCallback) => {
2830
// The versions frontmatter object or all versions if the file
2931
// being processed is a data file.
3032
const fm = getFrontmatter(params.lines)
@@ -34,7 +36,7 @@ export const liquidIfversionVersions = {
3436
? { ghec: '*', ghes: '*', fpt: '*' }
3537
: fm
3638
? fm.versions
37-
: getFrontmatter(params.frontMatterLines).versions
39+
: getFrontmatter(params.frontMatterLines)?.versions
3840
// This will only contain valid (non-deprecated) and future versions
3941
const fileVersions = getApplicableVersions(fileVersionsFm, '', {
4042
doNotThrow: true,
@@ -45,7 +47,8 @@ export const liquidIfversionVersions = {
4547
// Array of arrays - each array entry is an array of items that
4648
// make up a full if/elsif/else/endif statement.
4749
// [ [ifversion, elsif, else, endif], [nested ifversion, elsif, else, endif] ]
48-
const condStmtStack = []
50+
// Using any[] because these are complex dynamic objects with properties added at runtime
51+
const condStmtStack: any[] = []
4952

5053
// Tokens are in the order they are read in file, so we need to iterate
5154
// through and group full if/elsif/else/endif statements together.
@@ -76,25 +79,28 @@ export const liquidIfversionVersions = {
7679
// The versions of an else tag are the set of file versions that are
7780
// not supported by the previous ifversion or elsif tags.
7881
const siblingVersions = condTagItems
79-
.filter((item) => item.name === 'ifversion' || item.name === 'elsif')
80-
.map((item) => item.versions)
82+
// Using any because condTagItems contains dynamic objects from initTagObject
83+
.filter((item: any) => item.name === 'ifversion' || item.name === 'elsif')
84+
.map((item: any) => item.versions)
8185
.flat()
82-
condTagItem.versions = difference(fileVersions, siblingVersions)
86+
// Using any because versions property is added dynamically to condTagItem
87+
;(condTagItem as any).versions = difference(fileVersions, siblingVersions)
8388
condTagItems.push(condTagItem)
8489
condStmtStack.push(condTagItems)
8590
} else if (token.name === 'endif') {
8691
defaultProps.parent = undefined
8792
const condTagItems = condStmtStack.pop()
8893
const condTagItem = await initTagObject(token, defaultProps)
8994
condTagItems.push(condTagItem)
90-
decorateCondTagItems(condTagItems, params.lines)
95+
decorateCondTagItems(condTagItems)
9196
setLiquidErrors(condTagItems, onError, params.lines)
9297
}
9398
}
9499
},
95100
}
96101

97-
function setLiquidErrors(condTagItems, onError, lines) {
102+
// Using any[] because condTagItems contains dynamic objects with properties added at runtime
103+
function setLiquidErrors(condTagItems: any[], onError: RuleErrorCallback, lines: string[]) {
98104
for (let i = 0; i < condTagItems.length; i++) {
99105
const item = condTagItems[i]
100106
const tagNameNoCond = item.name === 'endif' || item.name === 'else'
@@ -175,8 +181,9 @@ function setLiquidErrors(condTagItems, onError, lines) {
175181
}
176182
}
177183

178-
async function getApplicableVersionFromLiquidTag(conditionStr, filename) {
179-
const newConditionObject = {}
184+
async function getApplicableVersionFromLiquidTag(conditionStr: string) {
185+
// Using Record<string, any> because version object keys are dynamic (fpt, ghec, ghes, feature, etc.)
186+
const newConditionObject: Record<string, any> = {}
180187
const condition = conditionStr.replace('not ', '')
181188
const liquidTagVersions = condition.split(' or ').map((item) => item.trim())
182189
for (const ver of liquidTagVersions) {
@@ -227,7 +234,8 @@ async function getApplicableVersionFromLiquidTag(conditionStr, filename) {
227234
return newConditionObject
228235
}
229236

230-
async function initTagObject(token, props) {
237+
// Using any for token and props because they come from markdownlint library without full type definitions
238+
async function initTagObject(token: any, props: any) {
231239
const condTagItem = {
232240
name: token.name,
233241
cond: token.content.replace(`${token.name} `, '').trim(),
@@ -245,15 +253,17 @@ async function initTagObject(token, props) {
245253
parent: props.parent,
246254
}
247255
if (token.name === 'ifversion' || token.name === 'elsif') {
248-
condTagItem.versionsObj = await getApplicableVersionFromLiquidTag(
249-
condTagItem.cond,
250-
props.filename,
251-
)
252-
condTagItem.featureVersionsObj = condTagItem.versionsObj.feature
253-
? getFeatureVersionsObject(condTagItem.versionsObj.feature)
256+
// Using any because these properties (versionsObj, featureVersionsObj, versionsObjAll, versions)
257+
// are added dynamically to condTagItem and not part of its initial type definition
258+
;(condTagItem as any).versionsObj = await getApplicableVersionFromLiquidTag(condTagItem.cond)
259+
;(condTagItem as any).featureVersionsObj = (condTagItem as any).versionsObj.feature
260+
? getFeatureVersionsObject((condTagItem as any).versionsObj.feature)
254261
: undefined
255-
condTagItem.versionsObjAll = { ...condTagItem.versionsObj, ...condTagItem.featureVersionsObj }
256-
condTagItem.versions = getApplicableVersions(condTagItem.versionsObj, '', {
262+
;(condTagItem as any).versionsObjAll = {
263+
...(condTagItem as any).versionsObj,
264+
...(condTagItem as any).featureVersionsObj,
265+
}
266+
;(condTagItem as any).versions = getApplicableVersions((condTagItem as any).versionsObj, '', {
257267
doNotThrow: true,
258268
includeNextVersion: true,
259269
})
@@ -270,7 +280,8 @@ async function initTagObject(token, props) {
270280
Then create flaws per stack item.
271281
newCond
272282
*/
273-
function decorateCondTagItems(condTagItems, lines) {
283+
// Using any[] because condTagItems contains dynamic objects with action property added at runtime
284+
function decorateCondTagItems(condTagItems: any[]) {
274285
for (const item of condTagItems) {
275286
item.action = {
276287
type: 'none',
@@ -287,7 +298,8 @@ function decorateCondTagItems(condTagItems, lines) {
287298
return
288299
}
289300

290-
function updateConditionals(condTagItems) {
301+
// Using any[] because condTagItems contains dynamic objects with various properties added at runtime
302+
function updateConditionals(condTagItems: any[]) {
291303
// iterate through the ifversion, elsif, and else
292304
// tags but NOT the endif tag. endif tags have
293305
// no versions associated with them and are handled
@@ -470,7 +482,8 @@ function updateConditionals(condTagItems) {
470482
}
471483
}
472484

473-
function processConditionals(item, condTagItems, indexOfAllItem) {
485+
// Using any for item and any[] for condTagItems because they contain dynamic objects with action property
486+
function processConditionals(item: any, condTagItems: any[], indexOfAllItem: number) {
474487
item.action.type = 'all'
475488
// if any tag in a statement is 'all', the
476489
// remaining tags are obsolete.
File renamed without changes.

src/content-linter/tests/unit/frontmatter-versions-whitespace.js renamed to src/content-linter/tests/unit/frontmatter-versions-whitespace.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@ import { frontmatterVersionsWhitespace } from '@/content-linter/lib/linting-rule
66
// Configure the test fixture to not split frontmatter and content
77
const fmOptions = { markdownlintOptions: { frontMatter: null } }
88

9+
interface ValidTestCase {
10+
name: string
11+
content: string
12+
}
13+
14+
interface InvalidTestCase {
15+
name: string
16+
content: string
17+
expectedErrors: number
18+
expectedMessage?: string
19+
}
20+
921
// Valid cases - should pass
10-
const validCases = [
22+
const validCases: ValidTestCase[] = [
1123
{
1224
name: 'valid-simple-versions',
1325
content: `---
@@ -52,7 +64,7 @@ This is a test.
5264
]
5365

5466
// Invalid cases - should fail
55-
const invalidCases = [
67+
const invalidCases: InvalidTestCase[] = [
5668
{
5769
name: 'trailing-whitespace',
5870
content: `---
@@ -184,7 +196,7 @@ versions:
184196
})
185197
expect(result.content.length).toBe(1)
186198
expect(result.content[0].fixInfo).toBeDefined()
187-
expect(result.content[0].fixInfo.insertText).toBe('*')
199+
expect(result.content[0].fixInfo?.insertText).toBe('*')
188200
})
189201

190202
test('should provide fix information for leading whitespace', async () => {
@@ -202,7 +214,7 @@ versions:
202214
})
203215
expect(result.content.length).toBe(1)
204216
expect(result.content[0].fixInfo).toBeDefined()
205-
expect(result.content[0].fixInfo.insertText).toBe('*')
217+
expect(result.content[0].fixInfo?.insertText).toBe('*')
206218
})
207219
})
208220

src/content-linter/tests/unit/note-warning-formatting.js renamed to src/content-linter/tests/unit/note-warning-formatting.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
4646
const errors = result.markdown
4747
expect(errors.length).toBe(1)
4848
expect(errors[0].lineNumber).toBe(2)
49-
if (errors[0].detail) {
50-
expect(errors[0].detail).toContain('Add a blank line before {% note %}')
49+
if (errors[0].errorDetail) {
50+
expect(errors[0].errorDetail).toContain('Add a blank line before {% note %}')
5151
}
5252
})
5353

@@ -63,8 +63,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
6363
const errors = result.markdown
6464
expect(errors.length).toBe(1)
6565
expect(errors[0].lineNumber).toBe(4)
66-
if (errors[0].detail) {
67-
expect(errors[0].detail).toContain('Add a blank line after {% endnote %}')
66+
if (errors[0].errorDetail) {
67+
expect(errors[0].errorDetail).toContain('Add a blank line after {% endnote %}')
6868
}
6969
})
7070

@@ -78,8 +78,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
7878
const errors = result.markdown
7979
expect(errors.length).toBe(1)
8080
expect(errors[0].lineNumber).toBe(2)
81-
if (errors[0].detail) {
82-
expect(errors[0].detail).toContain('Add a blank line before > [!WARNING]')
81+
if (errors[0].errorDetail) {
82+
expect(errors[0].errorDetail).toContain('Add a blank line before > [!WARNING]')
8383
}
8484
})
8585

@@ -94,8 +94,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
9494
const errors = result.markdown
9595
expect(errors.length).toBe(1)
9696
expect(errors[0].lineNumber).toBe(4)
97-
if (errors[0].detail) {
98-
expect(errors[0].detail).toContain('Add a blank line after > [!DANGER]')
97+
if (errors[0].errorDetail) {
98+
expect(errors[0].errorDetail).toContain('Add a blank line after > [!DANGER]')
9999
}
100100
})
101101

@@ -117,8 +117,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
117117
const errors = result.markdown
118118
expect(errors.length).toBe(1)
119119
expect(errors[0].lineNumber).toBe(8)
120-
if (errors[0].detail) {
121-
expect(errors[0].detail).toContain('Do not include more than 2 bullet points')
120+
if (errors[0].errorDetail) {
121+
expect(errors[0].errorDetail).toContain('Do not include more than 2 bullet points')
122122
}
123123
})
124124

@@ -137,8 +137,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
137137
const errors = result.markdown
138138
expect(errors.length).toBe(1)
139139
expect(errors[0].lineNumber).toBe(7)
140-
if (errors[0].detail) {
141-
expect(errors[0].detail).toContain('Do not include more than 2 bullet points')
140+
if (errors[0].errorDetail) {
141+
expect(errors[0].errorDetail).toContain('Do not include more than 2 bullet points')
142142
}
143143
})
144144

@@ -156,12 +156,12 @@ describe(noteWarningFormatting.names.join(' - '), () => {
156156
const errors = result.markdown
157157
expect(errors.length).toBe(1)
158158
expect(errors[0].lineNumber).toBe(4)
159-
if (errors[0].detail) {
160-
expect(errors[0].detail).toContain('should start with **Note:**')
159+
if (errors[0].errorDetail) {
160+
expect(errors[0].errorDetail).toContain('should start with **Note:**')
161161
}
162162
expect(errors[0].fixInfo).toBeDefined()
163163
if (errors[0].fixInfo) {
164-
expect(errors[0].fixInfo.insertText).toBe('**Note:** ')
164+
expect(errors[0].fixInfo?.insertText).toBe('**Note:** ')
165165
}
166166
})
167167

@@ -177,8 +177,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
177177
const errors = result.markdown
178178
expect(errors.length).toBe(1)
179179
expect(errors[0].lineNumber).toBe(3)
180-
if (errors[0].detail) {
181-
expect(errors[0].detail).toContain('should be inside a callout block')
180+
if (errors[0].errorDetail) {
181+
expect(errors[0].errorDetail).toContain('should be inside a callout block')
182182
}
183183
})
184184

@@ -194,8 +194,8 @@ describe(noteWarningFormatting.names.join(' - '), () => {
194194
const errors = result.markdown
195195
expect(errors.length).toBe(1)
196196
expect(errors[0].lineNumber).toBe(3)
197-
if (errors[0].detail) {
198-
expect(errors[0].detail).toContain('Warning prefix should be inside a callout block')
197+
if (errors[0].errorDetail) {
198+
expect(errors[0].errorDetail).toContain('Warning prefix should be inside a callout block')
199199
}
200200
})
201201

0 commit comments

Comments
 (0)