Skip to content

Commit e1713a7

Browse files
authored
Convert 10 JavaScript files to TypeScript (#57642)
1 parent 8aa5f53 commit e1713a7

File tree

13 files changed

+203
-117
lines changed

13 files changed

+203
-117
lines changed

src/content-linter/lib/diff-files.js renamed to src/content-linter/lib/diff-files.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import fs from 'fs'
55
// is unpredictable in GitHub Actions because of how it does `git clone`.
66
// So we rely on environment variables instead.
77

8-
export function getDiffFiles() {
8+
export function getDiffFiles(): string[] {
99
// Instead of testing every single file possible, if there's
1010
// an environment variable called `DIFF_FILES` or one called
1111
// `DIFF_FILE` then use that.
1212
// If `DIFF_FILES` is set, it's expected to be a space separated
1313
// string. If `DIFF_FILE` is set, it's expected to be a text file
1414
// which contains a space separated string.
15-
const diffFiles = []
15+
const diffFiles: string[] = []
1616
// Setting an environment variable called `DIFF_FILES` is optional.
1717
// But if and only if it's set, we will respect it.
1818
// And if it set, turn it into a cleaned up Set so it's made available

src/content-linter/lib/linting-rules/code-fence-line-length.js renamed to src/content-linter/lib/linting-rules/code-fence-line-length.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1+
// @ts-ignore - markdownlint-rule-helpers doesn't provide TypeScript declarations
12
import { addError, filterTokens, newLineRe } from 'markdownlint-rule-helpers'
23

3-
export const codeFenceLineLength = {
4+
import type { RuleParams, RuleErrorCallback, MarkdownToken, Rule } from '@/content-linter/types'
5+
6+
export const codeFenceLineLength: Rule = {
47
names: ['GHD030', 'code-fence-line-length'],
58
description: 'Code fence lines should not exceed a maximum length',
69
tags: ['code', 'accessibility'],
710
parser: 'markdownit',
8-
function: (params, onError) => {
9-
const MAX_LINE_LENGTH = String(params.config.maxLength || 60)
10-
filterTokens(params, 'fence', (token) => {
11-
const lines = token.content.split(newLineRe)
12-
lines.forEach((line, index) => {
11+
function: (params: RuleParams, onError: RuleErrorCallback) => {
12+
const MAX_LINE_LENGTH: number = params.config?.maxLength || 60
13+
filterTokens(params, 'fence', (token: MarkdownToken) => {
14+
if (!token.content) return
15+
const lines: string[] = token.content.split(newLineRe)
16+
lines.forEach((line: string, index: number) => {
1317
if (line.length > MAX_LINE_LENGTH) {
1418
// The token line number is the line number of the first line of the
1519
// code fence. We want to report the line number of the content within
1620
// the code fence so we need to add 1 + the index.
17-
const lineNumber = token.lineNumber + index + 1
21+
const lineNumber: number = token.lineNumber + index + 1
1822
addError(
1923
onError,
2024
lineNumber,

src/content-render/liquid/post.js renamed to src/content-render/liquid/post.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
// used below to remove extra newlines in TOC lists
2-
const endLine = '</a>\r?\n'
3-
const blankLine = '\\s*?[\r\n]*'
4-
const startNextLine = '[^\\S\r\n]*?[-\\*] <a'
5-
const blankLineInList = new RegExp(`(${endLine})${blankLine}(${startNextLine})`, 'mg')
2+
const endLine: string = '</a>\r?\n'
3+
const blankLine: string = '\\s*?[\r\n]*'
4+
const startNextLine: string = '[^\\S\r\n]*?[-\\*] <a'
5+
const blankLineInList: RegExp = new RegExp(`(${endLine})${blankLine}(${startNextLine})`, 'mg')
66

7-
export function processLiquidPost(template) {
7+
export function processLiquidPost(template: string): string {
88
template = cleanUpListEmptyLines(template)
99
template = cleanUpExtraEmptyLines(template)
1010
return template
1111
}
1212

13-
function cleanUpListEmptyLines(template) {
13+
function cleanUpListEmptyLines(template: string): string {
1414
// clean up empty lines in TOC lists left by unrendered list items (due to productVersions)
1515
// for example, remove the blank line here:
1616
// - <a>foo</a>
@@ -22,7 +22,7 @@ function cleanUpListEmptyLines(template) {
2222
return template
2323
}
2424

25-
function cleanUpExtraEmptyLines(template) {
25+
function cleanUpExtraEmptyLines(template: string): string {
2626
// this removes any extra newlines left by (now resolved) liquid
2727
// statements so that extra space doesn't mess with list numbering
2828
template = template.replace(/(\r?\n){3}/g, '\n\n')
Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1-
// src/content-render/liquid/prompt.js
1+
// src/content-render/liquid/prompt.ts
22
// Defines {% prompt %}…{% endprompt %} to wrap its content in <code> and append the Copilot icon.
33

4+
// @ts-ignore - @primer/octicons doesn't provide TypeScript declarations
45
import octicons from '@primer/octicons'
56

6-
export const Prompt = {
7+
interface LiquidTag {
8+
type: 'block'
9+
templates?: any[] // Note: Using 'any' because liquidjs doesn't provide proper types for template objects
10+
// Note: Using 'any' for liquid-related parameters because liquidjs doesn't provide comprehensive TypeScript definitions
11+
parse(tagToken: any, remainTokens: any): void
12+
render(scope: any): Generator<any, string, unknown>
13+
}
14+
15+
export const Prompt: LiquidTag = {
716
type: 'block',
817

918
// Collect everything until {% endprompt %}
10-
parse(tagToken, remainTokens) {
19+
parse(tagToken: any, remainTokens: any): void {
1120
this.templates = []
1221
const stream = this.liquid.parser.parseStream(remainTokens)
1322
stream
14-
.on('template', (tpl) => this.templates.push(tpl))
23+
.on('template', (tpl: any) => this.templates.push(tpl))
1524
.on('tag:endprompt', () => stream.stop())
1625
.on('end', () => {
1726
throw new Error(`{% prompt %} tag not closed`)
@@ -20,12 +29,12 @@ export const Prompt = {
2029
},
2130

2231
// Render the inner Markdown, wrap in <code>, then append the SVG
23-
render: function* (scope) {
32+
render: function* (scope: any): Generator<any, string, unknown> {
2433
const content = yield this.liquid.renderer.renderTemplates(this.templates, scope)
2534

2635
// build a URL with the prompt text encoded as query parameter
27-
const promptParam = encodeURIComponent(content)
28-
const href = `https://github.com/copilot?prompt=${promptParam}`
36+
const promptParam: string = encodeURIComponent(content as string)
37+
const href: string = `https://github.com/copilot?prompt=${promptParam}`
2938
return `<code>${content}</code><a href="${href}" target="_blank" class="tooltipped tooltipped-nw ml-1" aria-label="Run this prompt in Copilot Chat" style="text-decoration:none;">${octicons.copilot.toSVG()}</a>`
3039
},
3140
}

src/content-render/tests/prompt.js renamed to src/content-render/tests/prompt.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { renderContent } from '@/content-render/index'
33

44
describe('prompt tag', () => {
55
test('wraps content in <code> and appends svg', async () => {
6-
const input = 'Here is your prompt: {% prompt %}example prompt text{% endprompt %}.'
7-
const output = await renderContent(input)
6+
const input: string = 'Here is your prompt: {% prompt %}example prompt text{% endprompt %}.'
7+
const output: string = await renderContent(input)
88
expect(output).toContain('<code>example prompt text</code><a')
99
expect(output).toContain('<svg')
1010
})

src/content-render/unified/parse-info-string.js

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Based on https://spec.commonmark.org/0.30/#info-string
2+
// Parse out info strings on fenced code blocks, example:
3+
// ```javascript lineNumbers:left copy:all annotate
4+
// becomes...
5+
// node.lang = javascript
6+
// node.meta = { lineNumbers: 'left', copy: 'all', annotate: true }
7+
// Also parse equals signs, where id=some-id becomes { id: 'some-id' }
8+
9+
import { visit } from 'unist-util-visit'
10+
11+
interface CodeNode {
12+
type: 'code'
13+
lang?: string
14+
meta?: string | Record<string, string | boolean>
15+
value: string
16+
}
17+
18+
// Note: Using 'any' for node because unist-util-visit's type constraints
19+
// don't easily allow for proper code node typing without complex generics
20+
const matcher = (node: any): node is CodeNode => node.type === 'code' && node.lang
21+
22+
export default function parseInfoString() {
23+
// Note: Using 'any' for tree because unified's AST types are complex and
24+
// this function works with different tree types depending on the processor
25+
return (tree: any) => {
26+
visit(tree, matcher, (node: CodeNode) => {
27+
node.meta = strToObj(node.meta as string)
28+
29+
// Temporary, remove {:copy} to avoid highlight parse error in translations.
30+
if (node.lang) {
31+
node.lang = node.lang.replace('{:copy}', '')
32+
}
33+
})
34+
}
35+
}
36+
37+
function strToObj(str?: string): Record<string, string | boolean> {
38+
if (!str) return {}
39+
return Object.fromEntries(
40+
str
41+
.split(/\s+/g)
42+
.map((k: string) => k.split(/[:=]/)) // split by colon or equals sign
43+
.map(([k, ...v]: string[]) => [k, v.length ? v.join(':') : true]),
44+
)
45+
}

src/content-render/unified/use-english-headings.js

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import GithubSlugger from 'github-slugger'
2+
import { encode } from 'html-entities'
3+
import { toString } from 'hast-util-to-string'
4+
import { visit } from 'unist-util-visit'
5+
6+
const slugger = new GithubSlugger()
7+
8+
// Note: Using 'any' for node because the unist/hast type system is complex and
9+
// the visit function's type constraints don't easily allow for proper element typing
10+
// without extensive type gymnastics. The runtime check ensures type safety.
11+
const matcher = (node: any) => node.type === 'element' && ['h2', 'h3', 'h4'].includes(node.tagName)
12+
13+
interface UseEnglishHeadingsOptions {
14+
englishHeadings?: Record<string, string>
15+
}
16+
17+
// replace translated IDs and links in headings with English
18+
export default function useEnglishHeadings({ englishHeadings }: UseEnglishHeadingsOptions) {
19+
if (!englishHeadings) return
20+
// Note: Using 'any' for tree because unified's AST types are complex and
21+
// this function works with different tree types depending on the processor
22+
return (tree: any) => {
23+
// Note: Using 'any' for node because visit() callback typing is restrictive
24+
// and doesn't easily allow for proper element typing without complex generics
25+
visit(tree, matcher, (node: any) => {
26+
slugger.reset()
27+
// Get the plain text content of the heading node
28+
const text: string = toString(node)
29+
// find English heading in the collection
30+
const englishHeading: string = englishHeadings[encode(text)]
31+
// get English slug
32+
const englishSlug: string = slugger.slug(englishHeading)
33+
// use English slug for heading ID and link
34+
if (englishSlug) {
35+
// only use English slug if there is one, otherwise we'll end up with
36+
// empty IDs
37+
node.properties.id = englishSlug
38+
}
39+
})
40+
}
41+
}

src/github-apps/scripts/enabled-list-schema.js renamed to src/github-apps/scripts/enabled-list-schema.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,23 @@
33
// src/github-apps/data/user-to-server-rest.json
44
// and src/github-apps/data/fine-grained-pat.json
55

6-
export default {
6+
interface SchemaProperty {
7+
description: string
8+
type: string
9+
}
10+
11+
interface EnabledListSchema {
12+
type: string
13+
required: string[]
14+
properties: {
15+
slug: SchemaProperty
16+
subcategory: SchemaProperty
17+
verb: SchemaProperty
18+
requestPath: SchemaProperty
19+
}
20+
}
21+
22+
const schema: EnabledListSchema = {
723
type: 'object',
824
required: ['slug', 'subcategory', 'verb', 'requestPath'],
925
properties: {
@@ -25,3 +41,5 @@ export default {
2541
},
2642
},
2743
}
44+
45+
export default schema

0 commit comments

Comments
 (0)