Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v2): allow specifying meta image for blog posts #2856

Merged
merged 2 commits into from
Jun 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
75 changes: 44 additions & 31 deletions packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -92,38 +95,48 @@ function BlogPostItem(props) {
};

return (
<article className={!isBlogPostPage ? 'margin-bottom--xl' : undefined}>
{renderPostHeader()}
<section className="markdown">
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
</section>
{(tags.length > 0 || truncated) && (
<footer className="row margin-vert--lg">
{tags.length > 0 && (
<div className="col">
<strong>Tags:</strong>
{tags.map(({label, permalink: tagPermalink}) => (
<>
<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">
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
</section>
{(tags.length > 0 || truncated) && (
<footer className="row margin-vert--lg">
{tags.length > 0 && (
<div className="col">
<strong>Tags:</strong>
{tags.map(({label, permalink: tagPermalink}) => (
<Link
key={tagPermalink}
className="margin-horiz--sm"
to={tagPermalink}>
{label}
</Link>
))}
</div>
)}
{truncated && (
<div className="col text--right">
<Link
key={tagPermalink}
className="margin-horiz--sm"
to={tagPermalink}>
{label}
to={metadata.permalink}
aria-label={`Read more about ${title}`}>
<strong>Read More</strong>
</Link>
))}
</div>
)}
{truncated && (
<div className="col text--right">
<Link
to={metadata.permalink}
aria-label={`Read more about ${title}`}>
<strong>Read More</strong>
</Link>
</div>
)}
</footer>
)}
</article>
</div>
)}
</footer>
)}
</article>
</>
);
}

Expand Down
6 changes: 1 addition & 5 deletions packages/docusaurus-theme-classic/src/theme/DocItem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 1 addition & 7 deletions packages/docusaurus-theme-classic/src/theme/Layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions packages/docusaurus/src/client/exports/__tests__/useBaseUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('useBaseUrl', () => {
mockedContext.mockImplementation(() => ({
siteConfig: {
baseUrl: '/',
url: 'https://v2.docusaurus.io',
},
}));

Expand All @@ -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',
},
}));

Expand All @@ -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',
);
});
});
22 changes: 13 additions & 9 deletions packages/docusaurus/src/client/exports/useBaseUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@
*/

import useDocusaurusContext from './useDocusaurusContext';
import isInternalUrl from './isInternalUrl';

type BaseUrlOptions = {
lex111 marked this conversation as resolved.
Show resolved Hide resolved
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;
Expand All @@ -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;
}
2 changes: 2 additions & 0 deletions website/docs/blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/).

Expand All @@ -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

Expand Down
7 changes: 7 additions & 0 deletions website/docs/docusaurus-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down