Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor so that the typedoc plugin can be used outside of unplugin #25

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions docs-app/ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ module.exports = async function (defaults) {
devtool: 'source-map',
plugins: [
createManifest({ src: 'public/docs' }),
apiDocs({ package: 'kolay' }),
apiDocs({ package: 'ember-primitives' }),
apiDocs({ package: 'ember-resources' }),
apiDocs({ packages: ['kolay', 'ember-primitives', 'ember-resources'] }),
],
},
},
Expand Down
58 changes: 58 additions & 0 deletions src/plugins/api-docs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { createUnplugin } from 'unplugin';

import { generateTypeDocJSON } from './typedoc.js';

/**
* Generates JSON from typedoc given a target path.
*
* May be used multiple times to generate multiple docs
* for multiple libraries
*
* example:
* ```js
* import { typedoc, helpers } from 'kolay';
*
* typedoc.webpack({
* dest: '/api-docs/ember-primitives.json
* entryPoints: [
* helpers.pkgGlob(
* require.resolve('ember-primitives'),
* 'declarations'
* )
* ]
* })
* ```
*/
export const apiDocs = createUnplugin(
/**
* @param {import('./types.ts').APIDocsOptions} options
*/
(options) => {
const name = 'kolay::typedoc';

return {
name,
/**
* 1. generate typedoc config
* 2. given the
*/
async buildEnd() {
await Promise.all(
options.packages.map(async (pkgName) => {
let data = await generateTypeDocJSON({ packageName: pkgName });

if (data) {
let dest = `${options.dest ?? 'docs'}/${pkgName}.json`;

this.emitFile({
type: 'asset',
fileName: dest,
source: JSON.stringify(data),
});
}
})
);
},
};
}
);
96 changes: 96 additions & 0 deletions src/plugins/api-docs/typedoc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import assert from 'node:assert';
import { writeFile } from 'node:fs/promises';
import { createRequire } from 'node:module';
import { join } from 'node:path';

import { globby } from 'globby';

import { packageTypes } from '../helpers.js';

const require = createRequire(import.meta.url);

/**
* @typedef {object} Options
* @property {string} packageName
*
* @param {Options} options
*/
export async function generateTypeDocJSON({ packageName }) {
/**
* all "types" from package.json#exports
*/
const typeInfo = await packageTypes(packageName);
const entries = typeInfo.types;

assert(
entries?.length,
`Could not find any types for ${packageName}. Make sure that the package.json specifies "types" entries in package.json#exports`
);

const resolvedEntries = await resolveFiles(typeInfo.dir, entries);
const absoluteResolved = resolvedEntries.map((entry) => join(typeInfo.dir, entry));

const typedoc = await import('typedoc');
const tmpTSConfigPath = `/tmp/kolay-typedoc-${packageName}.json`;
const extendsTsConfig = require.resolve('@tsconfig/ember/tsconfig.json');

const tsConfig = {
extends: extendsTsConfig,
include: [join(typeInfo.dir, '**/*')],
compilerOptions: {
baseUrl: typeInfo.dir,
noEmitOnError: false,
},
};

await writeFile(tmpTSConfigPath, JSON.stringify(tsConfig, null, 2));

const typedocApp = await typedoc.Application.bootstrapWithPlugins({
// entryPoints: resolvedEntries,
entryPoints: absoluteResolved,
tsconfig: tmpTSConfigPath,
basePath: typeInfo.dir,
cleanOutputDir: false,
includes: typeInfo.dir,
readme: '',
pretty: false,
excludeInternal: false,
skipErrorChecking: true,
plugin: ['@zamiell/typedoc-plugin-not-exported'],
});

const project = await typedocApp.convert();

if (project) {
let data = typedocApp.serializer.projectToObject(project, typeInfo.dir);

return data;
}

return;
}

/**
* Converts array of package.json#export types globs to
* a list of files that actually exist on disk.
*
* @param {string} dir
* @param {string[]} entries
*/
async function resolveFiles(dir, entries) {
let globbyGlobs = [];

for (let entry of entries) {
globbyGlobs.push(entry);

// exports * are expanded to **/*
// but we have to do it manually
if (entry.match(/[^*]\/\*\.d\.ts$/)) {
globbyGlobs.push(entry.replace('/*.d.ts', '/**/*.d.ts'));
}
}

let resolvedEntries = await globby(globbyGlobs, { cwd: dir });

return resolvedEntries;
}
12 changes: 12 additions & 0 deletions src/plugins/api-docs/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface APIDocsOptions {
/**
* List of packages to generate api docs for
*/
packages: string[];

/**
* Destination folder to place the api docs json files in.
* Defaults to "docs"
*/
dest?: string;
}
133 changes: 0 additions & 133 deletions src/plugins/typedoc.js

This file was deleted.

1 change: 1 addition & 0 deletions src/plugins/types.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export type { APIDocsOptions } from './api-docs/types.js';
export type { CreateManifestOptions } from './create-manifest/types.js';
2 changes: 1 addition & 1 deletion src/plugins/vite.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { apiDocs as unApiDocs } from './api-docs/index.js';
import { copyFile as unCopyFile } from './copy-file.js';
import { copyToPublic as unCopyToPublic } from './copy-to-public.js';
import { createManifest as unCreateManifest } from './create-manifest/index.js';
import { apiDocs as unApiDocs } from './typedoc.js';

export const copyFile = unCopyFile.vite;
export const copyToPublic = unCopyToPublic.vite;
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/webpack.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { apiDocs as unApiDocs } from './api-docs/index.js';
import { copyFile as unCopyFile } from './copy-file.js';
import { copyToPublic as unCopyToPublic } from './copy-to-public.js';
import { createManifest as unCreateManifest } from './create-manifest/index.js';
import { apiDocs as unApiDocs } from './typedoc.js';

export const copyFile = unCopyFile.webpack;
export const copyToPublic = unCopyToPublic.webpack;
Expand Down
Loading