diff --git a/eslint.config.ts b/eslint.config.ts index 323197067e..9e40b282ae 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -93,14 +93,13 @@ export default [ 'no-redeclare': 'off', // Allow function overloads in TypeScript 'i18n-text/no-en': 'off', // This rule causes eslint to not run at all 'filenames/match-regex': 'off', // This rule causes eslint to not run at all + camelcase: 'off', // Many gh apis use underscores, 600+ uses // Disabled rules to review 'github/no-then': 'off', // 30+ '@typescript-eslint/ban-ts-comment': 'off', // 50+ 'no-shadow': 'off', // 150+ - 'prefer-template': 'off', // 150+ 'github/array-foreach': 'off', // 250+ - camelcase: 'off', // 600+ 'no-console': 'off', // 800+ '@typescript-eslint/no-explicit-any': 'off', // 1000+ }, diff --git a/src/app/lib/language-utils.ts b/src/app/lib/language-utils.ts index 173f4e9a1f..c3c88dea62 100644 --- a/src/app/lib/language-utils.ts +++ b/src/app/lib/language-utils.ts @@ -34,7 +34,7 @@ export function hasLanguagePrefix(path: string): boolean { export function stripLanguagePrefix(path: string): string { if (hasLanguagePrefix(path)) { const pathSegments = path.split('/') - return '/' + pathSegments.slice(2).join('/') + return `/${pathSegments.slice(2).join('/')}` } return path } diff --git a/src/archives/middleware/archived-enterprise-versions.ts b/src/archives/middleware/archived-enterprise-versions.ts index 848a151f0e..74dbf9caf2 100644 --- a/src/archives/middleware/archived-enterprise-versions.ts +++ b/src/archives/middleware/archived-enterprise-versions.ts @@ -353,14 +353,14 @@ function getProxyPath(reqPath: string, requestedVersion: string) { // Releases 2.18 and higher if (versionSatisfiesRange(requestedVersion, `>${lastVersionWithoutArchivedRedirectsFile}`)) { - const newReqPath = reqPath.includes('redirects.json') ? `/${reqPath}` : reqPath + '/index.html' + const newReqPath = reqPath.includes('redirects.json') ? `/${reqPath}` : `${reqPath}/index.html` return ENTERPRISE_GH_PAGES_URL_PREFIX + requestedVersion + newReqPath } // Releases 2.13 - 2.17 // redirect.json files don't exist for these versions if (versionSatisfiesRange(requestedVersion, `>=2.13`)) { - return ENTERPRISE_GH_PAGES_URL_PREFIX + requestedVersion + reqPath + '/index.html' + return `${ENTERPRISE_GH_PAGES_URL_PREFIX + requestedVersion + reqPath}/index.html` } // Releases 2.12 and lower diff --git a/src/article-api/middleware/article.ts b/src/article-api/middleware/article.ts index eca1e0a97f..2d73067da1 100644 --- a/src/article-api/middleware/article.ts +++ b/src/article-api/middleware/article.ts @@ -167,7 +167,7 @@ function incrementArticleLookup( const source = req.get('X-Request-Source') || (req.get('Referer') - ? 'external-' + (new URL(req.get('Referer') || '').hostname || 'unknown') + ? `external-${new URL(req.get('Referer') || '').hostname || 'unknown'}` : 'external') const tags = [ diff --git a/src/article-api/scripts/generate-api-docs.ts b/src/article-api/scripts/generate-api-docs.ts index bddac9a9c1..81b9cad96a 100644 --- a/src/article-api/scripts/generate-api-docs.ts +++ b/src/article-api/scripts/generate-api-docs.ts @@ -156,10 +156,10 @@ function updateReadme(readmePath: string, markdown: string): void { // Replace API documentation section, or append to end if (readme.includes(placeholderComment)) { - const pattern = new RegExp(placeholderComment + '[\\s\\S]*', 'g') - readme = readme.replace(pattern, placeholderComment + '\n' + markdown) + const pattern = new RegExp(`${placeholderComment}[\\s\\S]*`, 'g') + readme = readme.replace(pattern, `${placeholderComment}\n${markdown}`) } else { - readme += '\n' + markdown + readme += `\n${markdown}` } writeFileSync(readmePath, readme) diff --git a/src/assets/tests/dynamic-assets.ts b/src/assets/tests/dynamic-assets.ts index b889735b00..9bfb457a6f 100644 --- a/src/assets/tests/dynamic-assets.ts +++ b/src/assets/tests/dynamic-assets.ts @@ -103,7 +103,7 @@ describe('dynamic assets', () => { }) test.each(['key', 'key=value'])('any query string (%p) triggers a redirect', async (qs) => { - const res = await get('/assets/images/_fixtures/screenshot.webp?' + qs) + const res = await get(`/assets/images/_fixtures/screenshot.webp?${qs}`) expect(res.statusCode).toBe(302) expect(res.headers.location).toBe('/assets/images/_fixtures/screenshot.webp') expect(res.headers['cache-control']).toContain('public') diff --git a/src/assets/tests/static-assets.ts b/src/assets/tests/static-assets.ts index 479b6af44f..272aa86201 100644 --- a/src/assets/tests/static-assets.ts +++ b/src/assets/tests/static-assets.ts @@ -113,7 +113,7 @@ describe('static assets', () => { // This picks the first one found. We just need it to be anything // that actually resolves. const filePath = getNextStaticAsset('css') - const asURL = '/' + filePath.replace('.next', '_next').split(path.sep).join('/') + const asURL = `/${filePath.replace('.next', '_next').split(path.sep).join('/')}` const res = await get(asURL) expect(res.statusCode).toBe(200) checkCachingHeaders(res) diff --git a/src/codeql-cli/scripts/sync.ts b/src/codeql-cli/scripts/sync.ts index 407b96e056..5f360da6bf 100755 --- a/src/codeql-cli/scripts/sync.ts +++ b/src/codeql-cli/scripts/sync.ts @@ -41,7 +41,7 @@ async function main() { const matchHeading = '## Options\n' const primaryHeadingSourceContent = sourceContent.replace( matchHeading, - matchHeading + '\n### Primary Options\n', + `${matchHeading}\n### Primary Options\n`, ) const currentFileName = path.basename(file) const { data, content } = await convertContentToDocs( diff --git a/src/codeql-cli/tests/test-circular-links.ts b/src/codeql-cli/tests/test-circular-links.ts index d8a2def89d..651d5ebc0d 100644 --- a/src/codeql-cli/tests/test-circular-links.ts +++ b/src/codeql-cli/tests/test-circular-links.ts @@ -56,7 +56,7 @@ async function testCircularLinkFix(): Promise { } console.log('\n--- Generated content preview ---') - console.log(result1.content.substring(0, 800) + '...') + console.log(`${result1.content.substring(0, 800)}...`) return !hasCircularLink && hasValidLink } catch (error) { diff --git a/src/content-linter/lib/linting-rules/code-annotation-comment-spacing.ts b/src/content-linter/lib/linting-rules/code-annotation-comment-spacing.ts index 26ac674bc6..96c69dcb2d 100644 --- a/src/content-linter/lib/linting-rules/code-annotation-comment-spacing.ts +++ b/src/content-linter/lib/linting-rules/code-annotation-comment-spacing.ts @@ -81,7 +81,7 @@ export const codeAnnotationCommentSpacing = { // No space after comment character - this is an error const lineNumber: number = token.lineNumber + index + 1 const leadingWhitespace: string = line.match(/^\s*/)![0] - const fixedLine: string = leadingWhitespace + commentChar + ' ' + restOfLine + const fixedLine: string = `${leadingWhitespace + commentChar} ${restOfLine}` addError( onError, diff --git a/src/content-linter/lib/linting-rules/image-alt-text-end-punctuation.ts b/src/content-linter/lib/linting-rules/image-alt-text-end-punctuation.ts index c78c29e350..d00b881996 100644 --- a/src/content-linter/lib/linting-rules/image-alt-text-end-punctuation.ts +++ b/src/content-linter/lib/linting-rules/image-alt-text-end-punctuation.ts @@ -26,7 +26,7 @@ export const imageAltTextEndPunctuation: Rule = { const range = getRange(token.line, imageAltText) - addFixErrorDetail(onError, token.lineNumber, imageAltText + '.', imageAltText, range, { + addFixErrorDetail(onError, token.lineNumber, `${imageAltText}.`, imageAltText, range, { lineNumber: token.lineNumber, editColumn: isStringQuoted(imageAltText) ? token.line.indexOf(']') diff --git a/src/content-linter/lib/linting-rules/link-quotation.ts b/src/content-linter/lib/linting-rules/link-quotation.ts index 9d4eb089a1..609896ec5f 100644 --- a/src/content-linter/lib/linting-rules/link-quotation.ts +++ b/src/content-linter/lib/linting-rules/link-quotation.ts @@ -26,7 +26,7 @@ export const linkQuotation: Rule = { } else if (inLinkWithPrecedingQuotes && child.type === 'text') { content.push(escapeRegExp((child.content || '').trim())) } else if (inLinkWithPrecedingQuotes && child.type === 'code_inline') { - content.push('`' + escapeRegExp((child.content || '').trim()) + '`') + content.push(`\`${escapeRegExp((child.content || '').trim())}\``) } else if (child.type === 'link_close') { const title = content.join(' ') const regex = new RegExp(`"\\[${title}\\]\\(${linkUrl}\\)({%.*%})?(!|\\.|\\?|,)?"`) @@ -44,7 +44,7 @@ export const linkQuotation: Rule = { newLine = newLine.slice(0, -1) } if (newLine.endsWith('".')) { - newLine = newLine.slice(0, -2) + '.' + newLine = `${newLine.slice(0, -2)}.` } const lineNumber = child.lineNumber addError( diff --git a/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts b/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts index 97da99f41a..8748bbca12 100644 --- a/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts +++ b/src/content-linter/lib/linting-rules/liquid-ifversion-versions.ts @@ -104,7 +104,7 @@ function setLiquidErrors(condTagItems: any[], onError: RuleErrorCallback, lines: for (let i = 0; i < condTagItems.length; i++) { const item = condTagItems[i] const tagNameNoCond = item.name === 'endif' || item.name === 'else' - const itemErrorName = tagNameNoCond ? item.name : item.name + ' ' + item.cond + const itemErrorName = tagNameNoCond ? item.name : `${item.name} ${item.cond}` if (item.action.type === 'delete') { // There is no next stack item, the endif tag is alway the @@ -438,7 +438,7 @@ function updateConditionals(condTagItems: any[]) { const newVersions = Object.entries(item.versionsObj).map(([key, value]) => { if (key === 'ghes') { if (value === '*') return key - return key + ' ' + value + return `${key} ${value}` } else return key }) item.action.cond = newVersions.join(' or ') diff --git a/src/content-linter/lib/linting-rules/liquid-syntax.ts b/src/content-linter/lib/linting-rules/liquid-syntax.ts index 1203b7e073..efab53c928 100644 --- a/src/content-linter/lib/linting-rules/liquid-syntax.ts +++ b/src/content-linter/lib/linting-rules/liquid-syntax.ts @@ -55,7 +55,7 @@ export const frontmatterLiquidSyntax = { addError( onError, lineNumber, - 'Liquid syntax error: ' + errorDescription, + `Liquid syntax error: ${errorDescription}`, value, range, null, // No fix possible @@ -92,7 +92,7 @@ export const liquidSyntax = { addError( onError, lineNumber, - 'Liquid syntax error: ' + errorDescription, + `Liquid syntax error: ${errorDescription}`, line, range, null, // No fix possible diff --git a/src/content-linter/lib/linting-rules/liquid-tag-whitespace.ts b/src/content-linter/lib/linting-rules/liquid-tag-whitespace.ts index 3b06630ac4..e0678607ac 100644 --- a/src/content-linter/lib/linting-rules/liquid-tag-whitespace.ts +++ b/src/content-linter/lib/linting-rules/liquid-tag-whitespace.ts @@ -46,14 +46,13 @@ export const liquidTagWhitespace: Rule = { const openTag = tag.slice(0, token.contentRange[0] - token.begin) const closeTag = tag.slice(-(token.end - token.contentRange[1])) - const isOpenTagOneSpace = openTag !== openTag.trim() + ' ' - const isCloseTagOneSpace = closeTag !== ' ' + closeTag.trim() + const isOpenTagOneSpace = openTag !== `${openTag.trim()} ` + const isCloseTagOneSpace = closeTag !== ` ${closeTag.trim()}` const moreThanOneSpace = /\s{2,}/ const isArgOneSpace = moreThanOneSpace.test(tag) - const fixedContent = - openTag.trim() + ' ' + token.content.replace(moreThanOneSpace, ' ') + ' ' + closeTag.trim() + const fixedContent = `${openTag.trim()} ${token.content.replace(moreThanOneSpace, ' ')} ${closeTag.trim()}` if (isOpenTagOneSpace || isCloseTagOneSpace || isArgOneSpace) { addFixErrorDetail( diff --git a/src/content-linter/lib/linting-rules/octicon-aria-labels.ts b/src/content-linter/lib/linting-rules/octicon-aria-labels.ts index a3eb531395..376c67185f 100644 --- a/src/content-linter/lib/linting-rules/octicon-aria-labels.ts +++ b/src/content-linter/lib/linting-rules/octicon-aria-labels.ts @@ -37,7 +37,7 @@ export const octiconAriaLabels: Rule = { const octiconNameMatch = token.args.match(/["']([^"']+)["']/) const octiconName = octiconNameMatch ? octiconNameMatch[1] : 'icon' const originalContent = token.content - const fixedContent = originalContent + ` aria-label="${octiconName}"` + const fixedContent = `${originalContent} aria-label="${octiconName}"` addFixErrorDetail( onError, diff --git a/src/content-linter/scripts/find-unsed-variables.ts b/src/content-linter/scripts/find-unsed-variables.ts index 2e6a5560b8..4fbd0ff085 100644 --- a/src/content-linter/scripts/find-unsed-variables.ts +++ b/src/content-linter/scripts/find-unsed-variables.ts @@ -104,11 +104,10 @@ async function main(options: Options) { function getVariables(): Map { const variables = new Map() for (const filePath of walkFiles('data/variables', '.yml')) { - const dottedPathBase = - 'variables.' + filePath.replace('data/variables/', '').replace('.yml', '').replace(/\//g, '.') + const dottedPathBase = `variables.${filePath.replace('data/variables/', '').replace('.yml', '').replace(/\//g, '.')}` const data = yaml.load(fs.readFileSync(filePath, 'utf-8')) as Record for (const key of Object.keys(data)) { - const dottedPath = dottedPathBase + '.' + key + const dottedPath = `${dottedPathBase}.${key}` variables.set(dottedPath, filePath) } } diff --git a/src/content-linter/scripts/pretty-print-results.ts b/src/content-linter/scripts/pretty-print-results.ts index 615fb812ef..d447b1170c 100644 --- a/src/content-linter/scripts/pretty-print-results.ts +++ b/src/content-linter/scripts/pretty-print-results.ts @@ -170,14 +170,14 @@ function indentWrappedString(str: string, startingIndent: number): string { if ((currentLine + word).length > effectiveWidth) { if (isFirstLine) { - indentedString += currentLine.trim() + '\n' + indentedString += `${currentLine.trim()}\n` isFirstLine = false } else { - indentedString += NEW_LINE_PADDING + currentLine.trim() + '\n' + indentedString += `${NEW_LINE_PADDING + currentLine.trim()}\n` } - currentLine = word + ' ' + currentLine = `${word} ` } else { - currentLine += word + ' ' + currentLine += `${word} ` } } if (isFirstLine) { diff --git a/src/content-linter/tests/unit/outdated-release-phase-terminology.ts b/src/content-linter/tests/unit/outdated-release-phase-terminology.ts index 166a012614..d986c769b8 100644 --- a/src/content-linter/tests/unit/outdated-release-phase-terminology.ts +++ b/src/content-linter/tests/unit/outdated-release-phase-terminology.ts @@ -145,7 +145,7 @@ describe(outdatedReleasePhaseTerminology.names.join(' - '), () => { const markdown = ['This feature is in beta.'].join('\n') const result = await runRule(outdatedReleasePhaseTerminology, { strings: { - markdown: frontmatter + '\n' + markdown, + markdown: `${frontmatter}\n${markdown}`, }, }) const errors = result.markdown diff --git a/src/content-render/liquid/octicon.ts b/src/content-render/liquid/octicon.ts index 3a9e1c72c5..88bab333cf 100644 --- a/src/content-render/liquid/octicon.ts +++ b/src/content-render/liquid/octicon.ts @@ -18,7 +18,7 @@ interface OcticonsMatch { } const OptionsSyntax = /([a-zA-Z-]+)="([\w\s-]+)"*/g -const Syntax = new RegExp('"(?[a-zA-Z-]+)"(?(?:\\s' + OptionsSyntax.source + ')*)') +const Syntax = new RegExp(`"(?[a-zA-Z-]+)"(?(?:\\s${OptionsSyntax.source})*)`) const SyntaxHelp = 'Syntax Error in tag \'octicon\' - Valid syntax: octicon "" ' /** diff --git a/src/content-render/scripts/move-content.ts b/src/content-render/scripts/move-content.ts index 018b98b57d..2a699d7c00 100755 --- a/src/content-render/scripts/move-content.ts +++ b/src/content-render/scripts/move-content.ts @@ -268,7 +268,7 @@ function makeHref(root, filePath) { } else { nameSplit.push(nameSplit.pop().replace(/\.md$/, '')) } - return '/' + nameSplit.join('/') + return `/${nameSplit.join('/')}` } function moveFolder(oldPath, newPath, files, opts) { diff --git a/src/content-render/scripts/reusables-cli/find/unused.ts b/src/content-render/scripts/reusables-cli/find/unused.ts index e3d0e893d7..82feb590ab 100644 --- a/src/content-render/scripts/reusables-cli/find/unused.ts +++ b/src/content-render/scripts/reusables-cli/find/unused.ts @@ -28,7 +28,7 @@ export function findUnused({ absolute }: { absolute: boolean }) { (name === 'data' || name === 'indented_data_reference') && args.startsWith('reusables.') ) { - const reusableName = path.join('data', ...args.split(' ')[0].split('.')) + '.md' + const reusableName = `${path.join('data', ...args.split(' ')[0].split('.'))}.md` // Special cases where we don't want them to count as reusables. It's an example in a how-to doc if ( reusableName.includes('foo/bar.md') || diff --git a/src/content-render/scripts/reusables-cli/find/used.ts b/src/content-render/scripts/reusables-cli/find/used.ts index c6815cf501..24e1851a1a 100644 --- a/src/content-render/scripts/reusables-cli/find/used.ts +++ b/src/content-render/scripts/reusables-cli/find/used.ts @@ -65,7 +65,7 @@ export function findTopUsed(numberOfMostUsedToFind: number, { absolute }: { abso console.log(`\nTop ${numberOfMostUsedToFind} most used reusables:`) let i = 0 for (const [reusable, count] of sortedCounts.slice(0, numberOfMostUsedToFind)) { - let printReusablePath = path.join('data', ...reusable.split('.')) + '.md' + let printReusablePath = `${path.join('data', ...reusable.split('.'))}.md` if (absolute) { printReusablePath = path.resolve(printReusablePath) } diff --git a/src/content-render/scripts/test-moved-content.ts b/src/content-render/scripts/test-moved-content.ts index 3916b9158d..7b5dcac101 100644 --- a/src/content-render/scripts/test-moved-content.ts +++ b/src/content-render/scripts/test-moved-content.ts @@ -31,7 +31,7 @@ async function main(nameTuple: [string, string]) { const parentIndexMd = path.join(path.dirname(after), 'index.md') const fileContent = fs.readFileSync(parentIndexMd, 'utf-8') const { data } = readFrontmatter(fileContent) - const afterShortname = '/' + after.split('/').slice(-1)[0].replace(/\.md$/, '') + const afterShortname = `/${after.split('/').slice(-1)[0].replace(/\.md$/, '')}` if (data) assert(data.children.includes(afterShortname), `Child ${afterShortname} not found`) } } else { @@ -43,7 +43,7 @@ async function main(nameTuple: [string, string]) { const parentIndexMd = path.join(path.dirname(after), 'index.md') const fileContent = fs.readFileSync(parentIndexMd, 'utf-8') const { data } = readFrontmatter(fileContent) - const afterShortname = '/' + after.split('/').slice(-1) + const afterShortname = `/${after.split('/').slice(-1)}` if (data) assert(data.children.includes(afterShortname), `Child ${afterShortname} not found`) } } @@ -57,5 +57,5 @@ function makeHref(root: string, filePath: string) { const last = nameSplit.pop() if (last) nameSplit.push(last.replace(/\.md$/, '')) } - return '/' + nameSplit.join('/') + return `/${nameSplit.join('/')}` } diff --git a/src/content-render/unified/alerts.ts b/src/content-render/unified/alerts.ts index dd9e3ecc78..5fe2436a7d 100644 --- a/src/content-render/unified/alerts.ts +++ b/src/content-render/unified/alerts.ts @@ -43,7 +43,7 @@ export default function alerts({ alertTitles = {} }: { alertTitles?: Record { // Playwright will cache this redirect, so we need to add something // to "cache bust" the URL const cb = `?cb=${Math.random()}` - await page.goto('/get-started/start-your-journey/hello-world' + cb) - await expect(page).toHaveURL('/ja/get-started/start-your-journey/hello-world' + cb) + await page.goto(`/get-started/start-your-journey/hello-world${cb}`) + await expect(page).toHaveURL(`/ja/get-started/start-your-journey/hello-world${cb}`) // If you go, with the Japanese cookie, to the English page directly, // it will offer a link to the Japanese URL in a banner. diff --git a/src/frame/components/DefaultLayout.tsx b/src/frame/components/DefaultLayout.tsx index 411ba1a7c4..a23a377995 100644 --- a/src/frame/components/DefaultLayout.tsx +++ b/src/frame/components/DefaultLayout.tsx @@ -64,7 +64,7 @@ export const DefaultLayout = (props: Props) => { const metaDescription = page.introPlainText ? page.introPlainText : t('default_description') const SOCIAL_CATEGORIES = new Set(['code-security', 'actions', 'issues', 'copilot']) - const SOCIAL_CARD_IMG_BASE_URL = `${xHost ? 'https://' + xHost : ''}/assets/cb-345/images/social-cards` + const SOCIAL_CARD_IMG_BASE_URL = `${xHost ? `https://${xHost}` : ''}/assets/cb-345/images/social-cards` function getCategoryImageUrl(category: string): string { return `${SOCIAL_CARD_IMG_BASE_URL}/${category}.png` diff --git a/src/frame/components/context/MainContext.tsx b/src/frame/components/context/MainContext.tsx index 714dadb3a2..f90691cd4d 100644 --- a/src/frame/components/context/MainContext.tsx +++ b/src/frame/components/context/MainContext.tsx @@ -266,7 +266,7 @@ export const getMainContext = async (req: any, res: any): Promise enterpriseServerVersions: req.context.enterpriseServerVersions, error: req.context.error ? req.context.error.toString() : '', featureFlags: {}, - fullUrl: req.protocol + '://' + req.hostname + req.originalUrl, // does not include port for localhost + fullUrl: `${req.protocol}://${req.hostname}${req.originalUrl}`, // does not include port for localhost isHomepageVersion: req.context.page?.documentType === 'homepage', nonEnterpriseDefaultVersion: req.context.nonEnterpriseDefaultVersion, page: pageInfo, diff --git a/src/frame/lib/get-mini-toc-items.ts b/src/frame/lib/get-mini-toc-items.ts index e2d0c8cf8f..a701e6bb9e 100644 --- a/src/frame/lib/get-mini-toc-items.ts +++ b/src/frame/lib/get-mini-toc-items.ts @@ -174,7 +174,7 @@ export async function getAutomatedPageMiniTocItems( for (let i = 0; i < depth; i++) { title += '#' } - return title + ` ${item}\n` + return `${title} ${item}\n` }) .join('') diff --git a/src/frame/lib/read-json-file.ts b/src/frame/lib/read-json-file.ts index 99824f21be..44b6758fd2 100644 --- a/src/frame/lib/read-json-file.ts +++ b/src/frame/lib/read-json-file.ts @@ -57,7 +57,7 @@ export function readCompressedJsonFileFallbackLazily(xpath: string): () => any { // err is any because fs errors can have various shapes with code property if (err.code === 'ENOENT') { try { - fs.accessSync(xpath + '.br') + fs.accessSync(`${xpath}.br`) } catch (err: any) { // err is any because fs errors can have various shapes with code property if (err.code === 'ENOENT') { diff --git a/src/frame/middleware/find-page.ts b/src/frame/middleware/find-page.ts index 00b0013da8..617b162d90 100644 --- a/src/frame/middleware/find-page.ts +++ b/src/frame/middleware/find-page.ts @@ -110,7 +110,7 @@ async function rereadByPath( // but perhaps one day we can always and only do these kinds of lookups // at runtime. const possible = path.join(contentRoot, withoutVersion) - const filePath = existsSync(possible) ? path.join(possible, 'index.md') : possible + '.md' + const filePath = existsSync(possible) ? path.join(possible, 'index.md') : `${possible}.md` const relativePath = path.relative(contentRoot, filePath) const basePath = contentRoot diff --git a/src/frame/middleware/handle-next-data-path.ts b/src/frame/middleware/handle-next-data-path.ts index 8aff87bbda..882720748c 100644 --- a/src/frame/middleware/handle-next-data-path.ts +++ b/src/frame/middleware/handle-next-data-path.ts @@ -30,7 +30,7 @@ export default function handleNextDataPath( if (parts[1] === 'free-pro-team@latest') { parts.splice(1, 1) } - req.pagePath = '/' + parts.join('/').replace(/.json+$/, '') + req.pagePath = `/${parts.join('/').replace(/.json+$/, '')}` } else { req.pagePath = req.path } diff --git a/src/frame/middleware/render-page.ts b/src/frame/middleware/render-page.ts index f647718ef7..eeb2eb0bf9 100644 --- a/src/frame/middleware/render-page.ts +++ b/src/frame/middleware/render-page.ts @@ -106,7 +106,7 @@ export default async function renderPage(req: ExtendedRequest, res: Response) { req.context.currentVersion === 'free-pro-team@latest' || !allVersions[req.context.currentVersion!] ) { - page.fullTitle += ' - ' + context.site!.data.ui.header.github_docs + page.fullTitle += ` - ${context.site!.data.ui.header.github_docs}` } else { const { versionTitle } = allVersions[req.context.currentVersion!] page.fullTitle += ' - ' @@ -116,7 +116,7 @@ export default async function renderPage(req: ExtendedRequest, res: Response) { if (!versionTitle.includes('GitHub')) { page.fullTitle += 'GitHub ' } - page.fullTitle += versionTitle + ' Docs' + page.fullTitle += `${versionTitle} Docs` } } diff --git a/src/frame/tests/pages.ts b/src/frame/tests/pages.ts index af8c4efc41..99d000e884 100644 --- a/src/frame/tests/pages.ts +++ b/src/frame/tests/pages.ts @@ -78,16 +78,14 @@ describe('pages module', () => { .map(([path]) => path) // Build a detailed message with sources for each duplicate - const message = - `Found ${duplicates.length} duplicate redirect_from path${duplicates.length === 1 ? '' : 's'}. + const message = `Found ${duplicates.length} duplicate redirect_from path${duplicates.length === 1 ? '' : 's'}. Ensure that you don't define the same path more than once in the redirect_from property in a single file and across all English files. - You may also receive this error if you have defined the same children property more than once.\n` + - duplicates + You may also receive this error if you have defined the same children property more than once.\n${duplicates .map((dup) => { const files = Array.from(redirectToFiles.get(dup) || []) return `${dup}\n Defined in:\n ${files.join('\n ')}` }) - .join('\n\n') + .join('\n\n')}` expect(duplicates.length, message).toBe(0) }) @@ -136,10 +134,12 @@ describe('pages module', () => { .flatten() .value() - const failureMessage = - JSON.stringify(frontmatterErrors, null, 2) + - '\n\n' + - chain(frontmatterErrors).map('filepath').join('\n').value() + const failureMessage = `${JSON.stringify(frontmatterErrors, null, 2)}\n\n${chain( + frontmatterErrors, + ) + .map('filepath') + .join('\n') + .value()}` expect(frontmatterErrors.length, failureMessage).toBe(0) }) diff --git a/src/frame/tests/toc-links.ts b/src/frame/tests/toc-links.ts index 3288fb2179..16dc42c754 100644 --- a/src/frame/tests/toc-links.ts +++ b/src/frame/tests/toc-links.ts @@ -47,7 +47,7 @@ describe('toc links', () => { } } - const message = 'broken link in a TOC: ' + JSON.stringify(issues, null, 2) + const message = `broken link in a TOC: ${JSON.stringify(issues, null, 2)}` expect(issues.length, message).toBe(0) }) }) diff --git a/src/ghes-releases/scripts/create-enterprise-issue.ts b/src/ghes-releases/scripts/create-enterprise-issue.ts index e7fe92ee61..73eda33257 100644 --- a/src/ghes-releases/scripts/create-enterprise-issue.ts +++ b/src/ghes-releases/scripts/create-enterprise-issue.ts @@ -359,10 +359,10 @@ async function isExistingIssue( let query = encodeURIComponent(`is:issue repo:${repo} `) if (searchQuery) { - query += '+' + searchQuery + query += `+${searchQuery}` } if (labelQuery) { - query += '+' + labelQuery + query += `+${labelQuery}` } const issues = await octokit.request(`GET /search/issues?q=${query}`) diff --git a/src/ghes-releases/scripts/deprecate/update-content.ts b/src/ghes-releases/scripts/deprecate/update-content.ts index 86cf54309f..36d0e56ef8 100644 --- a/src/ghes-releases/scripts/deprecate/update-content.ts +++ b/src/ghes-releases/scripts/deprecate/update-content.ts @@ -28,7 +28,7 @@ export function updateContentFiles() { let featureData = undefined if (data.versions.feature) { - const featureFilePath = 'data/features/' + data.versions.feature + '.yml' + const featureFilePath = `data/features/${data.versions.feature}.yml` const featureContent = fs.readFileSync(featureFilePath, 'utf8') featureData = yaml.load(featureContent) as featureDataType if (!featureData || !featureData.versions) @@ -117,8 +117,8 @@ function removeFileUpdateParent(filePath: string) { if (!data) return // Children paths are relative to the index.md file's directory const childPath = filePath.endsWith('index.md') - ? '/' + path.basename(path.dirname(filePath)) - : '/' + path.basename(filePath, '.md') + ? `/${path.basename(path.dirname(filePath))}` + : `/${path.basename(filePath, '.md')}` // Remove the childPath from the parent index.md file's children frontmatter data.children = data.children.filter((child) => child !== childPath) diff --git a/src/github-apps/scripts/sync.ts b/src/github-apps/scripts/sync.ts index 000b510e00..01a6cfa914 100755 --- a/src/github-apps/scripts/sync.ts +++ b/src/github-apps/scripts/sync.ts @@ -448,11 +448,11 @@ function getDisplayTitle( const displayTitle = isRest ? !resourceGroup - ? sentenceCase(title) + ' permissions' - : `"${sentenceCase(title)}" ` + resourceGroup + ' permissions' + ? `${sentenceCase(title)} permissions` + : `"${sentenceCase(title)}" ${resourceGroup} permissions` : !resourceGroup - ? sentenceCase(title) + ' permissions' - : sentenceCase(resourceGroup) + ` permissions for "${title}"` + ? `${sentenceCase(title)} permissions` + : `${sentenceCase(resourceGroup)} permissions for "${title}"` return { title, displayTitle } } diff --git a/src/github-apps/tests/rendering.ts b/src/github-apps/tests/rendering.ts index 2a352c666d..19ebb9ca7e 100644 --- a/src/github-apps/tests/rendering.ts +++ b/src/github-apps/tests/rendering.ts @@ -76,7 +76,7 @@ describe('REST references docs', () => { ...value.map( (item: EnabledItem) => `/en/rest/${key}${ - categoriesWithoutSubcategories.includes(key) ? '' : '/' + item.subcategory + categoriesWithoutSubcategories.includes(key) ? '' : `/${item.subcategory}` }#${item.slug}`, ), ) @@ -110,7 +110,7 @@ describe('REST references docs', () => { ...value.permissions.map( (item: PermissionItem) => `/en/rest/${item.category}${ - categoriesWithoutSubcategories.includes(item.category) ? '' : '/' + item.subcategory + categoriesWithoutSubcategories.includes(item.category) ? '' : `/${item.subcategory}` }#${item.slug}`, ), ) diff --git a/src/graphql/scripts/build-changelog.ts b/src/graphql/scripts/build-changelog.ts index 1a5b248c35..f02b510261 100644 --- a/src/graphql/scripts/build-changelog.ts +++ b/src/graphql/scripts/build-changelog.ts @@ -175,12 +175,9 @@ export async function createChangelogEntry( }), ) const cleanTitle = cleanPreviewTitle(previewTitle) - const entryTitle = - 'The [' + - cleanTitle + - '](/graphql/overview/schema-previews#' + - previewAnchor(cleanTitle) + - ') includes these changes:' + const entryTitle = `The [${cleanTitle}](/graphql/overview/schema-previews#${previewAnchor( + cleanTitle, + )}) includes these changes:` changelogEntry.previewChanges.push({ title: entryTitle, changes: renderedPreviewChanges, @@ -220,7 +217,7 @@ export function cleanPreviewTitle(title: string): string { } else if (title === 'MergeInfoPreview') { title = 'Merge info preview' } else if (!title.endsWith('preview')) { - title = title + ' preview' + title = `${title} preview` } return title } diff --git a/src/graphql/scripts/utils/schema-helpers.ts b/src/graphql/scripts/utils/schema-helpers.ts index 1d19682760..0bd516f1e2 100644 --- a/src/graphql/scripts/utils/schema-helpers.ts +++ b/src/graphql/scripts/utils/schema-helpers.ts @@ -59,7 +59,7 @@ const graphqlTypes: GraphQLTypeInfo[] = JSON.parse( const singleQuotesInsteadOfBackticks = / '(\S+?)' / function addPeriod(string: string): string { - return string.endsWith('.') ? string : string + '.' + return string.endsWith('.') ? string : `${string}.` } async function getArguments( diff --git a/src/landings/components/ProductLandingContext.tsx b/src/landings/components/ProductLandingContext.tsx index f732228e93..edd65a6daa 100644 --- a/src/landings/components/ProductLandingContext.tsx +++ b/src/landings/components/ProductLandingContext.tsx @@ -146,7 +146,7 @@ export const getProductLandingContextFromRequest = async ( key, label: key === 'popular' || key === 'videos' - ? req.context.page.featuredLinks[key + 'Heading'] || req.context.site.data.ui.toc[key] + ? req.context.page.featuredLinks[`${key}Heading`] || req.context.site.data.ui.toc[key] : req.context.site.data.ui.toc[key], viewAllHref: key === 'startHere' && !req.context.currentCategory && hasGuidesPage diff --git a/src/landings/components/SidebarProduct.tsx b/src/landings/components/SidebarProduct.tsx index 89494c3b1e..c899fff64a 100644 --- a/src/landings/components/SidebarProduct.tsx +++ b/src/landings/components/SidebarProduct.tsx @@ -135,10 +135,10 @@ function RestNavListItem({ category }: { category: ProductTreeNode }) { (entries) => { entries.forEach((entry) => { if (entry.target.id) { - const anchor = '#' + entry.target.id.split('--')[0] + const anchor = `#${entry.target.id.split('--')[0]}` if (entry.isIntersecting === true) setVisibleAnchor(anchor) } else if (asPath.includes('#')) { - setVisibleAnchor('#' + asPath.split('#')[1]) + setVisibleAnchor(`#${asPath.split('#')[1]}`) } else { setVisibleAnchor('') } diff --git a/src/languages/components/LanguagePicker.tsx b/src/languages/components/LanguagePicker.tsx index b2ed1b50b6..05c46694d8 100644 --- a/src/languages/components/LanguagePicker.tsx +++ b/src/languages/components/LanguagePicker.tsx @@ -84,7 +84,7 @@ export const LanguagePicker = ({ xs, mediumOrLower }: Props) => { className={`color-fg-default width-full ${styles.menuButton}`} aria-label={`Select language: current language is ${selectedLang.name}`} > - {t('language_picker_label') + '\n'} + {`${t('language_picker_label')}\n`} {selectedLang.name} diff --git a/src/languages/lib/correct-translation-content.ts b/src/languages/lib/correct-translation-content.ts index fda0b9af99..8916afaf93 100644 --- a/src/languages/lib/correct-translation-content.ts +++ b/src/languages/lib/correct-translation-content.ts @@ -253,7 +253,7 @@ export function correctTranslatedContentStrings( return match } - const withLinebreak = match.slice(0, -1) + '\n' + const withLinebreak = `${match.slice(0, -1)}\n` if (englishContent.includes(withLinebreak) && !englishContent.includes(match)) { return withLinebreak } @@ -332,7 +332,7 @@ export function correctTranslatedContentStrings( const keyString = '5DE3 E050 9C47 EA3C F04A 42D3 4AEE 18F8 3AFD EB23' const translatedSentences = [ // ru - 'Полный отпечаток ключа\u00A0\u2014 `' + keyString + '`.', + `Полный отпечаток ключа\u00A0\u2014 \`${keyString}\`.`, // ko `키의 전체 지문은 \`${keyString}\`입니다.`, // es diff --git a/src/languages/lib/render-with-fallback.ts b/src/languages/lib/render-with-fallback.ts index 3a76c90da5..30c3686e54 100644 --- a/src/languages/lib/render-with-fallback.ts +++ b/src/languages/lib/render-with-fallback.ts @@ -70,7 +70,7 @@ export function createTranslationFallbackComment(error: Error, property: string) // Limit message length to keep comment manageable if (cleanMessage.length > 200) { - cleanMessage = cleanMessage.substring(0, 200) + '...' + cleanMessage = `${cleanMessage.substring(0, 200)}...` } errorDetails.push(`msg="${cleanMessage.replace(/"/g, "'")}"`) @@ -141,7 +141,7 @@ export async function renderContentWithFallback( // Skip for textOnly rendering to avoid breaking plain text output if (context.currentLanguage !== 'en' && !options?.textOnly) { const errorComment = createTranslationFallbackComment(error as Error, property) - return errorComment + '\n' + fallbackContent + return `${errorComment}\n${fallbackContent}` } return fallbackContent @@ -181,7 +181,7 @@ export async function executeWithFallback( // Only for HTML content (detected by presence of HTML tags) if (typeof fallbackContent === 'string' && /<[^>]+>/.test(fallbackContent)) { const errorComment = createTranslationFallbackComment(error as Error, 'content') - return (errorComment + '\n' + fallbackContent) as T + return `${errorComment}\n${fallbackContent}` as T } return fallbackContent diff --git a/src/languages/lib/translation-utils.ts b/src/languages/lib/translation-utils.ts index 40acaa3b73..e190e94b87 100644 --- a/src/languages/lib/translation-utils.ts +++ b/src/languages/lib/translation-utils.ts @@ -19,8 +19,7 @@ export function createTranslationFunctions(uiData: UIStrings, namespaces: string if (missingNamespaces.length > 0) { console.warn( `Missing namespaces [${missingNamespaces.join(', ')}] in UI data. ` + - 'Available namespaces: ' + - Object.keys(uiData).sort().join(', '), + `Available namespaces: ${Object.keys(uiData).sort().join(', ')}`, ) // For 404 pages, we can't afford to throw errors; create defensive fallbacks diff --git a/src/languages/tests/api-search.ts b/src/languages/tests/api-search.ts index ed5adb37e1..1cd9f87c1d 100644 --- a/src/languages/tests/api-search.ts +++ b/src/languages/tests/api-search.ts @@ -14,7 +14,7 @@ describeIfElasticsearchURL('search v1 middleware in non-English', () => { // which clearly has a record with the title "Foo" sp.set('query', 'foo') sp.set('language', 'ja') - const res = await get('/api/search/v1?' + sp) + const res = await get(`/api/search/v1?${sp}`) expect(res.statusCode).toBe(200) const results = JSON.parse(res.body) diff --git a/src/links/scripts/rendered-content-link-checker.ts b/src/links/scripts/rendered-content-link-checker.ts index 3218a712d1..fbc81c0edd 100755 --- a/src/links/scripts/rendered-content-link-checker.ts +++ b/src/links/scripts/rendered-content-link-checker.ts @@ -611,7 +611,7 @@ function flawIssueDisplay(flaws: LinkFlaw[], opts: Options, mentionExternalExclu // limit is 65536 if (output.length > 60000) { - output = output.slice(0, 60000) + '\n\n---\n\nOUTPUT TRUNCATED' + output = `${output.slice(0, 60000)}\n\n---\n\nOUTPUT TRUNCATED` } return output @@ -950,7 +950,7 @@ async function checkHrefLink( // 6. 'https://example.com' (external link) const [pathFragment, hashFragment] = href.split('#') - const hash = '#' + hashFragment // the hash is the part that starts with `#` + const hash = `#${hashFragment}` // the hash is the part that starts with `#` // this conditional handles cases in which the link is to the current article (cases 1-3 above) if (checkAnchors && (!pathFragment || pathFragment === permalink.href)) { diff --git a/src/links/scripts/validate-github-github-docs-urls/generate-new-json.ts b/src/links/scripts/validate-github-github-docs-urls/generate-new-json.ts index 9c026d1ff2..20ad6e3ab5 100644 --- a/src/links/scripts/validate-github-github-docs-urls/generate-new-json.ts +++ b/src/links/scripts/validate-github-github-docs-urls/generate-new-json.ts @@ -38,7 +38,7 @@ export function generateNewJSON( const writeTo = options.output || destinationFilePath // It's important that this serializes exactly like the Ruby code // that is the CLI script `script/add-docs-url` in github/github. - const serialized = JSON.stringify(destination, null, 2) + '\n' + const serialized = `${JSON.stringify(destination, null, 2)}\n` fs.writeFileSync(writeTo, serialized, 'utf-8') console.log(`Wrote ${countChanges} change${countChanges === 1 ? '' : 's'} to ${writeTo}`) if (writeTo !== destinationFilePath) { diff --git a/src/metrics/scripts/docsaudit.ts b/src/metrics/scripts/docsaudit.ts index a49d6ccce9..75ef1d552f 100644 --- a/src/metrics/scripts/docsaudit.ts +++ b/src/metrics/scripts/docsaudit.ts @@ -77,7 +77,7 @@ async function main(): Promise { console.log(csvEntry) results.push(csvEntry) } - csvString += results.join('\n') + '\n' + csvString += `${results.join('\n')}\n` fs.writeFileSync(outputFile, csvString.trim(), 'utf8') console.log(`Done! Wrote ${outputFile}`) diff --git a/src/observability/logger/lib/to-logfmt.ts b/src/observability/logger/lib/to-logfmt.ts index fad0475869..0f59c7ee85 100644 --- a/src/observability/logger/lib/to-logfmt.ts +++ b/src/observability/logger/lib/to-logfmt.ts @@ -40,13 +40,13 @@ function stringify(data: Record): string { stringValue = stringValue.replace(/["\\]/g, '\\$&') } if (needs_quoting || needs_escaping) { - stringValue = '"' + stringValue + '"' + stringValue = `"${stringValue}"` } if (stringValue === '' && !is_null) { stringValue = '""' } - line += key + '=' + stringValue + ' ' + line += `${key}=${stringValue} ` } // trim trailing space diff --git a/src/observability/logger/middleware/get-automatic-request-logger.ts b/src/observability/logger/middleware/get-automatic-request-logger.ts index 7e9d015083..0ea1992178 100644 --- a/src/observability/logger/middleware/get-automatic-request-logger.ts +++ b/src/observability/logger/middleware/get-automatic-request-logger.ts @@ -47,7 +47,7 @@ export function getAutomaticRequestLogger() { toLogfmt({ ...loggerContext, status, - responseTime: responseTime + ' ms', + responseTime: `${responseTime} ms`, contentLength: String(contentLength), method, url, @@ -71,7 +71,7 @@ export function getAutomaticRequestLogger() { chalk.reset(method), chalk.reset(url), chalk[color](status), - chalk.reset(responseTime + ' ms'), + chalk.reset(`${responseTime} ms`), chalk.reset('-'), chalk.reset(String(contentLength)), ].join(' ') diff --git a/src/redirects/lib/get-redirect.ts b/src/redirects/lib/get-redirect.ts index 8cc5e1d043..99b1d75564 100644 --- a/src/redirects/lib/get-redirect.ts +++ b/src/redirects/lib/get-redirect.ts @@ -73,11 +73,10 @@ export default function getRedirect(uri: string, context: Context): string | und if (withoutLanguage.startsWith(nonEnterpriseDefaultVersionPrefix)) { // E.g. '/free-pro-team@latest/foo/bar' or '/free-pro-team@latest' - basicCorrection = - `/${language}` + withoutLanguage.replace(nonEnterpriseDefaultVersionPrefix, '') + basicCorrection = `/${language}${withoutLanguage.replace(nonEnterpriseDefaultVersionPrefix, '')}` } else if (withoutLanguage.replace('/', '') in allVersions && !languagePrefixRegex.test(uri)) { // E.g. just '/github-ae@latest' or '/enterprise-cloud@latest' - basicCorrection = `/${language}` + withoutLanguage + basicCorrection = `/${language}${withoutLanguage}` return basicCorrection } @@ -86,18 +85,20 @@ export default function getRedirect(uri: string, context: Context): string | und withoutLanguage.startsWith('/enterprise-server/') ) { // E.g. '/enterprise-server' or '/enterprise-server/3.0/foo' - basicCorrection = - `/${language}` + - withoutLanguage.replace('/enterprise-server', `/enterprise-server@${latestStable}`) + basicCorrection = `/${language}${withoutLanguage.replace( + '/enterprise-server', + `/enterprise-server@${latestStable}`, + )}` // If it's now just the version, without anything after, exit here if (withoutLanguage === '/enterprise-server') { return basicCorrection } } else if (withoutLanguage.startsWith('/enterprise-server@latest')) { // E.g. '/enterprise-server@latest' or '/enterprise-server@latest/3.3/foo' - basicCorrection = - `/${language}` + - withoutLanguage.replace('/enterprise-server@latest', `/enterprise-server@${latestStable}`) + basicCorrection = `/${language}${withoutLanguage.replace( + '/enterprise-server@latest', + `/enterprise-server@${latestStable}`, + )}` // If it was *just* '/enterprise-server@latest' all that's needed is // the language but with 'latest' replaced with the value of `latest` if (withoutLanguage === '/enterprise-server@latest') { @@ -115,14 +116,16 @@ export default function getRedirect(uri: string, context: Context): string | und const version = withoutLanguage.split('/')[2] if (withoutLanguage === `/enterprise/${version}`) { // E.g. `/enterprise/3.0` - basicCorrection = - `/${language}` + - withoutLanguage.replace(`/enterprise/${version}`, `/enterprise-server@${version}`) + basicCorrection = `/${language}${withoutLanguage.replace( + `/enterprise/${version}`, + `/enterprise-server@${version}`, + )}` return basicCorrection } else { - basicCorrection = - `/${language}` + - withoutLanguage.replace(`/enterprise/${version}/`, `/enterprise-server@${version}/`) + basicCorrection = `/${language}${withoutLanguage.replace( + `/enterprise/${version}/`, + `/enterprise-server@${version}/`, + )}` } } else if (withoutLanguage === '/enterprise') { // E.g. `/enterprise` exactly @@ -136,11 +139,9 @@ export default function getRedirect(uri: string, context: Context): string | und // If the URL is without a language, and no redirect is necessary, // but it has as version prefix, the language has to be there // otherwise it will never be found in `req.context.pages` - basicCorrection = - `/${language}` + - withoutLanguage - .replace(`/enterprise/`, `/enterprise-server@${latest}/`) - .replace('/user/', '/') + basicCorrection = `/${language}${withoutLanguage + .replace(`/enterprise/`, `/enterprise-server@${latest}/`) + .replace('/user/', '/')}` } else if (withoutLanguage.startsWith('/insights')) { // E.g. '/insights/foo' basicCorrection = uri.replace('/insights', `${language}/enterprise-server@${latest}/insights`) @@ -171,7 +172,7 @@ export default function getRedirect(uri: string, context: Context): string | und if (supported.includes(version) || version === 'latest') { prefix = `/${majorVersion}@${version}` - suffix = '/' + split.slice(2).join('/') + suffix = `/${split.slice(2).join('/')}` if ( suffix.includes('/user') || @@ -183,7 +184,7 @@ export default function getRedirect(uri: string, context: Context): string | und } else { // If version is not supported, we still need to set these values prefix = `/${majorVersion}@${version}` - suffix = '/' + split.slice(2).join('/') + suffix = `/${split.slice(2).join('/')}` } const newURL = prefix + suffix @@ -319,7 +320,7 @@ function tryReplacements(prefix: string, suffix: string, context: Context): stri return false } const candidateAsRedirect = prefix + suffix - const candidateAsURL = '/en' + candidateAsRedirect + const candidateAsURL = `/en${candidateAsRedirect}` return candidateAsRedirect in redirects || candidateAsURL in pages } diff --git a/src/redirects/middleware/handle-redirects.ts b/src/redirects/middleware/handle-redirects.ts index 82d88882de..23d806c53a 100644 --- a/src/redirects/middleware/handle-redirects.ts +++ b/src/redirects/middleware/handle-redirects.ts @@ -76,7 +76,7 @@ export default function handleRedirects(req: ExtendedRequest, res: Response, nex // have to do this now because searchPath replacement changes the path as well as the query params if (queryParams) { - queryParams = '?' + queryParams + queryParams = `?${queryParams}` } // remove query params temporarily so we can find the path in the redirects object diff --git a/src/rest/components/RestAuth.tsx b/src/rest/components/RestAuth.tsx index aaed841f33..f808dfec8c 100644 --- a/src/rest/components/RestAuth.tsx +++ b/src/rest/components/RestAuth.tsx @@ -106,8 +106,8 @@ function FineGrainedAccess({ progAccess }: FineGrainedProps) { numPermissionSets === 0 ? t('no_permission_sets') : numPermissionSets > 1 - ? t('permission_sets') + ':' - : t('permission_set') + ':' + ? `${t('permission_sets')}:` + : `${t('permission_set')}:` const publicAccessMsg = numPermissionSets === 0 ? t('allows_public_read_access_no_permissions') diff --git a/src/rest/components/RestRedirect.tsx b/src/rest/components/RestRedirect.tsx index cbb16ee87f..cb6829bd55 100644 --- a/src/rest/components/RestRedirect.tsx +++ b/src/rest/components/RestRedirect.tsx @@ -33,7 +33,7 @@ export function RestRedirect() { const params = new URLSearchParams(asPathQuery) params.set('apiVersion', date) - const url = `/${router.locale}${asPathRoot}?${params}${hash ? '#' + hash : ''}` + const url = `/${router.locale}${asPathRoot}?${params}${hash ? `#${hash}` : ''}` router.replace(url) } }, [router.asPath, currentVersion]) diff --git a/src/rest/docs.ts b/src/rest/docs.ts index 86cf35d0d7..756ca4ab6a 100755 --- a/src/rest/docs.ts +++ b/src/rest/docs.ts @@ -29,48 +29,46 @@ log(chalk.white.bold(' npm run dev\n')) log(chalk.green.bold.underline('REST docs script examples\n')) log(chalk.green.bold(' Examples of ways you can build the REST docs locally:\n')) log( - chalk.cyan.bold(' - REST All versions:') + - ' ' + - chalk.magenta('npm run sync-rest && npm run dev'), + `${chalk.cyan.bold(' - REST All versions:')} ${chalk.magenta( + 'npm run sync-rest && npm run dev', + )}`, ) log( - chalk.cyan.bold(' - REST Dotcom only:') + - ' ' + - chalk.magenta('npm run sync-rest -- --versions api.github.com && npm run dev'), + `${chalk.cyan.bold(' - REST Dotcom only:')} ${chalk.magenta( + 'npm run sync-rest -- --versions api.github.com && npm run dev', + )}`, ) log( - chalk.cyan.bold(' - REST Two versions:') + - ' ' + - chalk.magenta('npm run sync-rest -- --versions ghes-3.7 ghes-3.8 && npm run dev'), + `${chalk.cyan.bold(' - REST Two versions:')} ${chalk.magenta( + 'npm run sync-rest -- --versions ghes-3.7 ghes-3.8 && npm run dev', + )}`, ) log( - chalk.cyan.bold(' - REST Dotcom and next calendar date version:') + - ' ' + - chalk.magenta('npm run sync-rest -- --next --versions api.github.com && npm run dev'), + `${chalk.cyan.bold(' - REST Dotcom and next calendar date version:')} ${chalk.magenta( + 'npm run sync-rest -- --next --versions api.github.com && npm run dev', + )}`, ) log( - chalk.cyan.bold(' - REST Dotcom only, including unpublished operations:') + - ' ' + - chalk.magenta( - 'npm run sync-rest -- --versions api.github.com --include-unpublished && npm run dev', - ), + `${chalk.cyan.bold(' - REST Dotcom only, including unpublished operations:')} ${chalk.magenta( + 'npm run sync-rest -- --versions api.github.com --include-unpublished && npm run dev', + )}`, ) log(chalk.green.bold.underline('\nWebhook docs script examples\n')) log(chalk.green.bold(' Examples of ways you can build the Webhook docs locally:\n')) log( - chalk.cyan.bold(' - Webhooks All versions:') + - ' ' + - chalk.magenta('npm run sync-webhooks && npm run dev'), + `${chalk.cyan.bold(' - Webhooks All versions:')} ${chalk.magenta( + 'npm run sync-webhooks && npm run dev', + )}`, ) log( - chalk.cyan.bold(' - Webhooks Dotcom only:') + - ' ' + - chalk.magenta('npm run sync-webhooks -- --versions api.github.com && npm run dev'), + `${chalk.cyan.bold(' - Webhooks Dotcom only:')} ${chalk.magenta( + 'npm run sync-webhooks -- --versions api.github.com && npm run dev', + )}`, ) log( - chalk.cyan.bold(' - Webhooks Two versions:') + - ' ' + - chalk.magenta('npm run sync-webhooks -- --versions ghes-3.7 ghes-3.8 && npm run dev'), + `${chalk.cyan.bold(' - Webhooks Two versions:')} ${chalk.magenta( + 'npm run sync-webhooks -- --versions ghes-3.7 ghes-3.8 && npm run dev', + )}`, ) log(chalk.green.bold('\nFor more info and additional options, run:\n')) log(chalk.white.bold(' npm run sync-rest -- --help')) diff --git a/src/rest/scripts/utils/create-rest-examples.ts b/src/rest/scripts/utils/create-rest-examples.ts index f1fdf3a733..e6d71b7153 100644 --- a/src/rest/scripts/utils/create-rest-examples.ts +++ b/src/rest/scripts/utils/create-rest-examples.ts @@ -72,11 +72,7 @@ export default async function getCodeSamples(operation: Operation): Promise 1 - ? example.request.description + - ' ' + - (i + 1) + - ': Status Code ' + - example.response!.statusCode + ? `${example.request.description} ${i + 1}: Status Code ${example.response!.statusCode}` : example.request.description, }, })) diff --git a/src/rest/tests/api.ts b/src/rest/tests/api.ts index 837301d0f0..2341262d02 100644 --- a/src/rest/tests/api.ts +++ b/src/rest/tests/api.ts @@ -20,7 +20,7 @@ describe('anchor-redirect api', () => { const sp = new URLSearchParams() sp.set('path', path) sp.set('hash', hash) - const res = await get('/api/anchor-redirect?' + sp) + const res = await get(`/api/anchor-redirect?${sp}`) expect(res.statusCode).toBe(200) const { to } = JSON.parse(res.body) expect(to).toBe(value) @@ -31,7 +31,7 @@ describe('anchor-redirect api', () => { const hash = key.split('#')[1] const sp = new URLSearchParams() sp.set('hash', hash) - const res = await get('/api/anchor-redirect?' + sp) + const res = await get(`/api/anchor-redirect?${sp}`) expect(res.statusCode).toBe(400) }) test('errors when path is not passed', async () => { @@ -40,14 +40,14 @@ describe('anchor-redirect api', () => { const path = key.split('#')[0] const sp = new URLSearchParams() sp.set('path', path) - const res = await get('/api/anchor-redirect?' + sp) + const res = await get(`/api/anchor-redirect?${sp}`) expect(res.statusCode).toBe(400) }) test('unfound redirect returns undefined', async () => { const sp = new URLSearchParams() sp.set('path', 'foo') sp.set('hash', 'bar') - const res = await get('/api/anchor-redirect?' + sp) + const res = await get(`/api/anchor-redirect?${sp}`) const { to } = JSON.parse(res.body) expect(to).toBe(undefined) }) @@ -55,7 +55,7 @@ describe('anchor-redirect api', () => { const sp = new URLSearchParams() sp.set('path', 'foo') sp.set('hash', 'bar') - const res = await get('/api/anchor-redirect?' + sp) + const res = await get(`/api/anchor-redirect?${sp}`) expect(res.headers['cache-control']).toContain('public') expect(res.headers['cache-control']).toMatch(/max-age=[1-9]/) expect(res.headers['surrogate-control']).toContain('public') diff --git a/src/rest/tests/create-rest-examples.ts b/src/rest/tests/create-rest-examples.ts index 09b021fe03..239f97e6de 100644 --- a/src/rest/tests/create-rest-examples.ts +++ b/src/rest/tests/create-rest-examples.ts @@ -55,7 +55,7 @@ describe('rest example requests and responses', () => { // example is any because getCodeSamples returns objects from untyped JavaScript module mergedExamples.forEach((example: any, index: number) => { expect(example.request.description).toBe( - 'Example ' + (index + 1) + ': Status Code ' + example.response.statusCode, + `Example ${index + 1}: Status Code ${example.response.statusCode}`, ) }) }) diff --git a/src/rest/tests/rendering.ts b/src/rest/tests/rendering.ts index 56c9e85006..645401bf00 100644 --- a/src/rest/tests/rendering.ts +++ b/src/rest/tests/rendering.ts @@ -109,7 +109,7 @@ describe('REST references docs', () => { .text() .trim() if (apiVersion === allVersions[version].latestApiVersion) { - expect(versionName).toBe(apiVersion + ' (latest)') + expect(versionName).toBe(`${apiVersion} (latest)`) } else { expect(versionName).toBe(apiVersion) } @@ -148,12 +148,11 @@ describe('REST references docs', () => { function formatErrors(differences: Record): string { let errorMessage = 'There are differences in Categories/Subcategories in:\n' for (const schema in differences) { - errorMessage += 'Version: ' + schema + '\n' + errorMessage += `Version: ${schema}\n` for (const category in differences[schema]) { - errorMessage += 'Category: ' + category + '\nSubcategories: \n' - errorMessage += - ' - content/rest directory: ' + differences[schema][category].contentDir + '\n' - errorMessage += ' - OpenAPI Schema: ' + differences[schema][category].openAPI + '\n' + errorMessage += `Category: ${category}\nSubcategories: \n` + errorMessage += ` - content/rest directory: ${differences[schema][category].contentDir}\n` + errorMessage += ` - OpenAPI Schema: ${differences[schema][category].openAPI}\n` errorMessage += '---\n' } } diff --git a/src/search/components/input/SearchOverlay.tsx b/src/search/components/input/SearchOverlay.tsx index af97f3a049..bf9d40ea8e 100644 --- a/src/search/components/input/SearchOverlay.tsx +++ b/src/search/components/input/SearchOverlay.tsx @@ -299,7 +299,7 @@ export function SearchOverlay({ // When loading, capture the last height of the suggestions list so we can use it for the loading div const previousSuggestionsListHeight = useMemo(() => { if (generalSearchResults.length || aiAutocompleteOptions.length) { - return 7 * (generalSearchResults.length + aiAutocompleteOptions.length) + '' + return `${7 * (generalSearchResults.length + aiAutocompleteOptions.length)}` } else { return '150' // Default height for just 2 suggestions } diff --git a/src/search/lib/ai-search-proxy.ts b/src/search/lib/ai-search-proxy.ts index 75a4a42b4c..dd84458da3 100644 --- a/src/search/lib/ai-search-proxy.ts +++ b/src/search/lib/ai-search-proxy.ts @@ -132,8 +132,7 @@ export const aiSearchProxy = async (req: ExtendedRequest, res: Response) => { res.status(500).json({ errors: [{ message: 'Internal server error' }] }) } else { // Send error message via the stream - const errorMessage = - JSON.stringify({ errors: [{ message: 'Internal server error' }] }) + '\n' + const errorMessage = `${JSON.stringify({ errors: [{ message: 'Internal server error' }] })}\n` res.write(errorMessage) res.end() } diff --git a/src/search/lib/helpers/strings.ts b/src/search/lib/helpers/strings.ts index d8ca26383c..f7e546377e 100644 --- a/src/search/lib/helpers/strings.ts +++ b/src/search/lib/helpers/strings.ts @@ -4,7 +4,7 @@ export function safeUrlDisplay(url: string): string { parsed.password = '***' } if (parsed.username) { - parsed.username = parsed.username.slice(0, 4) + '***' + parsed.username = `${parsed.username.slice(0, 4)}***` } return parsed.toString() } diff --git a/src/search/lib/helpers/time.ts b/src/search/lib/helpers/time.ts index 36579358d4..2353d513c1 100644 --- a/src/search/lib/helpers/time.ts +++ b/src/search/lib/helpers/time.ts @@ -29,7 +29,7 @@ export function utcTimestamp() { d.getUTCSeconds(), ] // If it's a number make it a zero-padding 2 character string - .map((x) => (typeof x === 'number' ? ('0' + x).slice(-2) : x)) + .map((x) => (typeof x === 'number' ? `0${x}`.slice(-2) : x)) .join('') ) } diff --git a/src/search/scripts/scrape/lib/build-records.ts b/src/search/scripts/scrape/lib/build-records.ts index b50ca77240..7f40baac8b 100644 --- a/src/search/scripts/scrape/lib/build-records.ts +++ b/src/search/scripts/scrape/lib/build-records.ts @@ -178,36 +178,35 @@ export default async function buildRecords( // Report failed pages if any if (failedPages.length > 0) { - console.log( - '\n' + - boxen( - chalk.bold.red(`${failedPages.length} page(s) failed to scrape\n\n`) + - failedPages - .slice(0, 10) // Show first 10 failures - .map((failure, idx) => { - return ( - chalk.gray(`${idx + 1}. `) + - chalk.yellow(failure.errorType) + - '\n' + - (failure.relativePath - ? chalk.cyan(` Path: `) + failure.relativePath + '\n' - : '') + - (failure.url ? chalk.cyan(` URL: `) + failure.url + '\n' : '') + - chalk.gray(` Error: ${failure.error}`) - ) - }) - .join('\n\n') + - (failedPages.length > 10 - ? `\n\n${chalk.gray(`... and ${failedPages.length - 10} more`)}` - : ''), - { - title: chalk.red('⚠ Failed Pages'), - padding: 1, - borderColor: 'yellow', - }, - ) + - '\n', - ) + const failureCount = failedPages.length + const header = chalk.bold.red(`${failureCount} page(s) failed to scrape\n\n`) + + const failureList = failedPages + .slice(0, 10) // Show first 10 failures + .map((failure, idx) => { + const number = chalk.gray(`${idx + 1}. `) + const errorType = chalk.yellow(failure.errorType) + const pathLine = failure.relativePath + ? `\n${chalk.cyan(' Path: ')}${failure.relativePath}` + : '' + const urlLine = failure.url ? `\n${chalk.cyan(' URL: ')}${failure.url}` : '' + const errorLine = `\n${chalk.gray(` Error: ${failure.error}`)}` + + return `${number}${errorType}${pathLine}${urlLine}${errorLine}` + }) + .join('\n\n') + + const remaining = + failureCount > 10 ? `\n\n${chalk.gray(`... and ${failureCount - 10} more`)}` : '' + + const boxContent = header + failureList + remaining + const box = boxen(boxContent, { + title: chalk.red('⚠ Failed Pages'), + padding: 1, + borderColor: 'yellow', + }) + + console.log(`\n${box}\n`) // Log suggestion console.log( diff --git a/src/search/tests/api-search.ts b/src/search/tests/api-search.ts index a77abcdb91..b20227b40b 100644 --- a/src/search/tests/api-search.ts +++ b/src/search/tests/api-search.ts @@ -33,7 +33,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { // see src/search/tests/fixtures/search-indexes/github-docs-dotcom-en-records.json // which clearly has a record with the title "Foo" sp.set('query', 'foo') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) @@ -75,7 +75,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('debug', '1') // Note! - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) // safe because we know exactly the fixtures @@ -90,7 +90,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { { const sp = new URLSearchParams() sp.set('query', 'sill') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) // Fixtures contains no word called 'sill'. It does contain the term @@ -105,7 +105,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'sill') sp.set('autocomplete', 'true') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) expect(results.meta.found.value).toBeGreaterThanOrEqual(1) @@ -119,7 +119,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { test('find nothing', async () => { const sp = new URLSearchParams() sp.set('query', 'xojixjoiwejhfoiuwehjfioweufhj') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) expect(results.hits.length).toBe(0) @@ -130,7 +130,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'introduction heading') sp.append('highlights', 'content') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) expect(results.meta.found.value).toBeGreaterThanOrEqual(1) @@ -145,7 +145,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { // This will match because it's in the 'content' but not in 'headings' sp.set('query', 'Fact of life') sp.set('highlights', 'title') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) expect(results.meta.found.value).toBeGreaterThanOrEqual(1) @@ -159,12 +159,12 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('version', 'dotcom') - const res1 = await get('/api/search/v1?' + sp.toString()) + const res1 = await get(`/api/search/v1?${sp.toString()}`) expect(res1.statusCode).toBe(200) const results1: GeneralSearchResponse = JSON.parse(res1.body) sp.set('version', 'free-pro-team@latest') - const res2 = await get('/api/search/v1?' + sp.toString()) + const res2 = await get(`/api/search/v1?${sp.toString()}`) expect(res2.statusCode).toBe(200) const results2: GeneralSearchResponse = JSON.parse(res2.body) expect(results1.hits[0].id).toBe(results2.hits[0].id) @@ -185,7 +185,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { { const sp = new URLSearchParams() sp.set('query', ' ') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -198,7 +198,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'test') sp.set('language', 'xxx') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -211,7 +211,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'test') sp.set('page', '9999') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -224,7 +224,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'test') sp.set('version', 'xxxxx') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -238,7 +238,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'test') sp.set('size', 'not a number') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -251,7 +251,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'test') sp.set('sort', 'neverheardof') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -264,7 +264,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.set('query', 'test') sp.set('highlights', 'neverheardof') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -277,7 +277,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { const sp = new URLSearchParams() sp.append('query', 'test1') sp.append('query', 'test2') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const errorResponse = JSON.parse(res.body) as { error: string @@ -290,7 +290,7 @@ describeIfElasticsearchURL('search v1 middleware', () => { test('breadcrumbless records should always return a string', async () => { const sp = new URLSearchParams() sp.set('query', 'breadcrumbs') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) // safe because we know exactly the fixtures @@ -305,7 +305,7 @@ describeIfElasticsearchURL("additional fields with 'include'", () => { test("'intro' and 'headings' are omitted by default", async () => { const sp = new URLSearchParams() sp.set('query', 'foo') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) const firstKeys = Object.keys(results.hits[0]) @@ -317,7 +317,7 @@ describeIfElasticsearchURL("additional fields with 'include'", () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('include', 'intro') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) const firstKeys = Object.keys(results.hits[0]) @@ -330,7 +330,7 @@ describeIfElasticsearchURL("additional fields with 'include'", () => { sp.set('query', 'foo') sp.append('include', 'intro') sp.append('include', 'headings') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) const firstKeys = Object.keys(results.hits[0]) @@ -342,7 +342,7 @@ describeIfElasticsearchURL("additional fields with 'include'", () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('include', 'xxxxx') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const results = JSON.parse(res.body) as { error: string @@ -359,7 +359,7 @@ describeIfElasticsearchURL('filter by toplevel', () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('include', 'toplevel') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) // In the fixtures, there are two distinct `toplevel` that @@ -373,7 +373,7 @@ describeIfElasticsearchURL('filter by toplevel', () => { sp.set('query', 'foo') sp.set('include', 'toplevel') sp.set('toplevel', 'Baring') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) const toplevels = new Set(results.hits.map((hit) => hit.toplevel)) @@ -386,7 +386,7 @@ describeIfElasticsearchURL('filter by toplevel', () => { sp.set('include', 'toplevel') sp.append('toplevel', 'Baring') sp.append('toplevel', 'Fooing') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) const toplevels = new Set(results.hits.map((hit) => hit.toplevel)) @@ -398,7 +398,7 @@ describeIfElasticsearchURL('filter by toplevel', () => { sp.set('query', 'foo') sp.set('include', 'toplevel') sp.set('toplevel', 'Never heard of') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse = JSON.parse(res.body) expect(results.meta.found.value).toBe(0) @@ -412,7 +412,7 @@ describeIfElasticsearchURL('aggregate', () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('aggregate', 'toplevel') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(200) const results: GeneralSearchResponse & { aggregations?: SearchResultAggregations } = JSON.parse( res.body, @@ -428,7 +428,7 @@ describeIfElasticsearchURL('aggregate', () => { const sp = new URLSearchParams() sp.set('query', 'foo') sp.set('aggregate', 'unrecognizedxxx') - const res = await get('/api/search/v1?' + sp.toString()) + const res = await get(`/api/search/v1?${sp.toString()}`) expect(res.statusCode).toBe(400) const results = JSON.parse(res.body) as { error: string diff --git a/src/webhooks/tests/api.ts b/src/webhooks/tests/api.ts index 102738e413..a9e136f794 100644 --- a/src/webhooks/tests/api.ts +++ b/src/webhooks/tests/api.ts @@ -14,7 +14,7 @@ describe('webhooks v1 middleware', () => { // field which all webhook types should have. sp.set('category', 'branch_protection_rule') sp.set('version', 'free-pro-team@latest') - const res = await get('/api/webhooks/v1?' + sp) + const res = await get(`/api/webhooks/v1?${sp}`) expect(res.statusCode).toBe(200) const results = JSON.parse(res.body) const actionTypes = Object.keys(results) @@ -36,7 +36,7 @@ describe('webhooks v1 middleware', () => { const sp = new URLSearchParams() sp.set('category', 'branch_protection_rule') sp.set('version', 'enterprise-cloud@latest') - const res = await get('/api/webhooks/v1?' + sp) + const res = await get(`/api/webhooks/v1?${sp}`) expect(res.statusCode).toBe(200) const results = JSON.parse(res.body) const actionTypes = Object.keys(results) @@ -50,7 +50,7 @@ describe('webhooks v1 middleware', () => { const sp = new URLSearchParams() sp.set('category', 'no-such-category') sp.set('version', 'free-pro-team@latest') - const res = await get('/api/webhooks/v1?' + sp) + const res = await get(`/api/webhooks/v1?${sp}`) expect(res.statusCode).toBe(404) expect(JSON.parse(res.body).error).toBeTruthy() @@ -60,7 +60,7 @@ describe('webhooks v1 middleware', () => { const sp = new URLSearchParams() sp.set('category', 'branch_protection_rule') sp.set('version', 'no-such-version') - const res = await get('/api/webhooks/v1?' + sp) + const res = await get(`/api/webhooks/v1?${sp}`) expect(res.statusCode).toBe(404) expect(JSON.parse(res.body).error).toBeTruthy() diff --git a/src/workflows/content-changes-table-comment.ts b/src/workflows/content-changes-table-comment.ts index 26750f4658..7b49a7e9aa 100755 --- a/src/workflows/content-changes-table-comment.ts +++ b/src/workflows/content-changes-table-comment.ts @@ -167,13 +167,13 @@ async function main(owner: string, repo: string, baseSHA: string, headSHA: strin `| ${headings.map((heading) => `**${heading}**`).join(' | ')} |`, `| ${headings.map(() => ':---').join(' | ')} |`, ] - let markdownTable = markdownTableHead.join('\n') + '\n' + let markdownTable = `${markdownTableHead.join('\n')}\n` for (const filteredLine of filteredLines) { if ((markdownTable + filteredLine).length > MAX_COMMENT_SIZE) { markdownTable += '\n**Note** There are more changes in this PR than we can show.' break } - markdownTable += filteredLine + '\n' + markdownTable += `${filteredLine}\n` } return markdownTable diff --git a/src/workflows/enable-automerge.ts b/src/workflows/enable-automerge.ts index 54217e7635..740a201dda 100644 --- a/src/workflows/enable-automerge.ts +++ b/src/workflows/enable-automerge.ts @@ -37,12 +37,13 @@ async function main() { } const graph: Record = await github.graphql(mutation, variables) - console.log('GraphQL mutation result:\n' + JSON.stringify(graph)) + console.log(`GraphQL mutation result:\n${JSON.stringify(graph)}`) if (graph.errors && graph.errors.length > 0) { console.error( - 'ERROR! Failed to enable auto-merge:\n - ' + - graph.errors.map((error: any) => error.message).join('\n - '), + `ERROR! Failed to enable auto-merge:\n - ${graph.errors + .map((error: any) => error.message) + .join('\n - ')}`, ) } else { console.log('Auto-merge enabled!') diff --git a/src/workflows/experimental/readability-report.ts b/src/workflows/experimental/readability-report.ts index 0ca6d72324..c31ffe55d4 100644 --- a/src/workflows/experimental/readability-report.ts +++ b/src/workflows/experimental/readability-report.ts @@ -118,7 +118,7 @@ Note: Requires a local server running on localhost:4000 (npm start) const report = generateReport(results) // Always output to console for local development - console.log('\n' + report) + console.log(`\n${report}`) // If running in CI, also save report for commenting on PR if (process.env.GITHUB_ACTIONS) { @@ -198,12 +198,10 @@ async function waitForServer(): Promise { async function analyzeFile(filePath: string): Promise { // Convert file path to URL path // content/get-started/foo.md -> /get-started/foo - const urlPath = - '/' + - filePath - .replace(/^content\//, '') - .replace(/\.md$/, '') - .replace(/\/index$/, '') + const urlPath = `/${filePath + .replace(/^content\//, '') + .replace(/\.md$/, '') + .replace(/\/index$/, '')}` try { // Fetch the rendered page