Skip to content

Commit 501e251

Browse files
authored
Convert 27 JavaScript files to TypeScript (#57693)
1 parent 647e0dc commit 501e251

31 files changed

+374
-176
lines changed

next.config.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,29 @@ import fs from 'fs'
22
import path from 'path'
33

44
import frontmatter from '@gr2m/gray-matter'
5-
import { getLogLevelNumber } from './src/observability/logger/lib/log-levels.js'
5+
// Hardcoded log level function since next.config.js cannot import from TypeScript files
6+
// Matches ./src/observability/logger/lib/log-levels
7+
function getLogLevelNumber() {
8+
const LOG_LEVELS = {
9+
error: 0,
10+
warn: 1,
11+
info: 2,
12+
debug: 3,
13+
}
14+
15+
let defaultLogLevel = 'info'
16+
if (
17+
!process.env.LOG_LEVEL &&
18+
(process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test')
19+
) {
20+
defaultLogLevel = 'debug'
21+
}
22+
23+
const envLogLevel = process.env.LOG_LEVEL?.toLowerCase() || defaultLogLevel
24+
const logLevel = LOG_LEVELS[envLogLevel] !== undefined ? envLogLevel : defaultLogLevel
25+
26+
return LOG_LEVELS[logLevel]
27+
}
628

729
// Replace imports with hardcoded values
830
const ROOT = process.env.ROOT || '.'

src/content-linter/lib/helpers/schema-utils.js

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { getFrontmatter } from './utils'
2+
3+
// AJV validation error object structure
4+
interface AjvValidationError {
5+
instancePath: string
6+
keyword: string
7+
message: string
8+
params: {
9+
additionalProperty?: string
10+
missingProperty?: string
11+
[key: string]: unknown
12+
}
13+
}
14+
15+
// Processed error object for markdown linting
16+
interface ProcessedValidationError {
17+
instancePath: string
18+
detail: string
19+
context: string
20+
errorProperty: string
21+
searchProperty: string
22+
}
23+
24+
export function formatAjvErrors(errors: AjvValidationError[] = []): ProcessedValidationError[] {
25+
const processedErrors: ProcessedValidationError[] = []
26+
27+
errors.forEach((errorObj: AjvValidationError) => {
28+
const error: Partial<ProcessedValidationError> = {}
29+
30+
error.instancePath =
31+
errorObj.instancePath === ''
32+
? errorObj.instancePath
33+
: errorObj.instancePath.slice(1).replace('/', '.')
34+
35+
if (errorObj.keyword === 'additionalProperties') {
36+
error.detail = 'The frontmatter includes an unsupported property.'
37+
const pathContext = error.instancePath ? ` from \`${error.instancePath}\`` : ''
38+
error.context = `Remove the property \`${errorObj.params.additionalProperty}\`${pathContext}.`
39+
error.errorProperty = errorObj.params.additionalProperty
40+
error.searchProperty = error.errorProperty
41+
}
42+
43+
// required rule
44+
if (errorObj.keyword === 'required') {
45+
error.detail = 'The frontmatter has a missing required property'
46+
const pathContext = error.instancePath ? ` from \`${error.instancePath}\`` : ''
47+
error.context = `Add the missing property \`${errorObj.params.missingProperty}\`${pathContext}`
48+
error.errorProperty = errorObj.params.missingProperty
49+
error.searchProperty = error.instancePath.split('.').pop()
50+
}
51+
52+
// all other rules
53+
if (!error.detail) {
54+
error.detail = `Frontmatter ${errorObj.message}.`
55+
error.context = Object.values(errorObj.params).join('')
56+
error.errorProperty = error.context
57+
error.searchProperty = error.errorProperty
58+
}
59+
60+
processedErrors.push(error as ProcessedValidationError)
61+
})
62+
63+
return processedErrors
64+
}
65+
66+
// Alias for backward compatibility
67+
export const processSchemaValidationErrors = formatAjvErrors
68+
69+
// Schema validator interface - generic due to different schema types (AJV, JSON Schema, etc.)
70+
interface SchemaValidator {
71+
validate(data: unknown): boolean
72+
}
73+
74+
export function getSchemaValidator(
75+
frontmatterLines: string[],
76+
): (schema: SchemaValidator) => boolean {
77+
const frontmatter = getFrontmatter(frontmatterLines)
78+
return (schema: SchemaValidator) => schema.validate(frontmatter)
79+
}

src/content-linter/lib/linting-rules/frontmatter-hidden-docs.js renamed to src/content-linter/lib/linting-rules/frontmatter-hidden-docs.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't have TypeScript declarations
12
import { addError } from 'markdownlint-rule-helpers'
3+
import type { RuleParams, RuleErrorCallback } from '../../types'
24

35
import { getFrontmatter } from '../helpers/utils'
46

@@ -7,7 +9,7 @@ export const frontmatterHiddenDocs = {
79
description:
810
'Articles with frontmatter property `hidden` can only be located in specific products',
911
tags: ['frontmatter', 'feature', 'early-access'],
10-
function: (params, onError) => {
12+
function: (params: RuleParams, onError: RuleErrorCallback) => {
1113
const fm = getFrontmatter(params.lines)
1214
if (!fm || !fm.hidden) return
1315

@@ -24,7 +26,8 @@ export const frontmatterHiddenDocs = {
2426

2527
if (allowedProductPaths.some((allowedPath) => params.name.includes(allowedPath))) return
2628

27-
const hiddenLine = params.lines.find((line) => line.startsWith('hidden:'))
29+
const hiddenLine = params.lines.find((line: string) => line.startsWith('hidden:'))
30+
if (!hiddenLine) return
2831
const lineNumber = params.lines.indexOf(hiddenLine) + 1
2932

3033
addError(

src/content-linter/lib/linting-rules/github-owned-action-references.js renamed to src/content-linter/lib/linting-rules/github-owned-action-references.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't have TypeScript declarations
12
import { addError, ellipsify } from 'markdownlint-rule-helpers'
3+
import type { RuleParams, RuleErrorCallback } from '../../types'
24

35
import { getRange } from '../helpers/utils'
46
/*
57
This rule currently only checks for one hardcoded string but
6-
can be generalized in the future to check for strings that
8+
can be generalized in the future to check for strings that
79
have data reusables.
810
*/
911
export const githubOwnedActionReferences = {
1012
names: ['GHD013', 'github-owned-action-references'],
1113
description: 'GitHub-owned action references should not be hardcoded',
1214
tags: ['feature', 'actions'],
13-
function: (params, onError) => {
15+
function: (params: RuleParams, onError: RuleErrorCallback) => {
1416
const filepath = params.name
1517
if (filepath.startsWith('data/reusables/actions/action-')) return
1618

src/content-linter/lib/linting-rules/hardcoded-data-variable.js renamed to src/content-linter/lib/linting-rules/hardcoded-data-variable.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't have TypeScript declarations
12
import { addError, ellipsify } from 'markdownlint-rule-helpers'
3+
import type { RuleParams, RuleErrorCallback } from '../../types'
24

35
import { getRange } from '../helpers/utils'
46
import frontmatter from '@/frame/lib/read-frontmatter'
57

68
/*
79
This rule currently only checks for one hardcoded string but
8-
can be generalized in the future to check for strings that
10+
can be generalized in the future to check for strings that
911
have data variables.
1012
*/
1113
export const hardcodedDataVariable = {
1214
names: ['GHD005', 'hardcoded-data-variable'],
1315
description:
1416
'Strings that contain "personal access token" should use the product variable instead',
1517
tags: ['single-source'],
16-
function: (params, onError) => {
18+
function: (params: RuleParams, onError: RuleErrorCallback) => {
1719
if (params.name.startsWith('data/variables/product.yml')) return
1820
const frontmatterString = params.frontMatterLines.join('\n')
1921
const fm = frontmatter(frontmatterString).data

src/content-linter/lib/linting-rules/image-alt-text-end-punctuation.js renamed to src/content-linter/lib/linting-rules/image-alt-text-end-punctuation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import {
55
isStringQuoted,
66
isStringPunctuated,
77
} from '../helpers/utils'
8+
import type { RuleParams, RuleErrorCallback } from '../../types'
89

910
export const imageAltTextEndPunctuation = {
1011
names: ['GHD032', 'image-alt-text-end-punctuation'],
1112
description: 'Alternate text for images should end with punctuation',
1213
tags: ['accessibility', 'images'],
1314
parser: 'markdownit',
14-
function: (params, onError) => {
15-
forEachInlineChild(params, 'image', function forToken(token) {
15+
function: (params: RuleParams, onError: RuleErrorCallback) => {
16+
forEachInlineChild(params, 'image', function forToken(token: any) {
1617
const imageAltText = token.content.trim()
1718

1819
// If the alt text is empty, there is nothing to check and you can't

src/content-linter/lib/linting-rules/image-alt-text-length.js renamed to src/content-linter/lib/linting-rules/image-alt-text-length.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't have TypeScript declarations
12
import { addError } from 'markdownlint-rule-helpers'
3+
import type { RuleParams, RuleErrorCallback } from '../../types'
24

35
import { liquid } from '@/content-render/index'
46
import { allVersions } from '@/versions/lib/all-versions'
57
import { forEachInlineChild, getRange } from '../helpers/utils'
68

9+
interface ImageToken {
10+
content: string
11+
lineNumber: number
12+
line: string
13+
range: [number, number]
14+
}
15+
716
export const incorrectAltTextLength = {
817
names: ['GHD033', 'incorrect-alt-text-length'],
918
description: 'Images alternate text should be between 40-150 characters',
1019
tags: ['accessibility', 'images'],
1120
parser: 'markdownit',
1221
asynchronous: true,
13-
function: (params, onError) => {
14-
forEachInlineChild(params, 'image', async function forToken(token) {
22+
function: (params: RuleParams, onError: RuleErrorCallback) => {
23+
forEachInlineChild(params, 'image', async function forToken(token: ImageToken) {
1524
let renderedString = token.content
1625

1726
if (token.content.includes('{%') || token.content.includes('{{')) {

src/content-linter/lib/linting-rules/link-punctuation.js renamed to src/content-linter/lib/linting-rules/link-punctuation.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't have TypeScript declarations
12
import { addError, filterTokens } from 'markdownlint-rule-helpers'
3+
import type { RuleParams, RuleErrorCallback } from '../../types'
24

35
import { doesStringEndWithPeriod, getRange, isStringQuoted } from '../helpers/utils'
46

@@ -7,8 +9,8 @@ export const linkPunctuation = {
79
description: 'Internal link titles must not contain punctuation',
810
tags: ['links', 'url'],
911
parser: 'markdownit',
10-
function: (params, onError) => {
11-
filterTokens(params, 'inline', (token) => {
12+
function: (params: RuleParams, onError: RuleErrorCallback) => {
13+
filterTokens(params, 'inline', (token: any) => {
1214
const { children, line } = token
1315
let inLink = false
1416
for (const child of children) {

src/content-linter/tests/learning-track-liquid.js renamed to src/content-linter/tests/learning-track-liquid.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,19 @@ describe('lint learning tracks', () => {
1818
if (yamlFileList.length < 1) return
1919

2020
describe.each(yamlFileList)('%s', (yamlAbsPath) => {
21-
let yamlContent
21+
// Using any type because YAML content structure is dynamic and varies per file
22+
let yamlContent: any
2223

2324
beforeAll(async () => {
2425
const fileContents = await readFile(yamlAbsPath, 'utf8')
2526
yamlContent = await yaml.load(fileContents)
2627
})
2728

2829
test('contains valid liquid', () => {
29-
const toLint = []
30-
Object.values(yamlContent).forEach(({ title, description }) => {
30+
// Using any[] for toLint since it contains mixed string content from various YAML properties
31+
const toLint: any[] = []
32+
// Using any for destructured params as YAML structure varies across different learning track files
33+
Object.values(yamlContent).forEach(({ title, description }: any) => {
3134
toLint.push(title)
3235
toLint.push(description)
3336
})

0 commit comments

Comments
 (0)