ronantakizawa/codereview-bench huggingface dataset:
Repository: facebook/docusaurus
File: packages/docusaurus-plugin-content-blog/src/blogUtils.ts (TypeScript)

Code before:
  filePath,
  parseFrontMatter,
}: {
  filePath: string;
  parseFrontMatter: ParseFrontMatter;
}) {
  const fileContent = await fs.readFile(filePath, 'utf-8');
  try {
    const result = await parseMarkdownFile({
      filePath,
      fileContent,
      parseFrontMatter,
      removeContentTitle: true,
    });
    return {
      ...result,
      frontMatter: validateBlogPostFrontMatter(result.frontMatter),
    };
  } catch (err) {
    logger.error`Error while parsing blog post file path=${filePath}.`;
    throw err;
  }
}

const defaultReadingTime: ReadingTimeFunction = ({content, locale, options}) =>
  calculateReadingTime(content, {...options, locale});

async function processBlogSourceFile(
  blogSourceRelative: string,
  contentPaths: BlogContentPaths,
  context: LoadContext,
  options: PluginOptions,
  tagsFile: TagsFile | null,
  authorsMap?: AuthorsMap,
): Promise<BlogPost | undefined> {
  const {
    siteConfig: {
      baseUrl,
      markdown: {parseFrontMatter},
    },
    siteDir,
    i18n,
  } = context;
  const {
    routeBasePath,
    tagsBasePath: tagsRouteBasePath,
    truncateMarker,
    showReadingTime,
    editUrl,
  } = options;


Review comment (suggestion):
If you don't treat `locale` as an option elsewhere (for example, the exposed API), why not pass it separately everywhere? You should consistently spread it into options, or not.

Code after:
  filePath,
  parseFrontMatter,
}: {
  filePath: string;
  parseFrontMatter: ParseFrontMatter;
}) {
  const fileContent = await fs.readFile(filePath, 'utf-8');
  try {
    const result = await parseMarkdownFile({
      filePath,
      fileContent,
      parseFrontMatter,
      removeContentTitle: true,
    });
    return {
      ...result,
      frontMatter: validateBlogPostFrontMatter(result.frontMatter),
    };
  } catch (err) {
    logger.error`Error while parsing blog post file path=${filePath}.`;
    throw err;
  }
}

const defaultReadingTime: ReadingTimeFunction = ({content, locale, options}) =>
  calculateReadingTime(content, locale, options);

async function processBlogSourceFile(
  blogSourceRelative: string,
  contentPaths: BlogContentPaths,
  context: LoadContext,
  options: PluginOptions,
  tagsFile: TagsFile | null,
  authorsMap?: AuthorsMap,
): Promise<BlogPost | undefined> {
  const {
    siteConfig: {
      baseUrl,
      markdown: {parseFrontMatter},
    },
    siteDir,
    i18n,
  } = context;
  const {
    routeBasePath,
    tagsBasePath: tagsRouteBasePath,
    truncateMarker,
    showReadingTime,
    editUrl,
  } = options;
Repository: facebook/docusaurus
File: packages/docusaurus-plugin-content-blog/src/__tests__/readingTime.test.ts (TypeScript)

Code before:
  });

  it('handles content with multiple lines', () => {
    const content = `This is line 1.\n    This is line 2.\n    This is line 3.`;
    expect(calculateReadingTime(content, {locale: 'en'})).toBe(0.06);
  });

  it('handles content with HTML tags', () => {
    const content = '<p>This is a <strong>test</strong> content.</p>';
    expect(calculateReadingTime(content, {locale: 'en'})).toBe(0.05);
  });

  it('handles content with markdown', () => {
    const content = '# Title\n\nThis is **bold** and *italic* text.';
    expect(calculateReadingTime(content, {locale: 'en'})).toBe(0.04);
  });

  it('handles CJK content', () => {
    const content = '你好，世界！这是一段测试内容。';
    expect(calculateReadingTime(content, {locale: 'zh'})).toBe(0.04);
  });
});

describe('countWords', () => {
  it('counts words in English', () => {
    expect(countWords('This is a test.', 'en')).toBe(4);
  });
  it('counts words in CJK', () => {
    expect(countWords('你好，世界！这是一段测试内容。', 'zh')).toBe(7);
  });
});


Review comment (suggestion):
Just a suggestion: I don't think this is worth testing. Just test the reading time function. This way you don't have to "export something just to test it".

Code after:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {calculateReadingTime} from '../readingTime';

describe('calculateReadingTime', () => {
  it('calculates reading time for empty content', () => {
    expect(calculateReadingTime('', 'en')).toBe(0);
  });

  it('calculates reading time for short content', () => {
    const content = 'This is a short test content.';
    expect(calculateReadingTime(content, 'en')).toBe(0.03);
  });

  it('calculates reading time for long content', () => {
    const content = 'This is a test content. '.repeat(100);
    expect(calculateReadingTime(content, 'en')).toBe(2.5);
  });

  it('respects custom words per minute', () => {
    const content = 'This is a test content. '.repeat(100);
    expect(calculateReadingTime(content, 'en', {wordsPerMinute: 100})).toBe(5);
  });

  it('handles content with special characters', () => {
    const content = 'Hello! How are you? This is a test...';
    expect(calculateReadingTime(content, 'en')).toBe(0.04);
  });

  it('handles content with multiple lines', () => {
    const content = `This is line 1.\n    This is line 2.\n    This is line 3.`;
    expect(calculateReadingTime(content, 'en')).toBe(0.06);
  });

  it('handles content with HTML tags', () => {
    const content = '<p>This is a <strong>test</strong> content.</p>';
    expect(calculateReadingTime(content, 'en')).toBe(0.05);
  });

  it('handles content with markdown', () => {
    const content = '# Title\n\nThis is **bold** and *italic* text.';
    expect(calculateReadingTime(content, 'en')).toBe(0.04);
  });

  it('handles CJK content', () => {
    const content = '你好，世界！这是一段测试内容。';
    expect(calculateReadingTime(content, 'zh')).toBe(0.04);
  });
});
Repository: facebook/docusaurus
File: packages/docusaurus-theme-mermaid/src/client/index.ts (TypeScript)

Code before:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {useState, useEffect, useMemo} from 'react';
import {useColorMode, useThemeConfig} from '@docusaurus/theme-common';
import elkLayouts from '@mermaid-js/layout-elk';
import mermaid from 'mermaid';
import type {RenderResult, MermaidConfig} from 'mermaid';
import type {ThemeConfig} from '@docusaurus/theme-mermaid';

// mermaid does not support ELK layouts in external websites (e.g. Docusaurus) by default, as explained in https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid-layout-elk
mermaid.registerLayoutLoaders(elkLayouts);

// Stable className to allow users to easily target with CSS
export const MermaidContainerClassName = 'docusaurus-mermaid-container';

export function useMermaidThemeConfig(): ThemeConfig['mermaid'] {
  return (useThemeConfig() as unknown as ThemeConfig).mermaid;
}

export function useMermaidConfig(): MermaidConfig {
  const {colorMode} = useColorMode();
  const mermaidThemeConfig = useMermaidThemeConfig();

  const theme = mermaidThemeConfig.theme[colorMode];
  const {options} = mermaidThemeConfig;

  return useMemo(
    () => ({startOnLoad: false, ...options, theme}),
    [theme, options],
  );
}

function useMermaidId(): string {
  /*
  Random client-only id, we don't care much but mermaid want an id so...
  Note: Mermaid doesn't like values provided by Rect.useId() and throws

Review comment (suggestion):
I guess we could do something like:

```tsx
try {
  mermaid.registerLayoutLoaders(require("@mermaid-js/layout-elk"));
} catch (e) {
  // Ignore
}
```

Code after:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {useState, useEffect, useMemo} from 'react';
import {useColorMode, useThemeConfig} from '@docusaurus/theme-common';
import mermaid from 'mermaid';
import {ensureLayoutsRegistered} from './layouts';

import type {RenderResult, MermaidConfig} from 'mermaid';
import type {ThemeConfig} from '@docusaurus/theme-mermaid';

// Stable className to allow users to easily target with CSS
export const MermaidContainerClassName = 'docusaurus-mermaid-container';

export function useMermaidThemeConfig(): ThemeConfig['mermaid'] {
  return (useThemeConfig() as unknown as ThemeConfig).mermaid;
}

export function useMermaidConfig(): MermaidConfig {
  const {colorMode} = useColorMode();
  const mermaidThemeConfig = useMermaidThemeConfig();

  const theme = mermaidThemeConfig.theme[colorMode];
  const {options} = mermaidThemeConfig;

  return useMemo(
    () => ({startOnLoad: false, ...options, theme}),
    [theme, options],
  );
}

function useMermaidId(): string {
  /*
  Random client-only id, we don't care much but mermaid want an id so...
  Note: Mermaid doesn't like values provided by Rect.useId() and throws
  */
Repository: facebook/docusaurus
File: packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/index.tsx (TypeScript)

Code before:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import type {SVGProps, ReactNode, CSSProperties} from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';

// SVG Source: https://svgl.app/
function LinkedIn(props: SVGProps<SVGSVGElement>): ReactNode {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      width="1em"
      height="1em"
      preserveAspectRatio="xMidYMid"
      viewBox="0 0 256 256"
      style={{'--dark': '#ffffffe6', '--light': '#0a66c2'} as CSSProperties}
      {...props}
      className={clsx(props.className, styles.linkedinSvg)}>
      <path d="M218.123 218.127h-37.931v-59.403c0-14.165-.253-32.4-19.728-32.4-19.756 0-22.779 15.434-22.779 31.369v60.43h-37.93V95.967h36.413v16.694h.51a39.907 39.907 0 0 1 35.928-19.733c38.445 0 45.533 25.288 45.533 58.186l-.016 67.013ZM56.955 79.27c-12.157.002-22.014-9.852-22.016-22.009-.002-12.157 9.851-22.014 22.008-22.016 12.157-.003 22.014 9.851 22.016 22.008A22.013 22.013 0 0 1 56.955 79.27m18.966 138.858H37.95V95.967h37.97v122.16ZM237.033.018H18.89C8.58-.098.125 8.161-.001 18.471v219.053c.122 10.315 8.576 18.582 18.89 18.474h218.144c10.336.128 18.823-8.139 18.966-18.474V18.454c-.147-10.33-8.635-18.588-18.966-18.453" />
    </svg>
  );
}
export default LinkedIn;


Review comment (suggestion):
```suggestion
      style={{'--dark': '#0a66c2', '--light': '#ffffffe6'} as CSSProperties}
```

Code after:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import type {SVGProps, ReactNode, CSSProperties} from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';

// SVG Source: https://svgl.app/
function LinkedIn(props: SVGProps<SVGSVGElement>): ReactNode {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      width="1em"
      height="1em"
      preserveAspectRatio="xMidYMid"
      viewBox="0 0 256 256"
      style={{'--dark': '#0a66c2', '--light': '#ffffffe6'} as CSSProperties}
      {...props}
      className={clsx(props.className, styles.linkedinSvg)}>
      <path d="M218.123 218.127h-37.931v-59.403c0-14.165-.253-32.4-19.728-32.4-19.756 0-22.779 15.434-22.779 31.369v60.43h-37.93V95.967h36.413v16.694h.51a39.907 39.907 0 0 1 35.928-19.733c38.445 0 45.533 25.288 45.533 58.186l-.016 67.013ZM56.955 79.27c-12.157.002-22.014-9.852-22.016-22.009-.002-12.157 9.851-22.014 22.008-22.016 12.157-.003 22.014 9.851 22.016 22.008A22.013 22.013 0 0 1 56.955 79.27m18.966 138.858H37.95V95.967h37.97v122.16ZM237.033.018H18.89C8.58-.098.125 8.161-.001 18.471v219.053c.122 10.315 8.576 18.582 18.89 18.474h218.144c10.336.128 18.823-8.139 18.966-18.474V18.454c-.147-10.33-8.635-18.588-18.966-18.453" />
    </svg>
  );
}
export default LinkedIn;
Repository: facebook/docusaurus
File: packages/docusaurus-cssnano-preset/src/index.ts (TypeScript)

Code before:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import advancedBasePreset from 'cssnano-preset-advanced';
import postCssSortMediaQueries from 'postcss-sort-media-queries';
import postCssRemoveOverriddenCustomProperties from './remove-overridden-custom-properties';

const preset: typeof advancedBasePreset = function preset(opts) {
  const advancedPreset = advancedBasePreset({
    autoprefixer: {add: false},
    discardComments: {removeAll: true},
    /* cSpell:ignore Idents */
    reduceIdents: {counter: false},
    /* cSpell:ignore zindex */
    zindex: false,
    ...opts,
  });

  advancedPreset.plugins.unshift(
    [postCssSortMediaQueries, undefined],
    [postCssRemoveOverriddenCustomProperties, undefined],
  );

  return advancedPreset;
};

// @ts-expect-error: TODO fix later
export = preset;


Review comment (bug):
```suggestion
    // See CodeBlock custom line number bug: https://github.com/facebook/docusaurus/pull/11487
    /* cSpell:ignore Idents */
    reduceIdents: {counter: false},
```

Code after:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import advancedBasePreset from 'cssnano-preset-advanced';
import postCssSortMediaQueries from 'postcss-sort-media-queries';
import postCssRemoveOverriddenCustomProperties from './remove-overridden-custom-properties';

const preset: typeof advancedBasePreset = function preset(opts) {
  const advancedPreset = advancedBasePreset({
    autoprefixer: {add: false},
    discardComments: {removeAll: true},
    // See CodeBlock custom line number bug: https://github.com/facebook/docusaurus/pull/11487
    /* cSpell:ignore Idents */
    reduceIdents: {counter: false},
    /* cSpell:ignore zindex */
    zindex: false,
    ...opts,
  });

  advancedPreset.plugins.unshift(
    [postCssSortMediaQueries, undefined],
    [postCssRemoveOverriddenCustomProperties, undefined],
  );

  return advancedPreset;
};

// @ts-expect-error: TODO fix later
export = preset;
Repository: facebook/docusaurus
File: packages/docusaurus-theme-classic/src/theme/Admonition/Layout/index.tsx (TypeScript)

Code before:
    <div
      className={clsx(
        ThemeClassNames.common.admonition,
        ThemeClassNames.common.admonitionType(type),
        styles.admonition,
        className,
      )}
      {...optional}>
      {children}
    </div>
  );
}

function AdmonitionHeading({
  icon,
  title,
  id,
}: Pick<Props, 'icon' | 'title' | 'id'>) {
  return (
    <div className={styles.admonitionHeading}>
      <span className={styles.admonitionIcon}>{icon}</span>
      {id ? (
        <Heading as="h5" id={id} className={styles.admonitionHeadingLink}>
          {title}
        </Heading>
      ) : (
        title
      )}
    </div>
  );
}

function AdmonitionContent({children}: Pick<Props, 'children'>) {
  return children ? (
    <div className={styles.admonitionContent}>{children}</div>
  ) : null;
}

export default function AdmonitionLayout(props: Props): ReactNode {
  const {type, icon, title, children, className, id, ...optional} = props;
  const hasHeading = !!(title || icon);
  return (
    <AdmonitionContainer
      type={type}
      className={className}
      id={hasHeading ? undefined : id}
      {...optional}>
      {hasHeading ? (
        <AdmonitionHeading title={title} icon={icon} id={id} />
      ) : null}
      <AdmonitionContent>{children}</AdmonitionContent>

Review comment (suggestion):
this is not really something we want, and was the cause of accessibility issues in the past. Please leave the title as is and apply the id consistently to the container.

Users that want to create a heading can use JSX within the directive label, for example:

```mdx
::::note[<h5 id="myId">Title</h5>]
```

Code after:
      className={clsx(
        ThemeClassNames.common.admonition,
        ThemeClassNames.common.admonitionType(type),
        styles.admonition,
        className,
      )}
      id={id}>
      {children}
    </div>
  );
}

function AdmonitionHeading({icon, title}: Pick<Props, 'icon' | 'title'>) {
  return (
    <div className={styles.admonitionHeading}>
      <span className={styles.admonitionIcon}>{icon}</span>
      {title}
    </div>
  );
}

function AdmonitionContent({children}: Pick<Props, 'children'>) {
  return children ? (
    <div className={styles.admonitionContent}>{children}</div>
  ) : null;
}

export default function AdmonitionLayout(props: Props): ReactNode {
  const {type, icon, title, children, className, id} = props;
  return (
    <AdmonitionContainer type={type} className={className} id={id}>
      {title || icon ? <AdmonitionHeading title={title} icon={icon} /> : null}
      <AdmonitionContent>{children}</AdmonitionContent>
    </AdmonitionContainer>
  );
}
Repository: facebook/docusaurus
File: packages/docusaurus-utils/src/jsUtils.ts (TypeScript)

Code before:

/**
 * `Array#find` for async operations where order matters.
 * @param array The array to traverse.
 * @param predicate An async predicate to be called on every array item. Should
 * return a boolean indicating whether the currently element should be returned.
 * @returns The function immediately returns the first item on which `predicate`
 * returns `true`, or `undefined` if none matches the predicate.
 */
export async function findAsyncSequential<T>(
  array: T[],
  predicate: (t: T) => Promise<boolean>,
): Promise<T | undefined> {
  for (const t of array) {
    if (await predicate(t)) {
      return t;
    }
  }
  return undefined;
}

/**
 * Converts a string to kebab-case.
 * Mimics lodash's behavior.
 */
export function kebabCase(str: string): string {
  const match = str.match(
    /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b|[_])|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g,
  );
  return match ? match.map((x) => x.toLowerCase()).join('-') : '';
}


Review comment (suggestion):
This is not a reliable kebabCase implementation (compared to Lodash), so we clearly don't want to expose it as a js util to use everywhere else. The Lodash implementation remains better, and this good-enough implementation can stay within the create-docusaurus package.

Code after:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/**
 * `Array#map` for async operations where order matters.
 * @param array The array to traverse.
 * @param action An async action to be performed on every array item. Will be
 * awaited before working on the next.
 * @returns The list of results returned from every `action(item)`
 */
export async function mapAsyncSequential<T, R>(
  array: T[],
  action: (t: T) => Promise<R>,
): Promise<R[]> {
  const results: R[] = [];
  for (const t of array) {
    const result = await action(t);
    results.push(result);
  }
  return results;
}

/**
 * `Array#find` for async operations where order matters.
 * @param array The array to traverse.
 * @param predicate An async predicate to be called on every array item. Should
 * return a boolean indicating whether the currently element should be returned.
 * @returns The function immediately returns the first item on which `predicate`
 * returns `true`, or `undefined` if none matches the predicate.
 */
export async function findAsyncSequential<T>(
  array: T[],
  predicate: (t: T) => Promise<boolean>,
): Promise<T | undefined> {
  for (const t of array) {
    if (await predicate(t)) {
      return t;
    }
  }
  return undefined;
}
Repository: facebook/docusaurus
File: packages/docusaurus-plugin-ideal-image/src/theme/IdealImage/index.tsx (TypeScript)

Code before:
      }
      return translate({
        id: 'theme.IdealImageMessage.error',
        message: 'Error. Click to reload',
        description: 'When the image fails to load for unknown error',
      });
    }
    default:
      throw new Error(`Wrong icon: ${icon}`);
  }
}

export default function IdealImage(props: Props): ReactNode {
  const {img, ...propsRest} = props;

  // In dev env just use regular img with original file
  if (typeof img === 'string' || 'default' in img) {
    return (
      // eslint-disable-next-line jsx-a11y/alt-text
      <img src={typeof img === 'string' ? img : img.default} {...propsRest} />
    );
  }

  return (
    <ReactIdealImage
      style={propsRest.style}
      height={img.src.height ?? 100}
      width={img.src.width ?? 100}
      placeholder={{lqip: img.preSrc}}
      src={img.src.src}
      srcSet={img.src.images.map((image) => ({
        ...image,
        src: image.path,
      }))}
      getMessage={getMessage}
    />
  );
}


Review comment (refactor):
I think we should forward all remaining props, as we did before:

<img width="395" height="148" alt="CleanShot 2026-01-15 at 17 59 47" src="https://github.com/user-attachments/assets/c69a0005-f227-473c-9596-6a10f9cfe24c" />

```suggestion
      {...propsRest}
```

Not sure why I remove this line anymore, it was probably a mistake. 

From what I see, the className should also be forwarded and be applied to the ideal image div. At least it probably worked before, but doesn't work (yet) in your preview: https://deploy-preview-11659--docusaurus-2.netlify.app/tests/pages/ideal-image

(however, our component accepts any img prop but technically it doesn't seem that our legacy dependency we internalized used all the provided image props anyway)





Code after:
      }
      return translate({
        id: 'theme.IdealImageMessage.error',
        message: 'Error. Click to reload',
        description: 'When the image fails to load for unknown error',
      });
    }
    default:
      throw new Error(`Wrong icon: ${icon}`);
  }
}

export default function IdealImage(props: Props): ReactNode {
  const {img, ...propsRest} = props;

  // In dev env just use regular img with original file
  if (typeof img === 'string' || 'default' in img) {
    return (
      // eslint-disable-next-line jsx-a11y/alt-text
      <img src={typeof img === 'string' ? img : img.default} {...propsRest} />
    );
  }

  return (
    <ReactIdealImage
      {...propsRest}
      height={img.src.height ?? 100}
      width={img.src.width ?? 100}
      placeholder={{lqip: img.preSrc}}
      src={img.src.src}
      srcSet={img.src.images.map((image) => ({
        ...image,
        src: image.path,
      }))}
      getMessage={getMessage}
    />
  );
}
Repository: facebook/docusaurus
File: website/_dogfooding/_pages tests/ideal-image.tsx (TypeScript)

Code before:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import Image from '@theme/IdealImage';

import styles from './ideal-image.module.css';

function Component() {
  return (
    <Image
      className={styles.logo}
      style={{width: '100px', height: '32px'}}
      img={require('./img/oss_logo.png')}
    />
  );
}

export default Component;


Review comment (suggestion):
We don't really need that external file for dogfooding className propagation

```suggestion
function Component() {
  return (
    <Image
      className="margin--xl"
      style={{width: '100px', height: '32px'}}
      img={require('./img/oss_logo.png')}
    />
  );
}
```

Code after:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import Image from '@theme/IdealImage';

function Component() {
  return (
    <Image
      className="margin--xl"
      style={{width: '100px', height: '32px'}}
      img={require('./img/oss_logo.png')}
    />
  );
}

export default Component;