Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9e97ad0
Add upcoming conferences for React and CityJS (#8438)
arismarko Jul 30, 2026
c7d6b70
Add conditional use warning deeplink (#8567)
hoxyq Jul 31, 2026
47a4080
Add/fix RN team member links (#8558)
huntie Aug 10, 2026
383a1e9
Clarify Suspense link in useDeferredValue docs (#8591)
aurorascharff Aug 12, 2026
7a32c8a
Fix YouTube video overflow on mobile (#8609)
laxmansrt Aug 17, 2026
e730fd0
Add cache, cacheSignal, and captureOwnerStack to the APIs overview (#…
see-stack Aug 18, 2026
96ad418
Document browser-only rendering (#8582)
gnoff Aug 19, 2026
5b3692a
Clarify browser-only rendering guidance (#8612)
aurorascharff Aug 19, 2026
b374345
Fix stream demos on iOS Safari (#8613)
aurorascharff Aug 20, 2026
0d29012
Pin matching React Canary versions in Sandpack demos (#8614)
aurorascharff Aug 20, 2026
12d692d
Improve the browser-only rendering example (#8616)
aurorascharff Aug 20, 2026
7c36f7a
fix my entry on the team page, typo fixes (#8624)
Simek Aug 24, 2026
24618e2
Add a conditional browser query example (#8617)
aurorascharff Aug 31, 2026
f3d9794
Document missing react-dom server rendering and hydration options (#8…
eps1lon Sep 3, 2026
0006861
Validate inline code highlight metadata in CI (#8645)
aurorascharff Sep 8, 2026
521d4c2
Prepare site for React 19.3 release (#8649)
samselikoff Sep 9, 2026
fde7662
Document Strict Mode hydration behavior in React 19.3 (#8651)
samselikoff Sep 10, 2026
8efce78
Clarify error handling for standalone startTransition (#8648)
aurorascharff Sep 10, 2026
cdca239
merging all conflicts
react-translations-bot Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```js [[1, 1, "submitAction"]]
function UpdateName() {}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```js [[1, 3, "submitAction"]]
function submitAction() {}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```js [[1, 1, "submitAction"]]
function submitAction() {}
```

```js [[1, 1, "\\"hidden\\""]]
const mode = "hidden";
```
31 changes: 31 additions & 0 deletions eslint-local-rules/__tests__/lint-markdown-code-blocks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,37 @@ async function run() {
),
'expected malformed metadata to be replaced with canonical form'
);

const validHighlightResult = await lintFixture('valid-highlight.md');
assert.strictEqual(
validHighlightResult.messages.length,
0,
'expected a valid inline highlight to pass'
);

const missingHighlightResult = await lintFixture('missing-highlight.md');
assert.strictEqual(
missingHighlightResult.messages.length,
1,
'expected a highlight with text missing from its line to fail'
);
assert.strictEqual(
missingHighlightResult.messages[0].message,
"Could not find 'submitAction' on highlighted line 1"
);

const outOfBoundsHighlightResult = await lintFixture(
'out-of-bounds-highlight.md'
);
assert.strictEqual(
outOfBoundsHighlightResult.messages.length,
1,
'expected an out-of-bounds highlight line to fail'
);
assert.strictEqual(
outOfBoundsHighlightResult.messages[0].message,
'Code highlight line 3 is outside this code block'
);
}

run().catch(error => {
Expand Down
66 changes: 66 additions & 0 deletions eslint-local-rules/rules/inline-highlights.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

const INLINE_HIGHLIGHT_REGEX = /(\[\[.*\]\])/;

function validateInlineHighlights(meta, code) {
const match = INLINE_HIGHLIGHT_REGEX.exec(meta);
if (!match) {
return [];
}

let highlights;
try {
highlights = JSON.parse(match[1]);
} catch (error) {
return ['Code highlight metadata must be valid JSON'];
}

if (!Array.isArray(highlights)) {
return ['Code highlight metadata must be an array'];
}

const lines = code.split('\n');
const errors = [];

for (const highlight of highlights) {
if (!Array.isArray(highlight) || highlight.length < 3) {
errors.push('Each code highlight must specify a step, line, and text');
continue;
}

const [, lineNo, text, fromIndex] = highlight;
if (!Number.isInteger(lineNo) || lineNo < 1 || lineNo > lines.length) {
errors.push(`Code highlight line ${lineNo} is outside this code block`);
continue;
}
if (typeof text !== 'string') {
errors.push(`Code highlight text on line ${lineNo} must be a string`);
continue;
}

const line = lines[lineNo - 1];
let index = line.indexOf(text);
const lastIndex = line.lastIndexOf(text);
if (index !== lastIndex) {
if (fromIndex === undefined) {
errors.push(
`Found '${text}' twice on highlighted line ${lineNo}; specify fromIndex`
);
continue;
}
index = line.indexOf(text, fromIndex);
}
if (index === -1) {
errors.push(`Could not find '${text}' on highlighted line ${lineNo}`);
}
}

return errors;
}

module.exports = {validateInlineHighlights};
14 changes: 13 additions & 1 deletion eslint-local-rules/rules/lint-markdown-code-blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ const {
setCompilerExpectedLines,
} = require('./metadata');
const {normalizeDiagnostics} = require('./diagnostics');
const {validateInlineHighlights} = require('./inline-highlights');
const {parseMarkdownFile} = require('./markdown');
const {runReactCompiler} = require('./react-compiler');

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Run React Compiler on markdown code blocks',
description: 'Validate and compile markdown code blocks',
category: 'Possible Errors',
},
fixable: 'code',
Expand All @@ -43,6 +44,17 @@ module.exports = {
const {blocks} = parseMarkdownFile(sourceCode.text, filename);
// For each supported code block, run the compiler and reconcile metadata.
for (const block of blocks) {
for (const message of validateInlineHighlights(
block.meta,
block.code
)) {
context.report({
node,
loc: block.position,
message,
});
}

const compilerResult = runReactCompiler(
block.code,
`${filename}#codeblock`
Expand Down
2 changes: 2 additions & 0 deletions eslint-local-rules/rules/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const {parseFenceMetadata} = require('./metadata');
* @property {{lineIndex: number, rawText: string, metaText: string, range: [number, number]}} fence
* @property {string} filePath
* @property {string} lang
* @property {string} meta
* @property {import('./metadata').FenceMetadata} metadata
*/

Expand Down Expand Up @@ -76,6 +77,7 @@ function parseMarkdownFile(content, filePath) {

blocks.push({
lang: rawLang || normalizedLang,
meta: node.meta || metaText.trim(),
metadata,
filePath,
code: node.value || '',
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"prettier:diff": "yarn nit:source",
"lint-heading-ids": "node scripts/headingIdLinter.js",
"fix-headings": "node scripts/headingIdLinter.js --fix",
"ci-check": "npm-run-all prettier:diff --parallel lint tsc lint-heading-ids rss deadlinks",
"ci-check": "npm-run-all prettier:diff --parallel lint test:eslint-local-rules tsc lint-heading-ids rss deadlinks",
"tsc": "tsc --noEmit",
"start": "next start",
"postinstall": "yarn --cwd eslint-local-rules install && is-ci || husky install .husky",
Expand Down Expand Up @@ -94,8 +94,13 @@
"postcss-flexbugs-fixes": "4.2.1",
"postcss-preset-env": "^6.7.0",
"prettier": "^2.5.1",
<<<<<<< HEAD
"react-server-dom-webpack": "^19.2.4",
"reading-time": "^1.5.0",
=======
"react-server-dom-webpack": "^19.3.0",
"reading-time": "^1.2.0",
>>>>>>> 8efce7853d0fc59e615ed1c253799cf1798b8428
"remark": "^12.0.1",
"remark-external-links": "^7.0.0",
"remark-html": "^12.0.0",
Expand Down
File renamed without changes
Loading
Loading