mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 10:22:16 +00:00
chore: land failing renovate updates (#67035)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
32c65547ac
commit
39408b3c83
+7
-7
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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%,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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%,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
+1
-1
@@ -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 (40–49)
|
||||
## type 24 — Numbers (40–49)
|
||||
|
||||
# --description--
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
+2
-2
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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]));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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?
|
||||
|
||||
Generated
+530
-366
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user