diff --git a/packages/__docs__/buildScripts/build-docs.mts b/packages/__docs__/buildScripts/build-docs.mts index 155f121db0..16236802cd 100644 --- a/packages/__docs__/buildScripts/build-docs.mts +++ b/packages/__docs__/buildScripts/build-docs.mts @@ -105,6 +105,9 @@ const pathsToIgnore = [ '**/ui-theme-tokens/**', '**/ui-test-*/src/**', '**/ui-scripts/src/**', + // ui-web-core ships Lit Web Components with their own embedded Storybook at + // /parchment; the React docs builder's per-component shape doesn't apply. + '**/ui-web-core/**', // large generated files: '**/lucide/**', // Lucide icons directory (large generated file) diff --git a/packages/__docs__/buildScripts/build-storybooks.mts b/packages/__docs__/buildScripts/build-storybooks.mts new file mode 100644 index 0000000000..41a65a8756 --- /dev/null +++ b/packages/__docs__/buildScripts/build-storybooks.mts @@ -0,0 +1,92 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Builds the ui-web-core (Lit + Web Components) Storybook and copies its + * static output to packages/__docs__/__build__/storybook/parchment/, so the + * docs app can iframe it at the `/parchment` route. + * + * Dev workflow is unaffected: `pnpm --filter @instructure/ui-web-core + * storybook` runs at port 6006 for live development. + */ + +import { spawnSync } from 'child_process' +import fs from 'fs' +import path from 'path' +import { fileURLToPath } from 'url' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +const projectRoot = path.resolve(__dirname, '../../../') +const docsBuildDir = path.resolve(__dirname, '../__build__') +const storybookOutDir = path.join(docsBuildDir, 'storybook') + +const packages = [ + { + name: '@instructure/ui-web-core', + dir: 'ui-web-core', + mountAs: 'parchment' + } +] + +function runBuildStorybook(packageName: string): void { + // eslint-disable-next-line no-console + console.log(`Building Storybook: ${packageName}`) + const result = spawnSync( + 'pnpm', + ['--filter', packageName, 'build-storybook'], + { cwd: projectRoot, stdio: 'inherit' } + ) + if (result.status !== 0) { + throw new Error( + `build-storybook failed for ${packageName} (exit ${result.status})` + ) + } +} + +function copyStorybookOutput(packageDir: string, mountAs: string): void { + const src = path.join(projectRoot, 'packages', packageDir, 'storybook-static') + const dest = path.join(storybookOutDir, mountAs) + if (!fs.existsSync(src)) { + throw new Error(`Expected Storybook output at ${src}`) + } + fs.rmSync(dest, { recursive: true, force: true }) + fs.mkdirSync(dest, { recursive: true }) + fs.cpSync(src, dest, { recursive: true }) + // eslint-disable-next-line no-console + console.log(`Copied ${src} -> ${dest}`) +} + +function main(): void { + fs.mkdirSync(storybookOutDir, { recursive: true }) + for (const pkg of packages) { + runBuildStorybook(pkg.name) + copyStorybookOutput(pkg.dir, pkg.mountAs) + } + // eslint-disable-next-line no-console + console.log('Storybook(s) built and copied under', storybookOutDir) +} + +main() diff --git a/packages/__docs__/package.json b/packages/__docs__/package.json index b481a7ba27..2161c24eb3 100644 --- a/packages/__docs__/package.json +++ b/packages/__docs__/package.json @@ -16,7 +16,8 @@ "start:watch": "pnpm run prestart && concurrently -n markdown,webpack -c cyan,yellow \"node buildScripts/watch-markdown.mjs\" \"ui-scripts bundle --watch\"", "start-watch-just-app": "ui-scripts bundle --watch", "watch:markdown": "node buildScripts/watch-markdown.mjs", - "bundle": "pnpm run prestart && ui-scripts bundle", + "build:storybooks": "pnpm run build:scripts:ts && node lib/build-storybooks.mjs", + "bundle": "pnpm run prestart && pnpm run build:storybooks && ui-scripts bundle", "lint": "ui-scripts lint", "lint:fix": "ui-scripts lint --fix", "build:scripts:ts": "tsc -b tsconfig.node.build.json", diff --git a/packages/__docs__/src/App/index.tsx b/packages/__docs__/src/App/index.tsx index da4a7589d4..4e0342bbf6 100644 --- a/packages/__docs__/src/App/index.tsx +++ b/packages/__docs__/src/App/index.tsx @@ -650,6 +650,29 @@ class App extends Component { return
{this.renderWrappedContent(iconContent)}
} + renderParchmentStorybook(key: string) { + // The ui-web-core Storybook (Lit + Web Components) is built by the docs + // app's `build:storybooks` script and copied to + // `__build__/storybook/parchment/` during `bundle`. If that step hasn't + // run locally (e.g. `pnpm run dev`), the iframe will 404 — expected for + // the unbundled dev path. + const src = `${getDeployBase()}/storybook/parchment/` + const content = ( + +