Repository: facebook/docusaurus
File: packages/docusaurus-plugin-content-blog/src/authors.ts (TypeScript)

Code before:
 */

import _ from 'lodash';
import {normalizeUrl} from '@docusaurus/utils';
import type {
  Author,
  AuthorsMap,
  BlogPost,
  BlogPostFrontMatter,
  BlogPostFrontMatterAuthor,
} from '@docusaurus/plugin-content-blog';

type AuthorsParam = {
  frontMatter: BlogPostFrontMatter;
  authorsMap: AuthorsMap | undefined;
  baseUrl: string;
};

function normalizeImageUrl({
  imageURL,
  baseUrl,
}: {
  imageURL: string | undefined;
  baseUrl: string;
}) {
  return imageURL?.startsWith('/') && !imageURL.startsWith(baseUrl)
    ? normalizeUrl([baseUrl, imageURL])
    : imageURL;
}

// Legacy v1/early-v2 front matter fields
// We may want to deprecate those in favor of using only frontMatter.authors
// TODO Docusaurus v4: remove this legacy front matter
function getFrontMatterAuthorLegacy({
  baseUrl,
  frontMatter,
}: {
  baseUrl: string;
  frontMatter: BlogPostFrontMatter;
}): Author | undefined {
  const name = frontMatter.author;
  const title = frontMatter.author_title ?? frontMatter.authorTitle;
  const url = frontMatter.author_url ?? frontMatter.authorURL;
  const imageURL = normalizeImageUrl({
    imageURL: frontMatter.author_image_url ?? frontMatter.authorImageURL,
    baseUrl,
  });

  if (name || title || url || imageURL) {
    return {
      name,

Review comment (security):
If the goal is a double application, there's probably a better solution. 

Remember that:
- The user might use baseUrl `/blog/`
- The user might put files in `/static/blog/`
- An author image hosted at `/blog/blog/authorImage.png` is perfectly valid

---


I think I'd prefer to not have this extra condition

In the past (`useBaseUrl` hook) it has been annoying because some users will use baseUrl `/docs/` or `/blog/` and duplicate paths like `/docs/docs/someImage.png`  or `/blog/blog/someImage.png` should be allowed

I'd like to have a unit test ensuring that we actually allow `/baseUrl/baseUrl/img/ozaki.jpg`


---

What we want is to not apply the baseUrl if the author is a global author (ie it has a `key`). 


My suggestion:

```ts
  function toAuthor(frontMatterAuthor: BlogPostFrontMatterAuthor): Author {
    const author = {
      // Author def from authorsMap can be locally overridden by front matter
      ...getAuthorsMapAuthor(frontMatterAuthor.key),
      ...frontMatterAuthor,
    };

    return {
      ...author,
      key: author.key ?? null,
      page: author.page ?? null,
      // global author images have already been normalized
      imageURL: author.key ? author.imageURL : normalizeImageUrl({imageURL: author.imageURL, baseUrl}),
    };
  }
```

The unit tests should clearly cover this case

Code after:
 */

import _ from 'lodash';
import {normalizeUrl} from '@docusaurus/utils';
import type {
  Author,
  AuthorsMap,
  BlogPost,
  BlogPostFrontMatter,
  BlogPostFrontMatterAuthor,
} from '@docusaurus/plugin-content-blog';

type AuthorsParam = {
  frontMatter: BlogPostFrontMatter;
  authorsMap: AuthorsMap | undefined;
  baseUrl: string;
};

export function normalizeImageUrl({
  imageURL,
  baseUrl,
}: {
  imageURL: string | undefined;
  baseUrl: string;
}): string | undefined {
  return imageURL?.startsWith('/')
    ? normalizeUrl([baseUrl, imageURL])
    : imageURL;
}

function normalizeAuthorUrl({
  author,
  baseUrl,
}: {
  author: Author;
  baseUrl: string;
}): string | undefined {
  if (author.key) {
    // Ensures invariant: global authors should have already been normalized
    if (
      author.imageURL?.startsWith('/') &&
      !author.imageURL.startsWith(baseUrl)
    ) {
      throw new Error(
        `Docusaurus internal bug: global authors image ${author.imageURL} should start with the expected baseUrl=${baseUrl}`,
      );
    }

    return author.imageURL;
  }
  return normalizeImageUrl({imageURL: author.imageURL, baseUrl});