Kaynağa Gözat

docs(server): Add some docs about the docs

Michael Bromley 7 yıl önce
ebeveyn
işleme
01cc143352
2 değiştirilmiş dosya ile 39 ekleme ve 13 silme
  1. 27 13
      codegen/generate-docs.ts
  2. 12 0
      docs/README.md

+ 27 - 13
codegen/generate-docs.ts

@@ -40,25 +40,27 @@ type TypeMap = Map<string, string>;
 
 
 const docsPath = '/docs/api/';
 const docsPath = '/docs/api/';
 const outputPath = path.join(__dirname, '../docs/content/docs/api');
 const outputPath = path.join(__dirname, '../docs/content/docs/api');
-const vendureConfig = path.join(__dirname, '../server/src/config/vendure-config.ts');
+
+/**
+ * This map is used to cache types and their corresponding Hugo path. It is used to enable
+ * hyperlinking from a member's "type" to the definition of that type.
+ */
 const globalTypeMap: TypeMap = new Map();
 const globalTypeMap: TypeMap = new Map();
+
 const tsFiles = klawSync(path.join(__dirname, '../server/src/'), {
 const tsFiles = klawSync(path.join(__dirname, '../server/src/'), {
     nodir: true,
     nodir: true,
-    filter: item => {
-        return path.extname(item.path) === '.ts';
-    },
+    filter: item => path.extname(item.path) === '.ts',
     traverseAll: true,
     traverseAll: true,
 }).map(item => item.path);
 }).map(item => item.path);
 
 
 deleteGeneratedDocs();
 deleteGeneratedDocs();
-generateDocs(tsFiles, globalTypeMap);
-
+generateDocs(tsFiles, outputPath, globalTypeMap);
 const watchMode = !!process.argv.find(arg => arg === '--watch' || arg === '-w');
 const watchMode = !!process.argv.find(arg => arg === '--watch' || arg === '-w');
 if (watchMode) {
 if (watchMode) {
     console.log(`Watching for changes to source files...`);
     console.log(`Watching for changes to source files...`);
     tsFiles.forEach(file => {
     tsFiles.forEach(file => {
         fs.watchFile(file, {interval: 1000}, () => {
         fs.watchFile(file, {interval: 1000}, () => {
-            generateDocs([file], globalTypeMap);
+            generateDocs([file], outputPath, globalTypeMap);
         });
         });
     });
     });
 }
 }
@@ -86,7 +88,13 @@ function isGenerated(content: string) {
     return /generated\: true\n---\n/.test(content);
     return /generated\: true\n---\n/.test(content);
 }
 }
 
 
-function generateDocs(filePaths: string[], typeMap: TypeMap) {
+/**
+ * Uses the TypeScript compiler API to parse the given files and extract out the documentation
+ * into markdown files
+ * @param filePaths
+ * @param typeMap
+ */
+function generateDocs(filePaths: string[], hugoApiDocsPath: string, typeMap: TypeMap) {
     const timeStart = +new Date();
     const timeStart = +new Date();
     const sourceFiles = filePaths.map(filePath => {
     const sourceFiles = filePaths.map(filePath => {
         return ts.createSourceFile(
         return ts.createSourceFile(
@@ -111,7 +119,7 @@ function generateDocs(filePaths: string[], typeMap: TypeMap) {
 
 
     for (const info of interfaces) {
     for (const info of interfaces) {
         const markdown = renderInterface(info, typeMap);
         const markdown = renderInterface(info, typeMap);
-        const categoryDir = path.join(outputPath, info.category);
+        const categoryDir = path.join(hugoApiDocsPath, info.category);
         const indexFile = path.join(categoryDir, '_index.md');
         const indexFile = path.join(categoryDir, '_index.md');
         if (!fs.existsSync(categoryDir)) {
         if (!fs.existsSync(categoryDir)) {
             fs.mkdirSync(categoryDir);
             fs.mkdirSync(categoryDir);
@@ -121,7 +129,6 @@ function generateDocs(filePaths: string[], typeMap: TypeMap) {
             fs.writeFileSync(indexFile, indexFileContent);
             fs.writeFileSync(indexFile, indexFileContent);
         }
         }
 
 
-
         fs.writeFileSync(path.join(categoryDir, info.fileName + '.md'), markdown);
         fs.writeFileSync(path.join(categoryDir, info.fileName + '.md'), markdown);
     }
     }
 
 
@@ -252,10 +259,17 @@ function parseTags<T extends ts.Node>(node: T, tagMatcher: { [tagName: string]:
     }
     }
 }
 }
 
 
+/**
+ * This function takes a string representing a type (e.g. "Array<ShippingMethod>") and turns
+ * and known types (e.g. "ShippingMethod") into hyperlinks.
+ */
 function renderType(type: string, knownTypeMap: Map<string, string>): string {
 function renderType(type: string, knownTypeMap: Map<string, string>): string {
-    let typeText = type.trim().replace(/[\u00A0-\u9999<>\&]/gim, i => {
-        return '&#' + i.charCodeAt(0) + ';';
-    }).replace(/\n/, ' ');
+    let typeText = type.trim()
+        // encode HTML entities
+        .replace(/[\u00A0-\u9999<>\&]/gim, i => '&#' + i.charCodeAt(0) + ';')
+        // remove newlines
+        .replace(/\n/g, ' ');
+
     for (const [key, val] of knownTypeMap) {
     for (const [key, val] of knownTypeMap) {
         typeText = typeText.replace(key, `<a href='${docsPath}/${val}/'>${key}</a>`);
         typeText = typeText.replace(key, `<a href='${docsPath}/${val}/'>${key}</a>`);
     }
     }

+ 12 - 0
docs/README.md

@@ -3,3 +3,15 @@
 This is the source for the Vendure documentation website. Docs are written in markdown and the website is generated with [Hugo](https://gohugo.io).
 This is the source for the Vendure documentation website. Docs are written in markdown and the website is generated with [Hugo](https://gohugo.io).
 
 
 Currently requires the extended Hugo binary (for Sass support).
 Currently requires the extended Hugo binary (for Sass support).
+
+### API Docs Generation
+
+The API docs are generated from the TypeScript source files by running the "generate-docs" script:
+
+```bash
+yarn generate-docs [-w]
+```
+
+This script uses the TypeScript compiler API to traverse the server source code and extract data about the types as well as other information such as descriptions and default values.
+
+Currently, any `interface` which includes the JSDoc `@docCategory` tag will be extracted into a markdown file in the [content/docs/api](./content/docs/api) directory. Hugo can then build the API documentation from these markdown files. This will probably be expanded to be able to parse `class` and `type` declarations too.