generate-docs.ts 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { readFileSync, writeFileSync } from 'fs';
  2. import path from 'path';
  3. import ts from 'typescript';
  4. const outputPath = path.join(__dirname, '../docs/content/docs/api');
  5. const vendureConfig = path.join(__dirname, '../server/src/config/vendure-config.ts');
  6. // Parse a file
  7. const sourceFile = ts.createSourceFile(
  8. vendureConfig,
  9. readFileSync(vendureConfig).toString(),
  10. ts.ScriptTarget.ES2015,
  11. true,
  12. );
  13. for (const statement of [...sourceFile.statements]) {
  14. if (ts.isInterfaceDeclaration(statement)) {
  15. const title = statement.name.text;
  16. const frontMatter = generateFrontMatter(statement);
  17. const body = generateInterfaceDocs(statement);
  18. const fileName = getGeneratedFileName(title);
  19. const contents = `${frontMatter}\n${body}`;
  20. writeFileSync(path.join(outputPath, fileName), contents);
  21. }
  22. }
  23. /**
  24. * Generates the body of a TypeScript interface documentation markdown file.
  25. */
  26. function generateInterfaceDocs(statement: ts.InterfaceDeclaration): string {
  27. let output = `## ${statement.name.text}\n\n`;
  28. for (const member of statement.members) {
  29. if (ts.isPropertySignature(member)) {
  30. let description = '';
  31. let type = '';
  32. let defaultVal = '';
  33. const jsDocTags = ts.getJSDocTags(member);
  34. for (const tag of jsDocTags) {
  35. if (tag.tagName.text === 'description') {
  36. description = tag.comment || '';
  37. }
  38. if (tag.tagName.text === 'example') {
  39. description += formatExampleCode(tag.comment);
  40. }
  41. if (tag.tagName.text === 'default') {
  42. defaultVal = tag.comment || '';
  43. }
  44. }
  45. if (member.type) {
  46. type = member.type.getFullText();
  47. }
  48. output += `### ${member.name.getText()}\n\n`;
  49. output += `{{< config-option type="${type}" default="${defaultVal}" >}}\n\n`;
  50. output += `${description}\n\n`;
  51. }
  52. }
  53. return output;
  54. }
  55. /**
  56. * Generates the Hugo front matter with the title of the document
  57. */
  58. function generateFrontMatter(statement: ts.InterfaceDeclaration): string {
  59. return `---
  60. title: "${statement.name.text}"
  61. weight: 0
  62. generated: true
  63. ---
  64. <!-- This file was generated from the Vendure TypeScript source. Do not modify. Instead, re-run "generate-docs" -->
  65. `;
  66. }
  67. /**
  68. * Cleans up a JSDoc "@example" block by removing leading whitespace and asterisk (TypeScript has an open issue
  69. * wherein the asterisks are not stripped as they should be, see https://github.com/Microsoft/TypeScript/issues/23517)
  70. */
  71. function formatExampleCode(example: string = ''): string {
  72. return '\n\n' + example.replace(/\n\s+\*\s/g, '');
  73. }
  74. /**
  75. * Generates a markdown filename from a normalized version of the title.
  76. */
  77. function getGeneratedFileName(title: string): string {
  78. return title.split(/(?=[A-Z])/).join('-').toLowerCase() + '.md';
  79. }