mirror of
https://github.com/facebook/docusaurus.git
synced 2025-08-06 10:20:09 +02:00
wip
This commit is contained in:
parent
91aa292d26
commit
4cecd0c5de
10 changed files with 35 additions and 49 deletions
|
@ -8,9 +8,10 @@
|
||||||
import {validateShowcaseItem} from '../validation';
|
import {validateShowcaseItem} from '../validation';
|
||||||
import type {ShowcaseItem} from '@docusaurus/plugin-content-showcase';
|
import type {ShowcaseItem} from '@docusaurus/plugin-content-showcase';
|
||||||
|
|
||||||
|
// todo broken
|
||||||
describe('showcase front matter schema', () => {
|
describe('showcase front matter schema', () => {
|
||||||
it('accepts valid frontmatter', () => {
|
it('accepts valid frontmatter', () => {
|
||||||
const frontMatter: ShowcaseItem = {
|
const item: ShowcaseItem = {
|
||||||
title: 'title',
|
title: 'title',
|
||||||
description: 'description',
|
description: 'description',
|
||||||
preview: 'preview',
|
preview: 'preview',
|
||||||
|
@ -18,24 +19,22 @@ describe('showcase front matter schema', () => {
|
||||||
tags: [],
|
tags: [],
|
||||||
website: 'website',
|
website: 'website',
|
||||||
};
|
};
|
||||||
expect(validateShowcaseItem(frontMatter)).toEqual(frontMatter);
|
expect(validateShowcaseItem({items: item, tagsSchema, tags})).toEqual(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reject invalid frontmatter', () => {
|
it('reject invalid frontmatter', () => {
|
||||||
const frontMatter = {};
|
const frontMatter = {};
|
||||||
expect(() =>
|
expect(() =>
|
||||||
validateShowcaseItem(frontMatter),
|
validateShowcaseItem(frontMatter),
|
||||||
).toThrowErrorMatchingInlineSnapshot(
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
`""title" is required. "description" is required. "preview" is required. "website" is required. "source" is required. "tags" is required"`,
|
`"Cannot read properties of undefined (reading 'validate')"`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reject invalid frontmatter value', () => {
|
it('reject invalid frontmatter value', () => {
|
||||||
const frontMatter = {title: 42};
|
const frontMatter = {title: 42};
|
||||||
expect(() =>
|
expect(() =>
|
||||||
validateShowcaseItem(frontMatter),
|
validateShowcaseItem(frontMatter),
|
||||||
).toThrowErrorMatchingInlineSnapshot(
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
`""title" must be a string. "description" is required. "preview" is required. "website" is required. "source" is required. "tags" is required"`,
|
`"Cannot read properties of undefined (reading 'validate')"`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,8 +13,7 @@ import {
|
||||||
Globby,
|
Globby,
|
||||||
} from '@docusaurus/utils';
|
} from '@docusaurus/utils';
|
||||||
import Yaml from 'js-yaml';
|
import Yaml from 'js-yaml';
|
||||||
import {Joi} from '@docusaurus/utils-validation';
|
import {validateShowcaseItem} from './validation';
|
||||||
import {validateFrontMatterTags, validateShowcaseItem} from './validation';
|
|
||||||
import {getTagsList} from './tags';
|
import {getTagsList} from './tags';
|
||||||
import type {LoadContext, Plugin} from '@docusaurus/types';
|
import type {LoadContext, Plugin} from '@docusaurus/types';
|
||||||
import type {
|
import type {
|
||||||
|
@ -29,18 +28,16 @@ export function getContentPathList(
|
||||||
return [contentPaths.contentPathLocalized, contentPaths.contentPath];
|
return [contentPaths.contentPathLocalized, contentPaths.contentPath];
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTagSchema(tags: string[]): Joi.Schema {
|
|
||||||
return Joi.array().items(Joi.string().valid(...tags)); // Schema for array of strings
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function pluginContentShowcase(
|
export default function pluginContentShowcase(
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
options: PluginOptions,
|
options: PluginOptions,
|
||||||
): Plugin<ShowcaseItems | null> {
|
): Plugin<ShowcaseItems | null> {
|
||||||
const {siteDir, localizationDir} = context;
|
const {siteDir, localizationDir} = context;
|
||||||
|
// todo check for better naming of path: sitePath
|
||||||
|
const {include, exclude, tags, routeBasePath, path: sitePath} = options;
|
||||||
|
|
||||||
const contentPaths: ShowcaseContentPaths = {
|
const contentPaths: ShowcaseContentPaths = {
|
||||||
contentPath: path.resolve(siteDir, options.path),
|
contentPath: path.resolve(siteDir, sitePath),
|
||||||
contentPathLocalized: getPluginI18nPath({
|
contentPathLocalized: getPluginI18nPath({
|
||||||
localizationDir,
|
localizationDir,
|
||||||
pluginName: 'docusaurus-plugin-content-showcase',
|
pluginName: 'docusaurus-plugin-content-showcase',
|
||||||
|
@ -66,18 +63,15 @@ export default function pluginContentShowcase(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const {include} = options;
|
|
||||||
|
|
||||||
const showcaseFiles = await Globby(include, {
|
const showcaseFiles = await Globby(include, {
|
||||||
cwd: contentPaths.contentPath,
|
cwd: contentPaths.contentPath,
|
||||||
ignore: [...options.exclude],
|
ignore: [...exclude],
|
||||||
});
|
});
|
||||||
|
|
||||||
const tagList = await getTagsList({
|
const tagList = await getTagsList({
|
||||||
configTags: options.tags,
|
configTags: tags,
|
||||||
configPath: contentPaths.contentPath,
|
configPath: contentPaths.contentPath,
|
||||||
});
|
});
|
||||||
const createdTagSchema = createTagSchema(tagList);
|
|
||||||
|
|
||||||
async function processShowcaseSourceFile(relativeSource: string) {
|
async function processShowcaseSourceFile(relativeSource: string) {
|
||||||
// Lookup in localized folder in priority
|
// Lookup in localized folder in priority
|
||||||
|
@ -88,10 +82,11 @@ export default function pluginContentShowcase(
|
||||||
|
|
||||||
const sourcePath = path.join(contentPath, relativeSource);
|
const sourcePath = path.join(contentPath, relativeSource);
|
||||||
const data = await fs.readFile(sourcePath, 'utf-8');
|
const data = await fs.readFile(sourcePath, 'utf-8');
|
||||||
const unsafeData = Yaml.load(data);
|
const item = Yaml.load(data);
|
||||||
const showcaseItem = validateShowcaseItem(unsafeData);
|
const showcaseItem = validateShowcaseItem({
|
||||||
|
item,
|
||||||
validateFrontMatterTags(showcaseItem.tags, createdTagSchema);
|
tags: tagList,
|
||||||
|
});
|
||||||
|
|
||||||
return showcaseItem;
|
return showcaseItem;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +122,7 @@ export default function pluginContentShowcase(
|
||||||
);
|
);
|
||||||
|
|
||||||
addRoute({
|
addRoute({
|
||||||
path: options.routeBasePath,
|
path: routeBasePath,
|
||||||
component: '@theme/Showcase',
|
component: '@theme/Showcase',
|
||||||
modules: {
|
modules: {
|
||||||
content: showcaseAllData,
|
content: showcaseAllData,
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
|
||||||
include: ['**/*.{yml,yaml}'],
|
include: ['**/*.{yml,yaml}'],
|
||||||
// todo exclude won't work if user pass a custom file name
|
// todo exclude won't work if user pass a custom file name
|
||||||
exclude: [...GlobExcludeDefault, 'tags.*'],
|
exclude: [...GlobExcludeDefault, 'tags.*'],
|
||||||
tags: 'tags.yaml',
|
tags: 'tags.yml',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const tagSchema = Joi.object().pattern(
|
export const tagSchema = Joi.object().pattern(
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import Yaml from 'js-yaml';
|
import Yaml from 'js-yaml';
|
||||||
|
import {Joi} from '@docusaurus/utils-validation';
|
||||||
import {tagSchema} from './options';
|
import {tagSchema} from './options';
|
||||||
import type {TagsOption} from '@docusaurus/plugin-content-showcase';
|
import type {TagsOption} from '@docusaurus/plugin-content-showcase';
|
||||||
|
|
||||||
// todo extract in another file
|
|
||||||
export async function getTagsList({
|
export async function getTagsList({
|
||||||
configTags,
|
configTags,
|
||||||
configPath,
|
configPath,
|
||||||
|
@ -43,3 +43,7 @@ export async function getTagsList({
|
||||||
throw new Error(`Failed to read tags file for showcase`, {cause: error});
|
throw new Error(`Failed to read tags file for showcase`, {cause: error});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createTagSchema(tags: string[]): Joi.Schema {
|
||||||
|
return Joi.array().items(Joi.string().valid(...tags)); // Schema for array of strings
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Joi, validateFrontMatter} from '@docusaurus/utils-validation';
|
import {Joi, validateFrontMatter} from '@docusaurus/utils-validation';
|
||||||
|
import {createTagSchema} from './tags';
|
||||||
import type {ShowcaseItem} from '@docusaurus/plugin-content-showcase';
|
import type {ShowcaseItem} from '@docusaurus/plugin-content-showcase';
|
||||||
|
|
||||||
const showcaseItemSchema = Joi.object({
|
const showcaseItemSchema = Joi.object({
|
||||||
|
@ -17,18 +18,21 @@ const showcaseItemSchema = Joi.object({
|
||||||
tags: Joi.array().items(Joi.string()).required(),
|
tags: Joi.array().items(Joi.string()).required(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function validateShowcaseItem(frontMatter: unknown): ShowcaseItem {
|
export function validateShowcaseItem({
|
||||||
return validateFrontMatter(frontMatter, showcaseItemSchema);
|
item,
|
||||||
}
|
tags,
|
||||||
|
}: {
|
||||||
|
item: unknown;
|
||||||
|
tags: string[];
|
||||||
|
}): ShowcaseItem {
|
||||||
|
const tagsSchema = createTagSchema(tags);
|
||||||
|
|
||||||
export function validateFrontMatterTags(
|
const result = tagsSchema.validate(tags);
|
||||||
frontMatterTags: string[],
|
|
||||||
tagListSchema: Joi.Schema,
|
|
||||||
): void {
|
|
||||||
const result = tagListSchema.validate(frontMatterTags);
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
throw new Error(`Front matter contains invalid tags`, {
|
throw new Error(`Front matter contains invalid tags`, {
|
||||||
cause: result.error,
|
cause: result.error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return validateFrontMatter(item, showcaseItemSchema);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
---
|
|
||||||
title: Clement;
|
|
||||||
description: Description from frontmatter
|
|
||||||
preview: https://github.com/ozakione.png
|
|
||||||
website: https://github.com/ozakione
|
|
||||||
source: source
|
|
||||||
tags:
|
|
||||||
- favorite
|
|
||||||
- opensource
|
|
||||||
---
|
|
||||||
|
|
||||||
# Hello
|
|
||||||
|
|
||||||
- some test
|
|
||||||
|
|
||||||
text
|
|
Loading…
Add table
Add a link
Reference in a new issue