mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-17 19:16:58 +02:00
feat(v2): allow specifying meta image for blog posts (#2856)
* feat(v2): allow specifying meta image for blog posts * Update docs [skip ci]
This commit is contained in:
parent
2cd326fe20
commit
c0c7457e01
9 changed files with 84 additions and 54 deletions
|
@ -9,8 +9,10 @@ import React from 'react';
|
|||
import classnames from 'classnames';
|
||||
import {MDXProvider} from '@mdx-js/react';
|
||||
|
||||
import Head from '@docusaurus/Head';
|
||||
import Link from '@docusaurus/Link';
|
||||
import MDXComponents from '@theme/MDXComponents';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
|
@ -38,12 +40,13 @@ function BlogPostItem(props) {
|
|||
isBlogPostPage = false,
|
||||
} = props;
|
||||
const {date, permalink, tags, readingTime} = metadata;
|
||||
const {author, title} = frontMatter;
|
||||
const {author, title, image} = frontMatter;
|
||||
|
||||
const authorURL = frontMatter.author_url || frontMatter.authorURL;
|
||||
const authorTitle = frontMatter.author_title || frontMatter.authorTitle;
|
||||
const authorImageURL =
|
||||
frontMatter.author_image_url || frontMatter.authorImageURL;
|
||||
const imageUrl = useBaseUrl(image, {absolute: true});
|
||||
|
||||
const renderPostHeader = () => {
|
||||
const TitleHeading = isBlogPostPage ? 'h1' : 'h2';
|
||||
|
@ -92,6 +95,15 @@ function BlogPostItem(props) {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
{image && <meta property="og:image" content={imageUrl} />}
|
||||
{image && <meta property="twitter:image" content={imageUrl} />}
|
||||
{image && (
|
||||
<meta name="twitter:image:alt" content={`Image for ${title}`} />
|
||||
)}
|
||||
</Head>
|
||||
|
||||
<article className={!isBlogPostPage ? 'margin-bottom--xl' : undefined}>
|
||||
{renderPostHeader()}
|
||||
<section className="markdown">
|
||||
|
@ -124,6 +136,7 @@ function BlogPostItem(props) {
|
|||
</footer>
|
||||
)}
|
||||
</article>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import React from 'react';
|
||||
|
||||
import Head from '@docusaurus/Head';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import DocPaginator from '@theme/DocPaginator';
|
||||
|
@ -80,10 +79,7 @@ function DocItem(props) {
|
|||
} = DocContent;
|
||||
|
||||
const metaTitle = title ? `${title} | ${siteTitle}` : siteTitle;
|
||||
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
|
||||
if (!isInternalUrl(metaImage)) {
|
||||
metaImageUrl = metaImage;
|
||||
}
|
||||
const metaImageUrl = useBaseUrl(metaImage, {absolute: true});
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -15,7 +15,7 @@ import styles from './styles.module.css';
|
|||
|
||||
function FooterLink({to, href, label, prependBaseUrlToHref, ...props}) {
|
||||
const toUrl = useBaseUrl(to);
|
||||
const normalizedHref = useBaseUrl(href, true);
|
||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import React from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
|
@ -39,13 +38,8 @@ function Layout(props) {
|
|||
version,
|
||||
} = props;
|
||||
const metaTitle = title ? `${title} | ${siteTitle}` : siteTitle;
|
||||
|
||||
const metaImage = image || defaultImage;
|
||||
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
|
||||
if (!isInternalUrl(metaImage)) {
|
||||
metaImageUrl = metaImage;
|
||||
}
|
||||
|
||||
const metaImageUrl = useBaseUrl(metaImage, {absolute: true});
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
|
||||
return (
|
||||
|
|
|
@ -32,7 +32,7 @@ function NavLink({
|
|||
}) {
|
||||
const toUrl = useBaseUrl(to);
|
||||
const activeBaseUrl = useBaseUrl(activeBasePath);
|
||||
const normalizedHref = useBaseUrl(href, true);
|
||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
|
|
@ -16,6 +16,7 @@ describe('useBaseUrl', () => {
|
|||
mockedContext.mockImplementation(() => ({
|
||||
siteConfig: {
|
||||
baseUrl: '/',
|
||||
url: 'https://v2.docusaurus.io',
|
||||
},
|
||||
}));
|
||||
|
||||
|
@ -29,12 +30,19 @@ describe('useBaseUrl', () => {
|
|||
expect(useBaseUrl('/hello/byebye/')).toEqual('/hello/byebye/');
|
||||
expect(useBaseUrl('https://github.com')).toEqual('https://github.com');
|
||||
expect(useBaseUrl('//reactjs.org')).toEqual('//reactjs.org');
|
||||
expect(useBaseUrl('https://site.com', {forcePrependBaseUrl: true})).toEqual(
|
||||
'/https://site.com',
|
||||
);
|
||||
expect(useBaseUrl('/hello/byebye', {absolute: true})).toEqual(
|
||||
'https://v2.docusaurus.io/hello/byebye',
|
||||
);
|
||||
});
|
||||
|
||||
test('non-empty base URL', () => {
|
||||
mockedContext.mockImplementation(() => ({
|
||||
siteConfig: {
|
||||
baseUrl: '/docusaurus/',
|
||||
url: 'https://v2.docusaurus.io',
|
||||
},
|
||||
}));
|
||||
|
||||
|
@ -48,5 +56,11 @@ describe('useBaseUrl', () => {
|
|||
expect(useBaseUrl('/hello/byebye/')).toEqual('/docusaurus/hello/byebye/');
|
||||
expect(useBaseUrl('https://github.com')).toEqual('https://github.com');
|
||||
expect(useBaseUrl('//reactjs.org')).toEqual('//reactjs.org');
|
||||
expect(useBaseUrl('https://site.com', {forcePrependBaseUrl: true})).toEqual(
|
||||
'/docusaurus/https://site.com',
|
||||
);
|
||||
expect(useBaseUrl('/hello/byebye', {absolute: true})).toEqual(
|
||||
'https://v2.docusaurus.io/docusaurus/hello/byebye',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,13 +6,20 @@
|
|||
*/
|
||||
|
||||
import useDocusaurusContext from './useDocusaurusContext';
|
||||
import isInternalUrl from './isInternalUrl';
|
||||
|
||||
type BaseUrlOptions = {
|
||||
forcePrependBaseUrl: boolean;
|
||||
absolute: boolean;
|
||||
};
|
||||
|
||||
export default function useBaseUrl(
|
||||
url: string,
|
||||
forcePrependBaseUrl: boolean = false,
|
||||
{forcePrependBaseUrl = false, absolute = false}: Partial<BaseUrlOptions> = {},
|
||||
): string {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const {baseUrl = '/'} = siteConfig || {};
|
||||
const {
|
||||
siteConfig: {baseUrl = '/', url: siteUrl} = {},
|
||||
} = useDocusaurusContext();
|
||||
|
||||
if (!url) {
|
||||
return url;
|
||||
|
@ -22,14 +29,11 @@ export default function useBaseUrl(
|
|||
return baseUrl + url;
|
||||
}
|
||||
|
||||
const externalRegex = /^(https?:|\/\/)/;
|
||||
if (externalRegex.test(url)) {
|
||||
if (!isInternalUrl(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (url.startsWith('/')) {
|
||||
return baseUrl + url.slice(1);
|
||||
}
|
||||
const basePath = baseUrl + url.replace(/^\//, '');
|
||||
|
||||
return baseUrl + url;
|
||||
return absolute ? siteUrl + basePath : basePath;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ author_title: Co-creator of Docusaurus 1
|
|||
author_url: https://github.com/JoelMarcey
|
||||
author_image_url: https://graph.facebook.com/611217057/picture/?height=200&width=200
|
||||
tags: [hello, docusaurus-v2]
|
||||
image: https://i.imgur.com/mErPwqL.png
|
||||
---
|
||||
Welcome to this blog. This blog is created with [**Docusaurus 2 alpha**](https://v2.docusaurus.io/).
|
||||
|
||||
|
@ -59,6 +60,7 @@ The only required field is `title`; however, we provide options to add author in
|
|||
- `title` - The blog post title.
|
||||
- `tags` - A list of strings to tag to your post.
|
||||
- `draft` - A boolean flag to indicate that the blog post is work in process and therefore should not be published yet. However, draft blog posts will be displayed during development.
|
||||
- `image`: Cover or thumbnail image that will be used when displaying the link to your post.
|
||||
|
||||
## Summary truncation
|
||||
|
||||
|
|
|
@ -153,6 +153,13 @@ const Test = () => {
|
|||
|
||||
React hook to automatically prepend `baseUrl` to a string automatically. This is particularly useful if you don't want to hardcode your config's `baseUrl`. We highly recommend you to use this.
|
||||
|
||||
```ts
|
||||
type BaseUrlOptions = {
|
||||
forcePrependBaseUrl: boolean;
|
||||
absolute: boolean;
|
||||
};
|
||||
```
|
||||
|
||||
Example usage:
|
||||
|
||||
```jsx {3,11}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue