diff --git a/src/compiler/docs/generate-doc-data.ts b/src/compiler/docs/generate-doc-data.ts index 7788e5fd582f..8246b809f138 100644 --- a/src/compiler/docs/generate-doc-data.ts +++ b/src/compiler/docs/generate-doc-data.ts @@ -377,7 +377,10 @@ export const getNameText = (name: string, tags: d.JsonDocsTag[]) => { * @returns the user generated content that occurs before {@link AUTO_GENERATE_COMMENT}. If no user generated content * exists, or if there was an issue reading the file, return `undefined` */ -const getUserReadmeContent = async (compilerCtx: d.CompilerCtx, readmePath: string): Promise => { +export const getUserReadmeContent = async ( + compilerCtx: d.CompilerCtx, + readmePath: string, +): Promise => { try { const existingContent = await compilerCtx.fs.readFile(readmePath); // subtract one to get everything up to, but not including the auto generated comment diff --git a/src/compiler/docs/readme/output-docs.ts b/src/compiler/docs/readme/output-docs.ts index 7b5962779efa..a1c7edcf095c 100644 --- a/src/compiler/docs/readme/output-docs.ts +++ b/src/compiler/docs/readme/output-docs.ts @@ -2,6 +2,7 @@ import { join, relative } from '@utils'; import type * as d from '../../../declarations'; import { AUTO_GENERATE_COMMENT } from '../constants'; +import { getUserReadmeContent } from '../generate-doc-data'; import { stylesToMarkdown } from './markdown-css-props'; import { depsToMarkdown } from './markdown-dependencies'; import { eventsToMarkdown } from './markdown-events'; @@ -12,6 +13,23 @@ import { propsToMarkdown } from './markdown-props'; import { slotsToMarkdown } from './markdown-slots'; import { usageToMarkdown } from './markdown-usage'; +/** + * Generate a README for a given component and write it to disk. + * + * Typically the README is going to be a 'sibling' to the component's source + * code (i.e. written to the same directory) but the user may also configure a + * custom output directory by setting {@link d.OutputTargetDocsReadme.dir}. + * + * Output readme files also include {@link AUTO_GENERATE_COMMENT}, and any + * text located _above_ that comment is preserved when the new readme is written + * to disk. + * + * @param config a validated Stencil config + * @param compilerCtx the current compiler context + * @param readmeOutputs docs-readme output targets + * @param docsData documentation data for the component of interest + * @param cmps metadata for all the components in the project + */ export const generateReadme = async ( config: d.ValidatedConfig, compilerCtx: d.CompilerCtx, @@ -25,10 +43,20 @@ export const generateReadme = async ( await Promise.all( readmeOutputs.map(async (readmeOutput) => { if (readmeOutput.dir) { - const readmeContent = generateMarkdown(userContent, docsData, cmps, readmeOutput); - const relPath = relative(config.srcDir, docsData.readmePath); - const absPath = join(readmeOutput.dir, relPath); - const results = await compilerCtx.fs.writeFile(absPath, readmeContent); + const relativeReadmePath = relative(config.srcDir, docsData.readmePath); + const readmeOutputPath = join(readmeOutput.dir, relativeReadmePath); + + const currentReadmeContent = + readmeOutput.dir !== config.srcDir + ? // The user set a custom `.dir` property, which is where we're going + // to write the updated README. We need to read the non-automatically + // generated content from that file and preserve that. + await getUserReadmeContent(compilerCtx, readmeOutputPath) + : userContent; + + const readmeContent = generateMarkdown(currentReadmeContent, docsData, cmps, readmeOutput); + + const results = await compilerCtx.fs.writeFile(readmeOutputPath, readmeContent); if (results.changedContent) { if (isUpdate) { config.logger.info(`updated readme docs: ${docsData.tag}`); @@ -42,7 +70,7 @@ export const generateReadme = async ( }; export const generateMarkdown = ( - userContent: string, + userContent: string | undefined, cmp: d.JsonDocsComponent, cmps: d.JsonDocsComponent[], readmeOutput: d.OutputTargetDocsReadme, @@ -50,7 +78,7 @@ export const generateMarkdown = ( //If the readmeOutput.dependencies is true or undefined the dependencies will be generated. const dependencies = readmeOutput.dependencies !== false ? depsToMarkdown(cmp, cmps) : []; return [ - userContent, + userContent || "", AUTO_GENERATE_COMMENT, '', '', @@ -78,6 +106,12 @@ const getDocsDeprecation = (cmp: d.JsonDocsComponent) => { return []; }; +/** + * Get a minimal default README for a Stencil component + * + * @param docsData documentation data for the component of interest + * @returns a minimal README template for that component + */ const getDefaultReadme = (docsData: d.JsonDocsComponent) => { return [`# ${docsData.tag}`, '', '', ''].join('\n'); }; diff --git a/src/declarations/stencil-public-compiler.ts b/src/declarations/stencil-public-compiler.ts index 1834c6faa5b1..7d1c3d0cd639 100644 --- a/src/declarations/stencil-public-compiler.ts +++ b/src/declarations/stencil-public-compiler.ts @@ -2266,6 +2266,11 @@ export interface OutputTargetDocsVscode extends OutputTargetBase { export interface OutputTargetDocsReadme extends OutputTargetBase { type: 'docs-readme'; + /** + * The root directory where README files should be written + * + * defaults to {@link Config.srcDir} + */ dir?: string; dependencies?: boolean; footer?: string; diff --git a/test/docs-json/custom-readme-output/components/my-component/readme.md b/test/docs-json/custom-readme-output/components/my-component/readme.md new file mode 100644 index 000000000000..98f5b774ffda --- /dev/null +++ b/test/docs-json/custom-readme-output/components/my-component/readme.md @@ -0,0 +1,31 @@ +This file is in a custom location, set with `.dir` on the `docs-readme` OT. + +The content here above the 'auto-generation' comment shouldn't be overwritten. + +This is a regression test for the issue reported in ionic-team/stencil#5400. + + + + +## Methods + +### `onDidDismiss(arg: T) => Promise>` + +A comment, which should be included, I should think! + +#### Parameters + +| Name | Type | Description | +| ----- | ---- | ----------- | +| `arg` | `T` | | + +#### Returns + +Type: `Promise>` + + + + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/test/docs-json/stencil.config.ts b/test/docs-json/stencil.config.ts index 33972dc86efc..bd5f99bfd44c 100644 --- a/test/docs-json/stencil.config.ts +++ b/test/docs-json/stencil.config.ts @@ -8,5 +8,9 @@ export const config: Config = { file: 'docs.json', supplementalPublicTypes: 'src/components/interfaces.ts', }, + { + type: 'docs-readme', + dir: 'custom-readme-output', + }, ], };