docs: diagrams plugin tooling (#5741)
* added plugin * updated plugin + added component * dummy data TO BE REMOVED * (wip) workflow generator tool * add workflow generator tooling * updated the generator tool * added code file creation * fix design of diagrams * configured diagram theme * added build script * removed comments + unnecessary files * general fixes * refactored plugin * added README + more output types
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import React from "react"
|
||||
import { Diagram2CodeSpec } from "@medusajs/docs"
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
import { specs } from "../../utils/specs"
|
||||
import CodeBlock from "../../theme/CodeBlock"
|
||||
import Mermaid from "@docusaurus/theme-mermaid/lib/theme/Mermaid/index.js"
|
||||
|
||||
type WorkflowReferenceProps = {
|
||||
specName: string
|
||||
}
|
||||
|
||||
const Diagram2CodeSpecs = ({ specName }: WorkflowReferenceProps) => {
|
||||
if (!Object.hasOwn(specs, specName)) {
|
||||
return <></>
|
||||
}
|
||||
const specsData: Diagram2CodeSpec = specs[specName]
|
||||
|
||||
const transformTitle = (title: string): string => {
|
||||
return title
|
||||
.split("-")
|
||||
.map((word) => `${word.charAt(0).toUpperCase()}${word.substring(1)}`)
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{!Object.keys(specsData).length && <span>No diagrams found</span>}
|
||||
{Object.entries(specsData).map(([name, diagram2code]) => (
|
||||
<React.Fragment key={name}>
|
||||
<h2>{transformTitle(name)}</h2>
|
||||
<Tabs groupId="workflows">
|
||||
<TabItem
|
||||
value="diagram"
|
||||
label="Diagram"
|
||||
default
|
||||
className="bg-diagrams bg-repeat rounded [&>div]:flex [&>div]:justify-center [&>div]:items-center"
|
||||
>
|
||||
<Mermaid value={diagram2code.diagram} />
|
||||
</TabItem>
|
||||
{diagram2code.code && (
|
||||
<TabItem value="code" label="Code">
|
||||
<CodeBlock language="ts">{diagram2code.code}</CodeBlock>
|
||||
</TabItem>
|
||||
)}
|
||||
</Tabs>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Diagram2CodeSpecs
|
||||
@@ -0,0 +1,119 @@
|
||||
import { exec } from "child_process"
|
||||
import { Dirent } from "fs"
|
||||
import { readdir, readFile, writeFile } from "fs/promises"
|
||||
import path from "path"
|
||||
|
||||
export default async function docusaurusPluginDiagram2codeShowcase(
|
||||
context,
|
||||
{ directoryPath, outputPath, debug = false }
|
||||
) {
|
||||
async function readIfExists(filePath) {
|
||||
try {
|
||||
return await readFile(filePath, "utf-8")
|
||||
} catch (e) {
|
||||
if (debug) {
|
||||
console.error(
|
||||
`[Diagram2Code Showcase Plugin] An error occurred while reading ${filePath}: ${e}`
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function generateSpecs() {
|
||||
let specs = {}
|
||||
let diagramSpecDirectories = []
|
||||
|
||||
try {
|
||||
// read files under the provided directory path
|
||||
diagramSpecDirectories = (
|
||||
await readdir(directoryPath, { withFileTypes: true })
|
||||
).filter((dirent) => dirent.isDirectory())
|
||||
} catch {
|
||||
console.error(
|
||||
`Directory ${directoryPath} doesn't exist. Skipping reading diagrams...`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
diagramSpecDirectories.map(async (dirent) => {
|
||||
const tempSpecs = {}
|
||||
const specsPath = path.join(directoryPath, dirent.name)
|
||||
|
||||
const specDirents = (
|
||||
await readdir(specsPath, { withFileTypes: true })
|
||||
).filter((specDirent) => specDirent.isDirectory())
|
||||
await Promise.all(
|
||||
specDirents.map(async (specDirent) => {
|
||||
const specPath = path.join(specsPath, specDirent.name)
|
||||
// read the diagram and code files
|
||||
const diagram = await readIfExists(
|
||||
path.join(specPath, "diagram.mermaid")
|
||||
)
|
||||
const code =
|
||||
(await readIfExists(path.join(specPath, "code.ts"))) ||
|
||||
(await readIfExists(path.join(specPath, "code.tsx"))) ||
|
||||
(await readIfExists(path.join(specPath, "code.js")))
|
||||
|
||||
if (!diagram) {
|
||||
return
|
||||
}
|
||||
|
||||
tempSpecs[specDirent.name] = {
|
||||
diagram,
|
||||
code,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
if (Object.keys(tempSpecs).length) {
|
||||
specs[dirent.name] = tempSpecs
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// order steps alphabetically
|
||||
specs = Object.keys(specs)
|
||||
.sort()
|
||||
.reduce((accumulator, key) => {
|
||||
accumulator[key] = specs[key]
|
||||
|
||||
return accumulator
|
||||
}, {})
|
||||
|
||||
// store specs in a JavaScript object that can be consumed
|
||||
const specOutputFilePath = path.join(outputPath, "specs.ts")
|
||||
await writeFile(
|
||||
specOutputFilePath,
|
||||
`export const specs = ${JSON.stringify(specs, null, "\t")}`
|
||||
)
|
||||
|
||||
// execute eslint
|
||||
exec(`eslint ${specOutputFilePath} --fix`)
|
||||
|
||||
return specOutputFilePath
|
||||
}
|
||||
|
||||
return {
|
||||
name: "docusaurus-plugin-diagram2code-showcase",
|
||||
async loadContent() {
|
||||
await generateSpecs()
|
||||
},
|
||||
extendCli(cli) {
|
||||
cli
|
||||
.command("diagram2code:generate")
|
||||
.description(
|
||||
"Generate the spec file used to create diagram-to-code showcase"
|
||||
)
|
||||
.action(async () => {
|
||||
const specFile = await generateSpecs()
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Generated diagram2code spec file at ${specFile}`)
|
||||
})
|
||||
},
|
||||
getPathsToWatch() {
|
||||
return [directoryPath]
|
||||
},
|
||||
}
|
||||
}
|
||||
Vendored
+13
@@ -207,4 +207,17 @@ declare module "@medusajs/docs" {
|
||||
export declare type MedusaDocusaurusContext = DocusaurusContext & {
|
||||
siteConfig: MedusaDocusaurusConfig
|
||||
}
|
||||
|
||||
export declare type Diagram2Code = {
|
||||
diagram: string
|
||||
code: string
|
||||
}
|
||||
|
||||
export declare type Diagram2CodeSpec = {
|
||||
[k: string]: Diagram2Code
|
||||
}
|
||||
|
||||
export declare type Diagram2CodeSpecs = {
|
||||
[k: string]: Diagram2CodeSpec
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user