Design system.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

133 rindas
4.0 KiB

  1. import { readFile } from 'fs/promises';
  2. import { dirname, basename, resolve } from 'path';
  3. import { glob } from 'glob';
  4. import { minimatch } from 'minimatch';
  5. export interface AmanuensisConfig {
  6. package: {
  7. searchPatterns: string | string[];
  8. classifications: Record<string, Record<string, string | string[]>>;
  9. }
  10. }
  11. interface TypedocDataTextNode {
  12. kind: 'text';
  13. text: string;
  14. }
  15. interface TypedocDataInlineTagNode {
  16. kind: 'inline-tag';
  17. tag: string;
  18. text: string;
  19. target: number;
  20. tsLinkText: string;
  21. }
  22. interface SymbolIdMapEntry {
  23. sourceFileName: string;
  24. qualifiedName: string;
  25. }
  26. type TypedocDataNode = TypedocDataTextNode | TypedocDataInlineTagNode;
  27. export interface TypedocData {
  28. readme: TypedocDataNode[];
  29. symbolIdMap: Record<string, SymbolIdMapEntry>;
  30. }
  31. export interface PackageData {
  32. name: string;
  33. packageJson: Record<string, unknown>;
  34. basePath: string;
  35. markdown: { name: string; filePath: string; content: string }[];
  36. classifications: Record<string, string | undefined>;
  37. }
  38. export const getPackages = async (configPath: string, cwd: string): Promise<PackageData[]> => {
  39. const configString = await readFile(configPath, 'utf-8');
  40. const config = JSON.parse(configString) as AmanuensisConfig;
  41. const searchPatternsRaw = config.package.searchPatterns;
  42. const searchPatterns = Array.isArray(searchPatternsRaw) ? searchPatternsRaw : [searchPatternsRaw];
  43. const patternPackagePaths = await Promise.all(
  44. searchPatterns.map(async (searchPattern) => glob(
  45. searchPattern === 'package.json' || searchPattern.endsWith('/package.json')
  46. ? searchPattern
  47. : `${searchPattern}/package.json`,
  48. {
  49. cwd,
  50. ignore: ['**/node_modules/**'],
  51. },
  52. )),
  53. );
  54. const packagePaths = patternPackagePaths.flat();
  55. const markdownFilePathsRaw = await glob(
  56. '**/*.{md,mdx}',
  57. {
  58. cwd,
  59. ignore: ['**/node_modules/**'],
  60. },
  61. );
  62. const markdownFilePaths = markdownFilePathsRaw.map((p) => resolve(cwd, p));
  63. const readPackages = await Promise.all(
  64. packagePaths.map(async (packagePathRaw) => {
  65. const absolutePackagePath = resolve(cwd, packagePathRaw);
  66. const packageString = await readFile(absolutePackagePath, 'utf-8');
  67. const basePath = dirname(absolutePackagePath);
  68. const packageJson = JSON.parse(packageString) as { name: string };
  69. const classifications = Object.fromEntries(
  70. Object.entries(config.package.classifications)
  71. .map(([classification, c]) => {
  72. const [thisClassifications] = Object.entries(c)
  73. .find(([, globRaw]) => {
  74. const globs = Array.isArray(globRaw) ? globRaw : [globRaw];
  75. return globs.some((g) => minimatch(packageJson.name, g));
  76. }) ?? [];
  77. return [classification, thisClassifications] as const;
  78. }),
  79. );
  80. const markdownFiles = markdownFilePaths.filter((markdownFilePath) => (
  81. markdownFilePath.startsWith(basePath)
  82. ));
  83. const markdown = await Promise.all(
  84. markdownFiles.map(async (markdownFilePath) => {
  85. const content = await readFile(markdownFilePath, 'utf-8');
  86. const filePath = markdownFilePath.slice(basePath.length + 1);
  87. const file = filePath.split('/').at(-1) ?? '';
  88. const name = filePath === 'README.md' ? 'index.md' : basename(file);
  89. return {
  90. name,
  91. filePath,
  92. content,
  93. };
  94. }),
  95. );
  96. return {
  97. name: packageJson.name,
  98. packageJson,
  99. basePath: basePath.slice(cwd.length + 1),
  100. markdown,
  101. classifications,
  102. };
  103. }),
  104. );
  105. return readPackages.sort((a, b) => a.name.localeCompare(b.name));
  106. };
  107. export const getFileSources = async (cwd = process.cwd()) => {
  108. const typedocDataJsonPath = resolve(cwd, '.amanuensis', 'data.json');
  109. const typedocDataJson = await readFile(typedocDataJsonPath, 'utf-8');
  110. const typedocData = JSON.parse(typedocDataJson) as TypedocData;
  111. const symbolIdMapEntries = Object.values(typedocData.symbolIdMap);
  112. const firstPartySources = symbolIdMapEntries.filter(
  113. ({ sourceFileName }) => !sourceFileName.startsWith('node_modules'),
  114. );
  115. const firstPartySourceFiles = firstPartySources.map(({ sourceFileName }) => sourceFileName);
  116. return Array.from(new Set(firstPartySourceFiles));
  117. };