diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index 7fe81e83af..d43ec69c1b 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -26,7 +26,7 @@ import { } from '@docusaurus/utils'; import {validatePageFrontMatter} from './frontMatter'; import type {LoadContext, Plugin, RouteMetadata} from '@docusaurus/types'; -import type {PagesContentPaths} from './types'; +import type {ShowcaseContentPaths} from './types'; import type { PluginOptions, Metadata, @@ -34,7 +34,9 @@ import type { PageFrontMatter, } from '@docusaurus/plugin-content-pages'; -export function getContentPathList(contentPaths: PagesContentPaths): string[] { +export function getContentPathList( + contentPaths: ShowcaseContentPaths, +): string[] { return [contentPaths.contentPathLocalized, contentPaths.contentPath]; } @@ -47,7 +49,7 @@ export default function pluginContentPages( ): Plugin { const {siteConfig, siteDir, generatedFilesDir, localizationDir} = context; - const contentPaths: PagesContentPaths = { + const contentPaths: ShowcaseContentPaths = { contentPath: path.resolve(siteDir, options.path), contentPathLocalized: getPluginI18nPath({ localizationDir, diff --git a/packages/docusaurus-plugin-content-pages/src/types.ts b/packages/docusaurus-plugin-content-pages/src/types.ts index 2d11492cb0..457a800cc6 100644 --- a/packages/docusaurus-plugin-content-pages/src/types.ts +++ b/packages/docusaurus-plugin-content-pages/src/types.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -export type PagesContentPaths = { +export type ShowcaseContentPaths = { contentPath: string; contentPathLocalized: string; }; diff --git a/packages/docusaurus-plugin-content-showcase/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-showcase/src/__tests__/index.test.ts index 66660d4679..0522f31f9b 100644 --- a/packages/docusaurus-plugin-content-showcase/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-showcase/src/__tests__/index.test.ts @@ -9,13 +9,13 @@ import path from 'path'; import {loadContext} from '@docusaurus/core/src/server/site'; import {normalizePluginOptions} from '@docusaurus/utils-validation'; import {fromPartial} from '@total-typescript/shoehorn'; -import pluginContentPages from '../index'; +import pluginContentShowcase from '../index'; import {validateOptions} from '../options'; import type {PluginOptions} from '@docusaurus/plugin-content-showcase'; const loadPluginContent = async (siteDir: string, options: PluginOptions) => { const context = await loadContext({siteDir}); - const plugin = await pluginContentPages( + const plugin = await pluginContentShowcase( context, validateOptions({ validate: normalizePluginOptions, diff --git a/packages/docusaurus-plugin-content-showcase/src/__tests__/options.test.ts b/packages/docusaurus-plugin-content-showcase/src/__tests__/options.test.ts index eea3463732..4b95f8dfe3 100644 --- a/packages/docusaurus-plugin-content-showcase/src/__tests__/options.test.ts +++ b/packages/docusaurus-plugin-content-showcase/src/__tests__/options.test.ts @@ -101,7 +101,6 @@ describe('normalizeShowcasePluginOptions', () => { }, }, }; - // todo fix ts error expect(testValidate(userOptions)).toEqual({ ...defaultOptions, ...userOptions, diff --git a/packages/docusaurus-plugin-content-showcase/src/__tests__/tags.test.ts b/packages/docusaurus-plugin-content-showcase/src/__tests__/tags.test.ts index b93b787ba4..3e756b31e1 100644 --- a/packages/docusaurus-plugin-content-showcase/src/__tests__/tags.test.ts +++ b/packages/docusaurus-plugin-content-showcase/src/__tests__/tags.test.ts @@ -26,7 +26,6 @@ const invalidTags = { message: 'Open-Source Docusaurus sites can be useful for inspiration!', id: 'showcase.tag.opensource.description', }, - // todo throw an error with `getTagsList tagSchema` color: '#39c', }, }; @@ -55,7 +54,7 @@ describe('showcase tags', () => { }); await expect(() => tagList).rejects.toThrowErrorMatchingInlineSnapshot( - `"There was an error extracting tags: Color must be a hexadecimal color string (e.g., #RRGGBB #rrggbb)"`, + `"There was an error extracting tags: Color must be a hexadecimal color string (e.g., #14cfc3 #E9669E)"`, ); }); }); diff --git a/packages/docusaurus-plugin-content-showcase/src/__tests__/validation.test.ts b/packages/docusaurus-plugin-content-showcase/src/__tests__/validation.test.ts index 65bf07950e..6d6d501eac 100644 --- a/packages/docusaurus-plugin-content-showcase/src/__tests__/validation.test.ts +++ b/packages/docusaurus-plugin-content-showcase/src/__tests__/validation.test.ts @@ -38,7 +38,6 @@ async function prepareSchema() { return createShowcaseItemSchema(tagList); } -// todo broken describe('showcase item schema', () => { it('accepts valid item', async () => { const item: ShowcaseItem = { diff --git a/packages/docusaurus-plugin-content-showcase/src/index.ts b/packages/docusaurus-plugin-content-showcase/src/index.ts index 8602d26f61..933a18acc2 100644 --- a/packages/docusaurus-plugin-content-showcase/src/index.ts +++ b/packages/docusaurus-plugin-content-showcase/src/index.ts @@ -7,14 +7,11 @@ import fs from 'fs-extra'; import path from 'path'; -import { - getFolderContainingFile, - getPluginI18nPath, - Globby, -} from '@docusaurus/utils'; -import Yaml from 'js-yaml'; -import {createShowcaseItemSchema, validateShowcaseItem} from './validation'; +import {getPluginI18nPath} from '@docusaurus/utils'; +import {createShowcaseItemSchema} from './validation'; import {getTagsList} from './tags'; +import {processContentLoaded} from './lifecycle/contentLoaded'; +import {processLoadContent} from './lifecycle/loadContent'; import type {LoadContext, Plugin} from '@docusaurus/types'; import type { PluginOptions, @@ -34,14 +31,14 @@ export default async function pluginContentShowcase( ): Promise> { const {siteDir, localizationDir} = context; // todo check for better naming of path: sitePath - const {include, exclude, tags, routeBasePath, path: sitePath} = options; + const {include, exclude, tags, routeBasePath, path: sitePath, id} = options; const contentPaths: ShowcaseContentPaths = { contentPath: path.resolve(siteDir, sitePath), contentPathLocalized: getPluginI18nPath({ localizationDir, pluginName: 'docusaurus-plugin-content-showcase', - pluginId: options.id, + pluginId: id, }), }; @@ -55,13 +52,16 @@ export default async function pluginContentShowcase( return { name: 'docusaurus-plugin-content-showcase', - // todo doesn't work - // getPathsToWatch() { - // const {include} = options; - // return getContentPathList(contentPaths).flatMap((contentPath) => - // include.map((pattern) => `${contentPath}/${pattern}`), - // ); - // }, + // TODO doesn't work + getPathsToWatch() { + console.log( + 'getContentPathList(contentPaths):', + getContentPathList(contentPaths), + ); + return getContentPathList(contentPaths).flatMap((contentPath) => + include.map((pattern) => `${contentPath}/${pattern}`), + ); + }, async loadContent(): Promise { if (!(await fs.pathExists(contentPaths.contentPath))) { @@ -70,45 +70,12 @@ export default async function pluginContentShowcase( ); } - const showcaseFiles = await Globby(include, { - cwd: contentPaths.contentPath, - ignore: [...exclude], + return processLoadContent({ + include, + exclude, + contentPaths, + showcaseItemSchema, }); - - async function processShowcaseSourceFile(relativeSource: string) { - // Lookup in localized folder in priority - const contentPath = await getFolderContainingFile( - getContentPathList(contentPaths), - relativeSource, - ); - - const sourcePath = path.join(contentPath, relativeSource); - const data = await fs.readFile(sourcePath, 'utf-8'); - const item = Yaml.load(data); - const showcaseItem = validateShowcaseItem({ - item, - showcaseItemSchema, - }); - - return showcaseItem; - } - - async function doProcessShowcaseSourceFile(relativeSource: string) { - try { - return await processShowcaseSourceFile(relativeSource); - } catch (err) { - throw new Error( - `Processing of page source file path=${relativeSource} failed.`, - {cause: err}, - ); - } - } - - return { - items: await Promise.all( - showcaseFiles.map(doProcessShowcaseSourceFile), - ), - }; }, async contentLoaded({content, actions}) { @@ -118,19 +85,11 @@ export default async function pluginContentShowcase( const {addRoute, createData} = actions; - const showcaseAllData = await createData( - 'showcaseAll.json', - JSON.stringify(content.items), - ); - - addRoute({ - path: routeBasePath, - component: '@theme/Showcase', - modules: { - content: showcaseAllData, - // img: '@site/src/showcase/website/ozaki/aot.jpg', - }, - exact: true, + await processContentLoaded({ + content, + routeBasePath, + addRoute, + createData, }); }, }; diff --git a/packages/docusaurus-plugin-content-showcase/src/lifecycle/contentLoaded.ts b/packages/docusaurus-plugin-content-showcase/src/lifecycle/contentLoaded.ts new file mode 100644 index 0000000000..c7a4019339 --- /dev/null +++ b/packages/docusaurus-plugin-content-showcase/src/lifecycle/contentLoaded.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import type {ShowcaseItems} from '@docusaurus/plugin-content-showcase'; +import type {PluginContentLoadedActions} from '@docusaurus/types'; + +export async function processContentLoaded({ + content, + routeBasePath, + addRoute, + createData, +}: { + content: ShowcaseItems; + routeBasePath: string; + addRoute: PluginContentLoadedActions['addRoute']; + createData: PluginContentLoadedActions['createData']; +}): Promise { + const showcaseAllData = await createData( + 'showcaseAll.json', + JSON.stringify(content.items), + ); + + addRoute({ + path: routeBasePath, + component: '@theme/Showcase', + modules: { + content: showcaseAllData, + }, + exact: true, + }); +} diff --git a/packages/docusaurus-plugin-content-showcase/src/lifecycle/loadContent.ts b/packages/docusaurus-plugin-content-showcase/src/lifecycle/loadContent.ts new file mode 100644 index 0000000000..bbd404cb61 --- /dev/null +++ b/packages/docusaurus-plugin-content-showcase/src/lifecycle/loadContent.ts @@ -0,0 +1,68 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import fs from 'fs-extra'; +import path from 'path'; +import Yaml from 'js-yaml'; +import { + Globby, + getContentPathList, + getFolderContainingFile, +} from '@docusaurus/utils'; +import {validateShowcaseItem} from '../validation'; +import type {ShowcaseContentPaths} from '../types'; +import type {ShowcaseItems} from '@docusaurus/plugin-content-showcase'; + +export async function processLoadContent({ + include, + exclude, + contentPaths, + showcaseItemSchema, +}: { + include: string[]; + exclude: string[]; + contentPaths: ShowcaseContentPaths; + showcaseItemSchema: any; +}): Promise { + const showcaseFiles = await Globby(include, { + cwd: contentPaths.contentPath, + ignore: [...exclude], + }); + + async function processShowcaseSourceFile(relativeSource: string) { + // Lookup in localized folder in priority + const contentPath = await getFolderContainingFile( + getContentPathList(contentPaths), + relativeSource, + ); + + const sourcePath = path.join(contentPath, relativeSource); + const data = await fs.readFile(sourcePath, 'utf-8'); + const item = Yaml.load(data); + const showcaseItem = validateShowcaseItem({ + item, + showcaseItemSchema, + }); + + return showcaseItem; + } + + async function doProcessShowcaseSourceFile(relativeSource: string) { + try { + return await processShowcaseSourceFile(relativeSource); + } catch (err) { + throw new Error( + `Processing of page source file path=${relativeSource} failed.`, + {cause: err}, + ); + } + } + + return { + items: await Promise.all(showcaseFiles.map(doProcessShowcaseSourceFile)), + }; +} diff --git a/packages/docusaurus-plugin-content-showcase/src/options.ts b/packages/docusaurus-plugin-content-showcase/src/options.ts index f7c08f71b7..c92ad6fbd0 100644 --- a/packages/docusaurus-plugin-content-showcase/src/options.ts +++ b/packages/docusaurus-plugin-content-showcase/src/options.ts @@ -12,11 +12,10 @@ import type {OptionValidationContext} from '@docusaurus/types'; import type {PluginOptions, Options} from '@docusaurus/plugin-content-showcase'; export const DEFAULT_OPTIONS: PluginOptions = { - id: 'showcase', path: 'showcase', // Path to data on filesystem, relative to site dir. routeBasePath: '/showcase', // URL Route. 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.*'], tags: 'tags.yml', }; @@ -26,9 +25,7 @@ const PluginOptionSchema = Joi.object({ routeBasePath: RouteBasePathSchema.default(DEFAULT_OPTIONS.routeBasePath), include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include), exclude: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.exclude), - id: Joi.string().default(DEFAULT_OPTIONS.id), tags: Joi.alternatives() - // todo ozaki understand this .try(Joi.string().default(DEFAULT_OPTIONS.tags), tagSchema) .default(DEFAULT_OPTIONS.tags), }); diff --git a/packages/docusaurus-plugin-content-showcase/src/tags.ts b/packages/docusaurus-plugin-content-showcase/src/tags.ts index ad2c3d8675..1989554642 100644 --- a/packages/docusaurus-plugin-content-showcase/src/tags.ts +++ b/packages/docusaurus-plugin-content-showcase/src/tags.ts @@ -20,12 +20,11 @@ export const tagSchema = Joi.object().pattern( id: Joi.string().required(), }).required(), color: Joi.string() - // todo doesnt work ??? .pattern(/^#[\dA-Fa-f]{6}$/) .required() .messages({ 'string.pattern.base': - 'Color must be a hexadecimal color string (e.g., #RRGGBB #rrggbb)', + 'Color must be a hexadecimal color string (e.g., #14cfc3 #E9669E)', }), }), ); @@ -38,8 +37,6 @@ export async function getTagsList({ configPath: string; }): Promise { if (typeof configTags === 'object') { - console.log('Gettings Tag List and validating'); - tagSchema.describe(); const tags = tagSchema.validate(configTags); if (tags.error) { throw new Error( @@ -72,5 +69,5 @@ export async function getTagsList({ } export function createTagSchema(tags: string[]): Joi.Schema { - return Joi.array().items(Joi.string().valid(...tags)); // Schema for array of strings + return Joi.array().items(Joi.string().valid(...tags)); }