Skip to content

Commit

Permalink
feat(blog): add onUntruncatedBlogPosts blog options (#10375)
Browse files Browse the repository at this point in the history
Co-authored-by: OzakIOne <[email protected]>
Co-authored-by: Sébastien Lorber <[email protected]>
Co-authored-by: sebastien <[email protected]>
  • Loading branch information
4 people authored Aug 9, 2024
1 parent f43be85 commit a096bbc
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
* LICENSE file in the root directory of this source tree.
*/

import {jest} from '@jest/globals';
import {fromPartial} from '@total-typescript/shoehorn';
import {
truncate,
parseBlogFileName,
paginateBlogPosts,
applyProcessBlogPosts,
reportUntruncatedBlogPosts,
} from '../blogUtils';
import type {BlogPost} from '@docusaurus/plugin-content-blog';

Expand All @@ -32,6 +34,109 @@ describe('truncate', () => {
});
});

describe('reportUntruncatedBlogPosts', () => {
function testPost({
source,
hasTruncateMarker,
}: {
source: string;
hasTruncateMarker: boolean;
}): BlogPost {
return fromPartial({
metadata: {
source,
hasTruncateMarker,
},
});
}

it('throw for untruncated blog posts', () => {
const blogPosts = [
testPost({source: '@site/blog/post1.md', hasTruncateMarker: false}),
testPost({source: '@site/blog/post2.md', hasTruncateMarker: true}),
testPost({
source: '@site/blog/subDir/post3.md',
hasTruncateMarker: false,
}),
];
expect(() =>
reportUntruncatedBlogPosts({blogPosts, onUntruncatedBlogPosts: 'throw'}),
).toThrowErrorMatchingInlineSnapshot(`
"Docusaurus found blog posts without truncation markers:
- "blog/post1.md"
- "blog/subDir/post3.md"
We recommend using truncation markers (\`<!-- truncate -->\` or \`{/* truncate */}\`) in blog posts to create shorter previews on blog paginated lists.
Tip: turn this security off with the \`onUntruncatedBlogPosts: 'ignore'\` blog plugin option."
`);
});

it('warn for untruncated blog posts', () => {
const consoleMock = jest.spyOn(console, 'warn');

const blogPosts = [
testPost({source: '@site/blog/post1.md', hasTruncateMarker: false}),
testPost({source: '@site/blog/post2.md', hasTruncateMarker: true}),
testPost({
source: '@site/blog/subDir/post3.md',
hasTruncateMarker: false,
}),
];
expect(() =>
reportUntruncatedBlogPosts({blogPosts, onUntruncatedBlogPosts: 'warn'}),
).not.toThrow();

expect(consoleMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Docusaurus found blog posts without truncation markers:
- "blog/post1.md"
- "blog/subDir/post3.md"
We recommend using truncation markers (\`<!-- truncate -->\` or \`{/* truncate */}\`) in blog posts to create shorter previews on blog paginated lists.
Tip: turn this security off with the \`onUntruncatedBlogPosts: 'ignore'\` blog plugin option.",
],
]
`);
consoleMock.mockRestore();
});

it('ignore untruncated blog posts', () => {
const logMock = jest.spyOn(console, 'log');
const warnMock = jest.spyOn(console, 'warn');
const errorMock = jest.spyOn(console, 'error');

const blogPosts = [
testPost({source: '@site/blog/post1.md', hasTruncateMarker: false}),
testPost({source: '@site/blog/post2.md', hasTruncateMarker: true}),
testPost({
source: '@site/blog/subDir/post3.md',
hasTruncateMarker: false,
}),
];
expect(() =>
reportUntruncatedBlogPosts({blogPosts, onUntruncatedBlogPosts: 'ignore'}),
).not.toThrow();

expect(logMock).not.toHaveBeenCalled();
expect(warnMock).not.toHaveBeenCalled();
expect(errorMock).not.toHaveBeenCalled();
logMock.mockRestore();
warnMock.mockRestore();
errorMock.mockRestore();
});

it('does not throw for truncated posts', () => {
const blogPosts = [
testPost({source: '@site/blog/post1.md', hasTruncateMarker: true}),
testPost({source: '@site/blog/post2.md', hasTruncateMarker: true}),
];
expect(() =>
reportUntruncatedBlogPosts({blogPosts, onUntruncatedBlogPosts: 'throw'}),
).not.toThrow();
});
});

describe('paginateBlogPosts', () => {
const blogPosts = [
{id: 'post1', metadata: {}, content: 'Foo 1'},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,4 +374,46 @@ describe('validateOptions', () => {
);
});
});

describe('onUntruncatedBlogPosts', () => {
it('accepts onUntruncatedBlogPosts - undefined', () => {
expect(
testValidate({onUntruncatedBlogPosts: undefined})
.onUntruncatedBlogPosts,
).toBe('warn');
});

it('accepts onUntruncatedBlogPosts - "throw"', () => {
expect(
testValidate({onUntruncatedBlogPosts: 'throw'}).onUntruncatedBlogPosts,
).toBe('throw');
});

it('rejects onUntruncatedBlogPosts - "trace"', () => {
expect(() =>
// @ts-expect-error: test
testValidate({onUntruncatedBlogPosts: 'trace'}),
).toThrowErrorMatchingInlineSnapshot(
`""onUntruncatedBlogPosts" must be one of [ignore, log, warn, throw]"`,
);
});

it('rejects onUntruncatedBlogPosts - null', () => {
expect(() =>
// @ts-expect-error: test
testValidate({onUntruncatedBlogPosts: 42}),
).toThrowErrorMatchingInlineSnapshot(
`""onUntruncatedBlogPosts" must be one of [ignore, log, warn, throw]"`,
);
});

it('rejects onUntruncatedBlogPosts - 42', () => {
expect(() =>
// @ts-expect-error: test
testValidate({onUntruncatedBlogPosts: 42}),
).toThrowErrorMatchingInlineSnapshot(
`""onUntruncatedBlogPosts" must be one of [ignore, log, warn, throw]"`,
);
});
});
});
23 changes: 23 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/blogUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
isDraft,
readLastUpdateData,
normalizeTags,
aliasedSitePathToRelativePath,
} from '@docusaurus/utils';
import {getTagsFile} from '@docusaurus/utils-validation';
import {validateBlogPostFrontMatter} from './frontMatter';
Expand All @@ -47,6 +48,28 @@ export function truncate(fileString: string, truncateMarker: RegExp): string {
return fileString.split(truncateMarker, 1).shift()!;
}

export function reportUntruncatedBlogPosts({
blogPosts,
onUntruncatedBlogPosts,
}: {
blogPosts: BlogPost[];
onUntruncatedBlogPosts: PluginOptions['onUntruncatedBlogPosts'];
}): void {
const untruncatedBlogPosts = blogPosts.filter(
(p) => !p.metadata.hasTruncateMarker,
);
if (onUntruncatedBlogPosts !== 'ignore' && untruncatedBlogPosts.length > 0) {
const message = logger.interpolate`Docusaurus found blog posts without truncation markers:
- ${untruncatedBlogPosts
.map((p) => logger.path(aliasedSitePathToRelativePath(p.metadata.source)))
.join('\n- ')}
We recommend using truncation markers (code=${`<!-- truncate -->`} or code=${`{/* truncate */}`}) in blog posts to create shorter previews on blog paginated lists.
Tip: turn this security off with the code=${`onUntruncatedBlogPosts: 'ignore'`} blog plugin option.`;
logger.report(onUntruncatedBlogPosts)(message);
}
}

export function paginateBlogPosts({
blogPosts,
basePageUrl,
Expand Down
5 changes: 5 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
shouldBeListed,
applyProcessBlogPosts,
generateBlogPosts,
reportUntruncatedBlogPosts,
} from './blogUtils';
import footnoteIDFixer from './remark/footnoteIDFixer';
import {translateContent, getTranslationFiles} from './translations';
Expand Down Expand Up @@ -189,6 +190,10 @@ export default async function pluginContentBlog(
blogPosts,
processBlogPosts: options.processBlogPosts,
});
reportUntruncatedBlogPosts({
blogPosts,
onUntruncatedBlogPosts: options.onUntruncatedBlogPosts,
});
const listedBlogPosts = blogPosts.filter(shouldBeListed);

if (!blogPosts.length) {
Expand Down
4 changes: 4 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
tags: undefined,
authorsBasePath: 'authors',
onInlineAuthors: 'warn',
onUntruncatedBlogPosts: 'warn',
};

export const XSLTBuiltInPaths = {
Expand Down Expand Up @@ -240,6 +241,9 @@ const PluginOptionSchema = Joi.object<PluginOptions>({
onInlineAuthors: Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(DEFAULT_OPTIONS.onInlineAuthors),
onUntruncatedBlogPosts: Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(DEFAULT_OPTIONS.onUntruncatedBlogPosts),
}).default(DEFAULT_OPTIONS);

export function validateOptions({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,8 @@ declare module '@docusaurus/plugin-content-blog' {
authorsBasePath: string;
/** The behavior of Docusaurus when it finds inline authors. */
onInlineAuthors: 'ignore' | 'log' | 'warn' | 'throw';
/** The behavior of Docusaurus when it finds untruncated blog posts. */
onUntruncatedBlogPosts: 'ignore' | 'log' | 'warn' | 'throw';
};

export type UserFeedXSLTOptions =
Expand Down
2 changes: 2 additions & 0 deletions project-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ unlocalized
Unlocalized
unnormalized
unswizzle
untruncated
Untruncated
upvotes
urlset
Vannicatte
Expand Down
1 change: 1 addition & 0 deletions website/_dogfooding/dogfooding.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const dogfoodingPluginInstances: PluginConfig[] = [
: defaultReadingTime({content, options: {wordsPerMinute: 5}}),
onInlineTags: 'warn',
onInlineAuthors: 'ignore',
onUntruncatedBlogPosts: 'ignore',
tags: 'tags.yml',
} satisfies BlogOptions,
],
Expand Down
1 change: 1 addition & 0 deletions website/docs/api/plugins/plugin-content-blog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Accepted fields:
| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the blog post was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. |
| `tags` | `string \| false \| null \| undefined` | `tags.yml` | Path to the YAML tags file listing pre-defined tags. Relative to the blog content directory. |
| `onInlineTags` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when blog posts contain inline tags (not appearing in the list of pre-defined tags, usually `tags.yml`). |
| `onUntruncatedBlogPosts` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when blog posts do not contain a truncate marker. |

```mdx-code-block
</APITable>
Expand Down
4 changes: 4 additions & 0 deletions website/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,10 @@ export default async function createConfigAsync() {
blogDescription: 'Read blog posts about Docusaurus from the team',
blogSidebarCount: 'ALL',
blogSidebarTitle: 'All our posts',
onUntruncatedBlogPosts:
process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale
? 'warn'
: 'throw',
onInlineTags:
process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale
? 'warn'
Expand Down

0 comments on commit a096bbc

Please sign in to comment.