-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
feat: showcase #9967
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
Draft
OzakIOne
wants to merge
87
commits into
main
Choose a base branch
from
ozaki/showcase
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
feat: showcase #9967
Changes from 18 commits
Commits
Show all changes
87 commits
Select commit
Hold shift + click to select a range
2b37b51
wip init
OzakIOne f6b0d46
refactor: apply lint autofix
OzakIOne cd3908b
wip
OzakIOne a2516dc
refactor: apply lint autofix
OzakIOne 7cf981c
wip routes per yaml
OzakIOne ec35998
refactor: apply lint autofix
OzakIOne 8d1b174
wip
OzakIOne 7daa9a1
refactor: apply lint autofix
OzakIOne c542c81
ShowcaseDetails component
OzakIOne dddb8cf
cspell autolint fix
OzakIOne 1c825e0
refactor: apply lint autofix
OzakIOne 9790934
wip markdown process: crash
OzakIOne 49b6746
refactor: apply lint autofix
OzakIOne 6e40a79
wip use plugin page code logic
OzakIOne 984518e
fix: warning
OzakIOne 993efd2
wip process markdown
OzakIOne 8bee535
wip images
OzakIOne 022efa3
refactor: apply lint autofix
OzakIOne 30599c3
Update packages/docusaurus-plugin-showcase/package.json
OzakIOne bed9bb3
wip tests
OzakIOne c42c15e
refactor: apply lint autofix
OzakIOne e147034
wip tests
OzakIOne cdb7c07
consistent file naming
OzakIOne 46c57d6
wip tags file validation
OzakIOne 4a221f3
wip working tags from yaml
OzakIOne fc34725
prettier
OzakIOne 6b83e2d
wip
OzakIOne c3f32ab
wip
OzakIOne 8ab6dda
wip
OzakIOne 45af11f
add tests
OzakIOne a9d6bcf
wip
OzakIOne 91aa292
improve type
OzakIOne 4cecd0c
wip
OzakIOne 6670b7a
fix types
OzakIOne d9885db
dynamic validation
OzakIOne 9eab6ae
move schema creation outside of loadcontent
OzakIOne 0fdb9d6
wip tests
OzakIOne 290cdb4
wip tests
OzakIOne 65affab
wip tests
OzakIOne 867b604
wip
OzakIOne e1c51bf
wip
OzakIOne c89f8be
Merge branch 'main' into ozaki/showcase
OzakIOne 7a9418c
Merge branch 'main' into ozaki/showcase
OzakIOne 047b5f0
versions
slorber 3cef207
refactor: apply lint autofix
slorber c0a6520
yarnlock
slorber 6435e9a
Merge remote-tracking branch 'origin/ozaki/showcase' into ozaki/showcase
slorber 2af5b44
remove popper/tooltip
slorber 8f9408c
refactor: apply lint autofix
slorber 81acd87
showcase plugin client API setup
slorber 4f64b33
Merge remote-tracking branch 'origin/ozaki/showcase' into ozaki/showcase
slorber 0cfdd9d
hooks bypass extreme wip
OzakIOne c0c0f83
update with client showcase
OzakIOne 7b76e46
fix type error
OzakIOne 8504ad3
revert changes
OzakIOne 1fb54b6
Merge branch 'main' into ozaki/showcase
OzakIOne ff16819
refactor: apply lint autofix
OzakIOne 52bf244
wip showcase provider :D
OzakIOne c7cbafc
feat: new route props
OzakIOne 5b6626b
wip
OzakIOne 8c12b1c
wip
OzakIOne a4cb0ff
refactor: apply lint autofix
OzakIOne 61a7650
add all sites
OzakIOne c903765
refactor: apply lint autofix
OzakIOne 2855df5
allow null options
OzakIOne 38a71a6
fix tests
OzakIOne c9a05e2
wip
OzakIOne 8c1770b
admin script
OzakIOne 7869eb9
Merge branch 'main' into ozaki/showcase
OzakIOne 82858f8
fix build
OzakIOne 77aaf4a
refactor: apply lint autofix
OzakIOne 34a0e3f
update admin script
OzakIOne 40000d0
refactor clean
OzakIOne 510539f
refactor: apply lint autofix
OzakIOne c8b7e6d
screenshot api
OzakIOne 01657b0
Merge branch 'main' into ozaki/showcase
slorber 2c99553
Fix packages
slorber 57665a8
adjust ts configs for showcase
slorber 080949b
fix packages
slorber 841c81f
normalize tsBuildInfoFile
slorber 99a4c5f
Merge branch 'main' into ozaki/showcase
slorber 7e417aa
remove bad MDX import
slorber 8ad0747
wip routeContext
OzakIOne 633397a
wip
OzakIOne 77ee19e
fix unknown word test
OzakIOne 27a57d0
refactor: apply lint autofix
OzakIOne dee675c
feat route context
OzakIOne File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.tsbuildinfo* | ||
tsconfig* | ||
__tests__ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# `@docusaurus/plugin-showcase` | ||
|
||
Showcase plugin for Docusaurus. | ||
|
||
## Usage | ||
|
||
See [plugin-showcase documentation](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-showcase). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "@docusaurus/plugin-showcase", | ||
OzakIOne marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
"version": "3.0.0", | ||
"description": "Showcase plugin for Docusaurus.", | ||
"main": "lib/index.js", | ||
"types": "src/plugin-showcase.d.ts", | ||
"scripts": { | ||
"build": "tsc", | ||
"watch": "tsc --watch" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/facebook/docusaurus.git", | ||
"directory": "packages/docusaurus-plugin-showcase" | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"@docusaurus/core": "3.0.0", | ||
"@docusaurus/types": "3.0.0", | ||
"@docusaurus/utils": "3.0.0", | ||
"@docusaurus/utils-validation": "3.0.0", | ||
"fs-extra": "^11.1.1", | ||
"js-yaml": "^4.1.0", | ||
"tslib": "^2.6.0", | ||
"webpack": "^5.88.1" | ||
}, | ||
"peerDependencies": { | ||
"react": "^18.0.0", | ||
"react-dom": "^18.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=18.0" | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
/** | ||
* 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 { | ||
DEFAULT_PLUGIN_ID, | ||
addTrailingPathSeparator, | ||
aliasedSitePath, | ||
docuHash, | ||
getFolderContainingFile, | ||
getPluginI18nPath, | ||
Globby, | ||
parseMarkdownFile, | ||
aliasedSitePathToRelativePath, | ||
createAbsoluteFilePathMatcher, | ||
} from '@docusaurus/utils'; | ||
import Yaml from 'js-yaml'; | ||
|
||
import {validateShowcaseFrontMatter} from './options'; | ||
import type {LoadContext, Plugin, RouteMetadata} from '@docusaurus/types'; | ||
import type {PluginOptions, Content} from '@docusaurus/plugin-showcase'; | ||
import type {ShowcaseContentPaths} from './types'; | ||
|
||
export function getContentPathList( | ||
contentPaths: ShowcaseContentPaths, | ||
): string[] { | ||
return [contentPaths.contentPathLocalized, contentPaths.contentPath]; | ||
} | ||
|
||
const isMarkdownSource = (source: string) => | ||
source.endsWith('.md') || source.endsWith('.mdx'); | ||
|
||
export default function pluginContentShowcase( | ||
context: LoadContext, | ||
options: PluginOptions, | ||
): Plugin<Content | null> { | ||
const {siteConfig, siteDir, generatedFilesDir, localizationDir} = context; | ||
|
||
const contentPaths: ShowcaseContentPaths = { | ||
contentPath: path.resolve(siteDir, options.path), | ||
contentPathLocalized: getPluginI18nPath({ | ||
localizationDir, | ||
pluginName: 'docusaurus-plugin-content-pages', | ||
pluginId: options.id, | ||
}), | ||
}; | ||
|
||
const pluginDataDirRoot = path.join( | ||
generatedFilesDir, | ||
'docusaurus-plugin-showcase', | ||
); | ||
const dataDir = path.join(pluginDataDirRoot, options.id ?? DEFAULT_PLUGIN_ID); | ||
|
||
return { | ||
name: 'docusaurus-plugin-showcase', | ||
|
||
// todo doesn't work | ||
// getPathsToWatch() { | ||
// const {include} = options; | ||
// return getContentPathList(contentPaths).flatMap((contentPath) => | ||
// include.map((pattern) => `${contentPath}/${pattern}`), | ||
// ); | ||
// }, | ||
|
||
async loadContent() { | ||
const {include} = options; | ||
|
||
if (!(await fs.pathExists(contentPaths.contentPath))) { | ||
return null; | ||
} | ||
|
||
// const {baseUrl} = siteConfig; | ||
const showcaseFiles = await Globby(include, { | ||
cwd: contentPaths.contentPath, | ||
ignore: options.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 aliasedSourcePath = aliasedSitePath(sourcePath, siteDir); | ||
if (!isMarkdownSource(sourcePath)) { | ||
const rawYaml = await fs.readFile(sourcePath, 'utf-8'); | ||
const unsafeYaml = Yaml.load(rawYaml) as {[key: string]: unknown}; | ||
const yaml = validateShowcaseFrontMatter(unsafeYaml); | ||
return { | ||
type: 'yaml', | ||
...yaml, | ||
}; | ||
} | ||
const rawMarkdown = await fs.readFile(sourcePath, 'utf-8'); | ||
const {frontMatter: unsafeFrontMatter, content} = | ||
await parseMarkdownFile({ | ||
filePath: sourcePath, | ||
fileContent: rawMarkdown, | ||
parseFrontMatter: siteConfig.markdown?.parseFrontMatter, | ||
}); | ||
const frontMatter = validateShowcaseFrontMatter(unsafeFrontMatter); | ||
return { | ||
type: 'markdown', | ||
...frontMatter, | ||
content, | ||
sourcePath: aliasedSourcePath, | ||
}; | ||
} | ||
|
||
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 as Error}, | ||
); | ||
} | ||
} | ||
|
||
return { | ||
website: await Promise.all( | ||
showcaseFiles.map(doProcessShowcaseSourceFile), | ||
), | ||
}; | ||
}, | ||
|
||
async contentLoaded({content, actions}) { | ||
if (!content) { | ||
return; | ||
} | ||
|
||
const {addRoute, createData} = actions; | ||
|
||
function createPageRouteMetadata( | ||
metadata: Content['website'][number], | ||
): RouteMetadata { | ||
return { | ||
sourceFilePath: aliasedSitePathToRelativePath(metadata.sourcePath!), | ||
// TODO add support for last updated date in the page plugin | ||
// at least for Markdown files | ||
// lastUpdatedAt: metadata.lastUpdatedAt, | ||
lastUpdatedAt: undefined, | ||
}; | ||
} | ||
|
||
await Promise.all( | ||
content.website.map(async (item) => { | ||
if (item.type === 'yaml') { | ||
return; | ||
} | ||
await createData( | ||
`${docuHash(item.sourcePath!)}.json`, | ||
JSON.stringify(item), | ||
); | ||
|
||
const routeMetadata = createPageRouteMetadata(item); | ||
|
||
const mdxPath = aliasedSitePathToRelativePath(item.sourcePath!); | ||
console.log('mdxPath', mdxPath); | ||
|
||
addRoute({ | ||
path: `/showcaseAll/${item.title}`, | ||
component: '@theme/ShowcaseDetails', | ||
metadata: routeMetadata, | ||
modules: { | ||
content: item.sourcePath!, | ||
}, | ||
exact: true, | ||
}); | ||
}), | ||
); | ||
|
||
const showcaseAllData = await createData( | ||
'showcaseAll.json', | ||
JSON.stringify(content.website), | ||
); | ||
|
||
addRoute({ | ||
path: '/showcaseAll', | ||
component: '@theme/Showcase', | ||
modules: { | ||
content: showcaseAllData, | ||
}, | ||
exact: true, | ||
}); | ||
}, | ||
|
||
configureWebpack() { | ||
const contentDirs = getContentPathList(contentPaths); | ||
|
||
return { | ||
resolve: { | ||
alias: { | ||
'~showcase': pluginDataDirRoot, | ||
}, | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.mdx?$/i, | ||
include: contentDirs | ||
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970 | ||
.map(addTrailingPathSeparator), | ||
use: [ | ||
{ | ||
loader: require.resolve('@docusaurus/mdx-loader'), | ||
options: { | ||
staticDirs: siteConfig.staticDirectories.map((dir) => | ||
path.resolve(siteDir, dir), | ||
), | ||
siteDir, | ||
isMDXPartial: createAbsoluteFilePathMatcher( | ||
options.exclude, | ||
contentDirs, | ||
), | ||
metadataPath: (mdxPath: string) => { | ||
// Note that metadataPath must be the same/in-sync as | ||
// the path from createData for each MDX. | ||
const aliasedPath = aliasedSitePath(mdxPath, siteDir); | ||
return path.join( | ||
dataDir, | ||
`${docuHash(aliasedPath)}.json`, | ||
); | ||
}, | ||
// Assets allow to convert some relative images paths to | ||
// require() calls | ||
createAssets: ({ | ||
frontMatter, | ||
}: { | ||
frontMatter: Content['website'][number]; | ||
}) => ({ | ||
image: frontMatter.preview, | ||
}), | ||
markdownConfig: siteConfig.markdown, | ||
}, | ||
}, | ||
{ | ||
loader: path.resolve(__dirname, './markdownLoader.js'), | ||
}, | ||
].filter(Boolean), | ||
}, | ||
], | ||
}, | ||
}; | ||
}, | ||
}; | ||
} | ||
|
||
export {validateOptions} from './options'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* 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 {LoaderContext} from 'webpack'; | ||
|
||
export default function markdownLoader( | ||
this: LoaderContext<undefined>, | ||
fileString: string, | ||
): void { | ||
const callback = this.async(); | ||
|
||
// const options = this.getOptions(); | ||
|
||
// TODO provide additional md processing here? like interlinking pages? | ||
// fileString = linkify(fileString) | ||
|
||
return callback(null, fileString); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/** | ||
* 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 { | ||
Joi, | ||
validateFrontMatter, | ||
RouteBasePathSchema, | ||
} from '@docusaurus/utils-validation'; | ||
import {GlobExcludeDefault} from '@docusaurus/utils'; | ||
import type {OptionValidationContext} from '@docusaurus/types'; | ||
import type { | ||
PluginOptions, | ||
Options, | ||
ShowcaseFrontMatter, | ||
} from '@docusaurus/plugin-showcase'; | ||
|
||
export const DEFAULT_OPTIONS: PluginOptions = { | ||
id: 'showcase', | ||
path: 'src/showcase/website', // Path to data on filesystem, relative to site dir. | ||
routeBasePath: '/', // URL Route. | ||
include: ['**/*.{yml,yaml,md,mdx}'], // Extensions to include. | ||
exclude: GlobExcludeDefault, | ||
}; | ||
|
||
const PluginOptionSchema = Joi.object<PluginOptions>({ | ||
path: Joi.string().default(DEFAULT_OPTIONS.path), | ||
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), | ||
}); | ||
|
||
const contentAuthorsSchema = Joi.object({ | ||
title: Joi.string().required(), | ||
description: Joi.string().required(), | ||
preview: Joi.string().required(), | ||
website: Joi.string().required(), | ||
source: Joi.string().required(), | ||
tags: Joi.array().items(Joi.string()).required(), | ||
}); | ||
OzakIOne marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
export function validateOptions({ | ||
validate, | ||
options, | ||
}: OptionValidationContext<Options, PluginOptions>): PluginOptions { | ||
const validatedOptions = validate(PluginOptionSchema, options); | ||
return validatedOptions; | ||
} | ||
|
||
export function validateShowcaseFrontMatter(frontMatter: { | ||
[key: string]: unknown; | ||
}): ShowcaseFrontMatter { | ||
return validateFrontMatter(frontMatter, contentAuthorsSchema); | ||
} | ||
OzakIOne marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.