chore: land failing renovate updates (#67035)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
Mrugesh Mohapatra 2026-04-21 14:02:02 +05:30 committed by GitHub
parent 32c65547ac
commit 39408b3c83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 632 additions and 460 deletions

View File

@ -147,19 +147,19 @@
"@total-typescript/ts-reset": "^0.5.0",
"@types/canvas-confetti": "^1.6.0",
"@types/gatsbyjs__reach-router": "1.3.0",
"@types/js-yaml": "4.0.5",
"@types/loadable__component": "5.13.8",
"@types/js-yaml": "4.0.9",
"@types/loadable__component": "5.13.10",
"@types/lodash-es": "^4.17.6",
"@types/prismjs": "^1.26.0",
"@types/react": "18.2.79",
"@types/react-dom": "18.2.25",
"@types/react-gtm-module": "2.0.3",
"@types/react": "18.3.28",
"@types/react-dom": "18.3.7",
"@types/react-gtm-module": "2.0.4",
"@types/react-helmet": "6.1.11",
"@types/react-redux": "7.1.33",
"@types/react-redux": "7.1.34",
"@types/react-scroll": "1.8.10",
"@types/react-spinkit": "3.0.10",
"@types/react-test-renderer": "16.9.12",
"@types/react-transition-group": "4.4.10",
"@types/react-transition-group": "4.4.12",
"@types/redux-actions": "2.6.5",
"@types/sanitize-html": "^2.8.0",
"@types/store": "^2.0.2",

View File

@ -2,8 +2,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
interface GreenNotCompletedProps
extends JSX.IntrinsicAttributes,
React.SVGProps<SVGSVGElement> {
extends JSX.IntrinsicAttributes, React.SVGProps<SVGSVGElement> {
hushScreenReaderText?: boolean;
}

View File

@ -2,8 +2,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
interface GreenPassProps
extends JSX.IntrinsicAttributes,
React.SVGProps<SVGSVGElement> {
extends JSX.IntrinsicAttributes, React.SVGProps<SVGSVGElement> {
hushScreenReaderText?: boolean;
}
function GreenPass(props: GreenPassProps): JSX.Element {

View File

@ -668,7 +668,8 @@ a.patreon-button:hover {
.dark-palette .gradient-container {
position: relative;
background: linear-gradient(
background:
linear-gradient(
-10deg,
rgb(7 40 94) 35%,
rgba(237, 202, 216, 0) 75%,
@ -679,7 +680,8 @@ a.patreon-button:hover {
.light-palette .gradient-container {
position: relative;
background: linear-gradient(
background:
linear-gradient(
-10deg,
rgb(223 243 255) 35%,
rgba(237, 202, 216, 0) 75%,
@ -693,7 +695,8 @@ a.patreon-button:hover {
}
.light-palette .gradient-foreground {
background-image: linear-gradient(
background-image:
linear-gradient(
-10deg,
rgb(0, 51, 133) 35%,
rgba(237, 202, 216, 0) 75%,
@ -705,7 +708,8 @@ a.patreon-button:hover {
}
.dark-palette .gradient-foreground {
background-image: linear-gradient(
background-image:
linear-gradient(
-10deg,
rgb(223 243 255) 35%,
rgba(237, 202, 216, 0) 75%,

View File

@ -99,27 +99,27 @@
}
.exposed-button-nav:is(
:hover,
:hover:focus,
[aria-expanded='true'],
[aria-expanded='true']:hover
),
:hover,
:hover:focus,
[aria-expanded='true'],
[aria-expanded='true']:hover
),
.lang-button-nav:is(
:hover,
:hover:focus,
[aria-expanded='true'],
[aria-expanded='false'].force-show
) {
:hover,
:hover:focus,
[aria-expanded='true'],
[aria-expanded='false'].force-show
) {
background-color: var(--gray-00);
color: var(--theme-color);
}
.lang-button-nav:is(
:hover,
:hover:focus,
[aria-expanded='true'],
[aria-expanded='false'].force-show
) {
:hover,
:hover:focus,
[aria-expanded='true'],
[aria-expanded='false'].force-show
) {
fill: var(--gray-00);
}

View File

@ -3,7 +3,8 @@
margin-bottom: 40px;
border: 1px solid #31708f;
color: #31708f;
background: linear-gradient(
background:
linear-gradient(
-10deg,
rgba(217, 237, 247, 1) 35%,
rgba(237, 202, 216, 0) 75%,

View File

@ -10,8 +10,7 @@ import { getTodayUsCentral } from './helpers';
import './widget.css';
interface DailyCodingChallengeWidgetProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
interface DailyCodingChallengeWidgetProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
forLanding: boolean;
}

View File

@ -1,8 +1,10 @@
import { GatsbyLinkProps, Link as GatsbyLink } from 'gatsby';
import React from 'react';
interface LinkProps
extends Omit<GatsbyLinkProps<Record<string, unknown>>, 'ref'> {
interface LinkProps extends Omit<
GatsbyLinkProps<Record<string, unknown>>,
'ref'
> {
children?: React.ReactNode;
external?: boolean;
sameTab?: boolean;

View File

@ -22,7 +22,7 @@ function ChallengeTranscript({
// default to collapsed
const [isOpen, setIsOpen] = useState(() =>
shouldPersistExpanded
? (store.get('fcc-transcript-expanded') as boolean | null) ?? false
? ((store.get('fcc-transcript-expanded') as boolean | null) ?? false)
: false
);

View File

@ -118,9 +118,8 @@ describe('askSocratesSaga', () => {
});
it('dispatches error when buildChallenge returns no seed', async () => {
const { buildChallenge } = await import(
'@freecodecamp/challenge-builder/build'
);
const { buildChallenge } =
await import('@freecodecamp/challenge-builder/build');
return expectSaga(askSocratesSaga)
.withReducer(reducer)
@ -140,9 +139,8 @@ describe('askSocratesSaga', () => {
});
it('dispatches complete without userInput when editableContents is empty', async () => {
const { buildChallenge } = await import(
'@freecodecamp/challenge-builder/build'
);
const { buildChallenge } =
await import('@freecodecamp/challenge-builder/build');
const { getSocratesHint } = await import('../../../utils/ajax');
return expectSaga(askSocratesSaga)
@ -170,9 +168,8 @@ describe('askSocratesSaga', () => {
});
it('dispatches complete with hint on successful API response', async () => {
const { buildChallenge } = await import(
'@freecodecamp/challenge-builder/build'
);
const { buildChallenge } =
await import('@freecodecamp/challenge-builder/build');
const { getSocratesHint } = await import('../../../utils/ajax');
return expectSaga(askSocratesSaga)
@ -200,9 +197,8 @@ describe('askSocratesSaga', () => {
});
it('dispatches error with attempts/limit on API error response', async () => {
const { buildChallenge } = await import(
'@freecodecamp/challenge-builder/build'
);
const { buildChallenge } =
await import('@freecodecamp/challenge-builder/build');
const { getSocratesHint } = await import('../../../utils/ajax');
return expectSaga(askSocratesSaga)
@ -234,9 +230,8 @@ describe('askSocratesSaga', () => {
});
it('dispatches generic error when API call throws', async () => {
const { buildChallenge } = await import(
'@freecodecamp/challenge-builder/build'
);
const { buildChallenge } =
await import('@freecodecamp/challenge-builder/build');
const { getSocratesHint } = await import('../../../utils/ajax');
return expectSaga(askSocratesSaga)

View File

@ -1,12 +1,14 @@
default: true # include all rules, with exceptions below
MD002: false # first heading should not be a top level heading
MD013: false # lines can be any length
MD022: false # headings don't need surrounding by newlines
MD024: false # no duplicate headers
MD025: false # headings are used as markers by the parser
MD031: true # fenced blocks do need surrounding by newlines
MD033: false # inline html is required
MD040: true # fenced code blocks should have a language specified
MD034: false # allow bare-URLs
MD036: false # TODO: **Example** is the main offender, should that be a heading?
whitespace: false # extra whitespace is ignored, so we don't enforce it.
default: true # include all rules, with exceptions below
MD002: false # first heading should not be a top level heading
MD013: false # lines can be any length
MD022: false # headings don't need surrounding by newlines
MD024: false # no duplicate headers
MD025: false # headings are used as markers by the parser
MD031: true # fenced blocks do need surrounding by newlines
MD033: false # inline html is required
MD040: true # fenced code blocks should have a language specified
MD034: false # allow bare-URLs
MD036: false # TODO: **Example** is the main offender, should that be a heading?
MD058: false # allow blanks around tables
MD060: false # disable table column style
whitespace: false # extra whitespace is ignored, so we don't enforce it.

View File

@ -8,7 +8,7 @@ lang: zh-CN
<!-- (Audio) Chen Na: 四十 (sì shí), 四十一 (sì shí yī), 四十二 (sì shí èr), 四十三 (sì shí sān), 四十四 (sì shí sì), 四十五 (sì shí wǔ), 四十六 (sì shí liù), 四十七 (sì shí qī), 四十八 (sì shí bā), 四十九 (sì shí jiǔ) -->
### type 24 — Numbers (4049)
## type 24 — Numbers (4049)
# --description--

View File

@ -62,9 +62,9 @@
"@freecodecamp/eslint-config": "workspace:*",
"@freecodecamp/shared": "workspace:*",
"@total-typescript/ts-reset": "0.6.1",
"@types/debug": "4.1.12",
"@types/js-yaml": "4.0.5",
"@types/polka": "0.5.7",
"@types/debug": "4.1.13",
"@types/js-yaml": "4.0.9",
"@types/polka": "0.5.8",
"@typescript/vfs-1.6.1": "npm:@typescript/vfs@1.6.4",
"@vitest/ui": "4.0.15",
"eslint": "9.39.1",
@ -84,6 +84,6 @@
"vitest": "4.0.15"
},
"dependencies": {
"@types/node": "24.10.8"
"@types/node": "24.12.2"
}
}

View File

@ -34,9 +34,8 @@ vi.mock(
const tsvfs = await import('@typescript/vfs-1.6.1');
const ts = await import('typescript-5.9.2');
// use the same TS compiler as the challenge-builder
const tsCompiler = await import(
'@freecodecamp/browser-scripts/ts-compiler'
);
const tsCompiler =
await import('@freecodecamp/browser-scripts/ts-compiler');
const compiler = new tsCompiler.Compiler(ts, tsvfs);
let previousTsconfig;
let hasConfiguredCompiler = false;
@ -170,9 +169,8 @@ async function populateTestsForLang({ lang, challenges, meta }) {
// We have to dynamically import this because otherwise it will not be mocked.
// Presumably this is because we import from_this file in the generated block
// test files and that happens before the mock is applied.
const { buildChallenge } = await import(
'@freecodecamp/challenge-builder/build'
);
const { buildChallenge } =
await import('@freecodecamp/challenge-builder/build');
const validateChallenge = challengeSchemaValidator();
describe(`Language: ${lang}`, function () {

View File

@ -82,7 +82,7 @@
"@playwright/test": "^1.47.1",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "6.9.1",
"@types/lodash": "4.14.202",
"@types/lodash": "4.17.24",
"@types/node": "^24.10.8",
"debug": "4.4.3",
"globals": "^15.14.0",
@ -92,7 +92,7 @@
"lint-staged": "^16.4.0",
"lodash": "4.17.21",
"npm-run-all2": "5.0.2",
"prettier": "3.2.5",
"prettier": "3.8.2",
"stylelint": "16.24.0",
"tsx": "4.21.0",
"turbo": "^2.8.7",

View File

@ -31,14 +31,17 @@
},
"devDependencies": {
"@freecodecamp/eslint-config": "workspace:*",
"@types/js-yaml": "4.0.5",
"@types/js-yaml": "4.0.9",
"@types/yargs": "17.0.35",
"@vitest/ui": "3.2.4",
"eslint": "9.39.1",
"markdownlint": "0.33.0",
"markdownlint": "0.40.0",
"prismjs": "1.30.0",
"typescript": "5.9.3",
"vitest": "3.2.4",
"yargs": "17.7.2"
},
"dependencies": {
"markdown-it": "^14.1.1"
}
}

View File

@ -7,7 +7,9 @@ interface LintResults {
[key: string]: unknown[];
}
const configure = (configPath: string) => {
const configure = (
configPath: string
): { lint: (files: string[]) => Promise<LintResults> } => {
const lintRules = readFileSync(configPath, 'utf8');
const lint = linter(YAML.load(lintRules));

View File

@ -4,18 +4,15 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
import { configure, processLintErrors } from './index.js';
const badYMLError = {
const badYMLError = expect.objectContaining({
errorContext: '```yml',
errorDetail: `bad indentation of a mapping entry at line 3, column 17:
testString: testString
^`,
errorRange: null,
fixInfo: null,
errorDetail: expect.stringContaining(
'bad indentation of a mapping entry at line 3, column 17'
),
lineNumber: 19,
ruleDescription: 'YAML code blocks should be valid',
ruleInformation: null,
ruleNames: ['yaml-linter']
};
});
describe('markdown linter', () => {
const good = path.join(__dirname, './fixtures/good.md');
@ -51,6 +48,6 @@ describe('markdown linter', () => {
const errors = processLintErrors(results);
expect(errors[0].file).toContain('badYML.md');
expect(errors[0].errors).toContainEqual(badYMLError);
expect(errors[0].errors).toEqual(expect.arrayContaining([badYMLError]));
});
});

View File

@ -1,6 +1,7 @@
export const names = ['closed-code-blocks'];
export const description = 'Code blocks must have closing triple backticks';
export const tags = ['code'];
export const parser = 'micromark';
function rule(params, onError) {
params.parsers.micromark.tokens
.filter(token => token.type === 'codeFenced')

View File

@ -1,18 +1,22 @@
import markdownlint from 'markdownlint';
import { lint as markdownlint } from 'markdownlint/promise';
import * as lintPrism from './markdown-prism.js';
import * as lintYAML from './markdown-yaml.js';
import * as fencedCodeBlock from './fenced-code-block.js';
const markdownItFactory = () =>
import('markdown-it').then(module => module.default({ html: true }));
export function linter(rules) {
const lint = async files => {
const options = {
files,
config: rules,
customRules: [lintYAML, lintPrism, fencedCodeBlock]
customRules: [lintYAML, lintPrism, fencedCodeBlock],
markdownItFactory
};
return await markdownlint.promises.markdownlint(options);
return await markdownlint(options);
};
return lint;
}

View File

@ -4,8 +4,9 @@ export const names = ['prism-langs'];
export const description =
'Code block languages should be supported by PrismJS';
export const tags = ['prism'];
export const parser = 'markdownit';
function rule(params, onError) {
params.tokens
params.parsers.markdownit.tokens
.filter(param => param.type === 'fence')
.forEach(codeBlock => {
// whitespace around the language is ignored by the parser, as is case:

View File

@ -3,8 +3,9 @@ import jsYaml from 'js-yaml';
export const names = ['yaml-linter'];
export const description = 'YAML code blocks should be valid';
export const tags = ['yaml'];
export const parser = 'markdownit';
function rule(params, onError) {
params.tokens
params.parsers.markdownit.tokens
.filter(param => param.type === 'fence')
.filter(param => param.info === 'yml' || param.info === 'yaml')
// TODO since the parser only looks for yml, should we reject yaml blocks?

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@
"bson": "^7.0.0",
"eslint": "^9.39.1",
"gray-matter": "4.0.3",
"prettier": "3.2.5",
"prettier": "3.8.2",
"typescript": "5.9.3",
"vitest": "^4.0.15"
}