@ankhorage/paradox 0.1.20 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +18 -7
- package/dist/analyze/analyze.js +5 -0
- package/dist/analyze/components.js +1 -1
- package/dist/analyze/types.d.ts +4 -0
- package/dist/analyze/utils/getPropsFromType.d.ts +1 -1
- package/dist/analyze/utils/getPropsFromType.js +2 -2
- package/dist/config/types.d.ts +5 -0
- package/dist/config/utils/validateDonationAccount.d.ts +1 -0
- package/dist/config/utils/validateDonationAccount.js +7 -0
- package/dist/model/buildModel.d.ts +3 -0
- package/dist/model/buildModel.js +1 -0
- package/dist/model/types.d.ts +4 -0
- package/dist/render/render.js +4 -0
- package/dist/render/renderers/donation.d.ts +2 -0
- package/dist/render/renderers/donation.js +30 -0
- package/dist/render/renderers/funding.d.ts +2 -0
- package/dist/render/renderers/funding.js +9 -0
- package/dist/render/types.d.ts +1 -0
- package/dist/write/utils/syncFundingFileAsync.d.ts +1 -0
- package/dist/write/utils/syncFundingFileAsync.js +30 -0
- package/dist/write/write.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.22
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 125eac9: Add opt-in GitHub Sponsors support from a single root-level `donation.account` config, including generated Donation documentation and `.github/FUNDING.yml` handling.
|
|
8
|
+
|
|
9
|
+
## 0.1.21
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- b7cd8b9: Normalize package-local absolute import types emitted through React component prop analysis by carrying the analyzed package root into the existing type-text normalizer.
|
|
14
|
+
|
|
3
15
|
## 0.1.20
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/paradox
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Deterministic documentation generator for TypeScript packages.
|
|
9
9
|
|
|
@@ -70,6 +70,10 @@ import { defineParadoxConfig } from './src/config/defineParadoxConfig.js';
|
|
|
70
70
|
export default defineParadoxConfig({
|
|
71
71
|
mode: 'write',
|
|
72
72
|
|
|
73
|
+
donation: {
|
|
74
|
+
account: 'ankhorage',
|
|
75
|
+
},
|
|
76
|
+
|
|
73
77
|
docs: {
|
|
74
78
|
title: '@ankhorage/paradox',
|
|
75
79
|
description: 'Deterministic documentation generator for TypeScript packages.',
|
|
@@ -88,12 +92,13 @@ export default defineParadoxConfig({
|
|
|
88
92
|
<details>
|
|
89
93
|
<summary>Configuration options</summary>
|
|
90
94
|
|
|
91
|
-
| Field
|
|
92
|
-
|
|
|
93
|
-
| mode
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
95
|
+
| Field | Type | Required | Default | Description |
|
|
96
|
+
| -------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------- |
|
|
97
|
+
| mode | `'safe' \| 'write' \| undefined` | no | — | |
|
|
98
|
+
| donation | `{ account: string; } \| undefined` | no | — | |
|
|
99
|
+
| docs | `{ title?: string; description?: string; usage?: { description?: string; entrypoints?: string[]; }; } \| undefined` | no | — | |
|
|
100
|
+
| package | `{ root?: string; entrypoints?: string[]; } \| undefined` | no | — | |
|
|
101
|
+
| output | `{ dir?: string; } \| undefined` | no | — | |
|
|
97
102
|
|
|
98
103
|
</details>
|
|
99
104
|
|
|
@@ -136,3 +141,9 @@ Module: `src/config/types.ts`
|
|
|
136
141
|
Source: `src/config/types.ts:7:1`
|
|
137
142
|
|
|
138
143
|
</details>
|
|
144
|
+
|
|
145
|
+
## Donation
|
|
146
|
+
|
|
147
|
+
If this project is useful to you, you can support its continued development.
|
|
148
|
+
|
|
149
|
+
[Support @ankhorage](https://github.com/sponsors/ankhorage)
|
package/dist/analyze/analyze.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { validateDonationAccount } from '../config/utils/validateDonationAccount.js';
|
|
3
4
|
import { analyzeBadges } from './badges.js';
|
|
4
5
|
import { analyzeComponents } from './components.js';
|
|
5
6
|
import { analyzeExports } from './exports.js';
|
|
@@ -20,6 +21,9 @@ import { createUsageFromPackageJson } from './usage.js';
|
|
|
20
21
|
export async function analyze(config, runtime) {
|
|
21
22
|
const root = runtime.packageRoot;
|
|
22
23
|
const pkg = await readPackageJson(root);
|
|
24
|
+
const donation = config.donation === undefined
|
|
25
|
+
? null
|
|
26
|
+
: { account: validateDonationAccount(config.donation.account) };
|
|
23
27
|
const usage = createUsageFromPackageJson(pkg);
|
|
24
28
|
const badges = await analyzeBadges(root, pkg);
|
|
25
29
|
const project = createProject(root);
|
|
@@ -67,6 +71,7 @@ export async function analyze(config, runtime) {
|
|
|
67
71
|
packageName: config.docs?.title ?? pkg.name,
|
|
68
72
|
packageId: pkg.name,
|
|
69
73
|
description: config.docs?.description ?? pkg.description ?? null,
|
|
74
|
+
donation,
|
|
70
75
|
exports,
|
|
71
76
|
components,
|
|
72
77
|
sourceFunctions,
|
|
@@ -21,7 +21,7 @@ export function analyzeComponents(exports, options = {}) {
|
|
|
21
21
|
description: member.description ?? null,
|
|
22
22
|
})) ?? [];
|
|
23
23
|
const propsType = getComponentPropsType(e.node);
|
|
24
|
-
const legacyProps = propsType != null ? getPropsFromType(propsType) : [];
|
|
24
|
+
const legacyProps = propsType != null ? getPropsFromType(propsType, options.program?.root) : [];
|
|
25
25
|
const props = analyzerProps.length > 0 ? analyzerProps : legacyProps;
|
|
26
26
|
components.push({
|
|
27
27
|
name: e.name,
|
package/dist/analyze/types.d.ts
CHANGED
|
@@ -75,6 +75,9 @@ export interface AnalysisUsage {
|
|
|
75
75
|
packageName: string;
|
|
76
76
|
commands: AnalysisUsageCommand[];
|
|
77
77
|
}
|
|
78
|
+
interface AnalysisDonation {
|
|
79
|
+
account: string;
|
|
80
|
+
}
|
|
78
81
|
interface AnalysisUsageCommand {
|
|
79
82
|
name: string;
|
|
80
83
|
command: string;
|
|
@@ -165,6 +168,7 @@ export interface AnalysisResult {
|
|
|
165
168
|
packageName: string;
|
|
166
169
|
packageId: string;
|
|
167
170
|
description: string | null;
|
|
171
|
+
donation: AnalysisDonation | null;
|
|
168
172
|
exports: AnalysisExport[];
|
|
169
173
|
components: AnalysisComponent[];
|
|
170
174
|
sourceFunctions: AnalysisSourceFunction[];
|
|
@@ -3,4 +3,4 @@ import type { AnalysisComponent } from '../types.js';
|
|
|
3
3
|
/***
|
|
4
4
|
* Extracts prop names, types, required flags, and descriptions from a type.
|
|
5
5
|
*/
|
|
6
|
-
export declare function getPropsFromType(type: Type): AnalysisComponent['props'];
|
|
6
|
+
export declare function getPropsFromType(type: Type, packageRoot?: string): AnalysisComponent['props'];
|
|
@@ -4,7 +4,7 @@ import { parseParadoxComment } from './parseParadoxComment.js';
|
|
|
4
4
|
/***
|
|
5
5
|
* Extracts prop names, types, required flags, and descriptions from a type.
|
|
6
6
|
*/
|
|
7
|
-
export function getPropsFromType(type) {
|
|
7
|
+
export function getPropsFromType(type, packageRoot) {
|
|
8
8
|
return type.getProperties().map((property) => {
|
|
9
9
|
const [declaration] = property.getDeclarations();
|
|
10
10
|
const propertyType = property.getTypeAtLocation(declaration);
|
|
@@ -14,7 +14,7 @@ export function getPropsFromType(type) {
|
|
|
14
14
|
: { description: null, isConfig: false, params: {}, returns: null };
|
|
15
15
|
return {
|
|
16
16
|
name: property.getName(),
|
|
17
|
-
type: normalizeTypeText(propertyType.getText(declaration)),
|
|
17
|
+
type: normalizeTypeText(propertyType.getText(declaration), packageRoot),
|
|
18
18
|
required: !property.isOptional(),
|
|
19
19
|
description: parsed.description,
|
|
20
20
|
};
|
package/dist/config/types.d.ts
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export interface ParadoxConfig {
|
|
8
8
|
mode?: 'safe' | 'write';
|
|
9
|
+
/** Enables canonical GitHub Sponsors integration for generated repository documentation. */
|
|
10
|
+
donation?: {
|
|
11
|
+
/** GitHub Sponsors account login used for the Sponsor button and Donation chapter. */
|
|
12
|
+
account: string;
|
|
13
|
+
};
|
|
9
14
|
docs?: {
|
|
10
15
|
title?: string;
|
|
11
16
|
description?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function validateDonationAccount(account: string): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function validateDonationAccount(account) {
|
|
2
|
+
if (!githubAccountPattern.test(account)) {
|
|
3
|
+
throw new Error(`Invalid donation account "${account}". Expected a GitHub account login containing only alphanumeric characters or single hyphens.`);
|
|
4
|
+
}
|
|
5
|
+
return account;
|
|
6
|
+
}
|
|
7
|
+
const githubAccountPattern = /^(?!-)(?!.*--)[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
|
package/dist/model/buildModel.js
CHANGED
|
@@ -9,6 +9,7 @@ export function buildModel(analysis) {
|
|
|
9
9
|
packageName: analysis.packageName,
|
|
10
10
|
packageId: analysis.packageId,
|
|
11
11
|
description: analysis.description,
|
|
12
|
+
donation: analysis.donation === null ? null : { account: analysis.donation.account },
|
|
12
13
|
badges: analysis.badges.map((badge) => ({
|
|
13
14
|
id: badge.id,
|
|
14
15
|
label: badge.label,
|
package/dist/model/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface DocumentationModel {
|
|
|
5
5
|
packageName: string;
|
|
6
6
|
packageId: string;
|
|
7
7
|
description: string | null;
|
|
8
|
+
donation: DonationModel | null;
|
|
8
9
|
badges: GeneratedBadge[];
|
|
9
10
|
usage: UsageModel | null;
|
|
10
11
|
readmeUsageDescription: string | null;
|
|
@@ -20,6 +21,9 @@ export interface DocumentationModel {
|
|
|
20
21
|
sequenceScenarios: SequenceScenarioModel[];
|
|
21
22
|
graphs: GraphModel;
|
|
22
23
|
}
|
|
24
|
+
interface DonationModel {
|
|
25
|
+
account: string;
|
|
26
|
+
}
|
|
23
27
|
export interface GeneratedBadge {
|
|
24
28
|
id: string;
|
|
25
29
|
label: string;
|
package/dist/render/render.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { renderBadgeArtifacts } from './renderers/badges.js';
|
|
2
2
|
import { renderDiagramArtifacts } from './renderers/diagrams.js';
|
|
3
|
+
import { renderDonation } from './renderers/donation.js';
|
|
4
|
+
import { renderFundingYaml } from './renderers/funding.js';
|
|
3
5
|
import { renderHtml } from './renderers/html.js';
|
|
4
6
|
import { renderMarkdown } from './renderers/markdown.js';
|
|
5
7
|
/***
|
|
@@ -16,6 +18,7 @@ export function render(model, options = {}) {
|
|
|
16
18
|
exportsJson: `${JSON.stringify(model.exports, null, 2)}\n`,
|
|
17
19
|
paradoxJson: `${JSON.stringify(model, null, 2)}\n`,
|
|
18
20
|
indexHtml: '',
|
|
21
|
+
fundingYaml: renderFundingYaml(model),
|
|
19
22
|
badges,
|
|
20
23
|
diagrams,
|
|
21
24
|
};
|
|
@@ -29,5 +32,6 @@ export function render(model, options = {}) {
|
|
|
29
32
|
for (const renderer of [renderMarkdown, renderHtml]) {
|
|
30
33
|
Object.assign(result, renderer(context));
|
|
31
34
|
}
|
|
35
|
+
Object.assign(result, renderDonation(context));
|
|
32
36
|
return result;
|
|
33
37
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function renderDonation(context) {
|
|
2
|
+
const { donation } = context.model;
|
|
3
|
+
if (donation === null) {
|
|
4
|
+
return { indexHtml: context.result.indexHtml, readme: context.result.readme };
|
|
5
|
+
}
|
|
6
|
+
const { account } = donation;
|
|
7
|
+
return {
|
|
8
|
+
readme: renderDonationReadme(context.result.readme, account),
|
|
9
|
+
indexHtml: renderDonationHtml(context.result.indexHtml, account),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function renderDonationHtml(indexHtml, account) {
|
|
13
|
+
const mainEnd = indexHtml.indexOf('\n </main>');
|
|
14
|
+
const homeStart = indexHtml.indexOf('<section id="view-home"');
|
|
15
|
+
const homeEnd = indexHtml.lastIndexOf('\n </section>', mainEnd);
|
|
16
|
+
if (mainEnd < 0 || homeStart < 0 || homeEnd < homeStart) {
|
|
17
|
+
throw new Error('Unable to locate Paradox HTML home view for Donation rendering.');
|
|
18
|
+
}
|
|
19
|
+
const panel = [
|
|
20
|
+
' <section class="panel" data-search="donation sponsor support">',
|
|
21
|
+
' <h2>Donation</h2>',
|
|
22
|
+
' <p>If this project is useful to you, you can support its continued development.</p>',
|
|
23
|
+
` <p><a href="https://github.com/sponsors/${account}">Support @${account}</a></p>`,
|
|
24
|
+
' </section>',
|
|
25
|
+
].join('\n');
|
|
26
|
+
return `${indexHtml.slice(0, homeEnd)}\n${panel}${indexHtml.slice(homeEnd)}`;
|
|
27
|
+
}
|
|
28
|
+
function renderDonationReadme(readme, account) {
|
|
29
|
+
return `${readme.trimEnd()}\n\n## Donation\n\nIf this project is useful to you, you can support its continued development.\n\n[Support @${account}](https://github.com/sponsors/${account})\n`;
|
|
30
|
+
}
|
package/dist/render/types.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function syncFundingFileAsync(packageRoot: string, fundingYaml: string | null): Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
export async function syncFundingFileAsync(packageRoot, fundingYaml) {
|
|
4
|
+
const fundingPath = join(packageRoot, '.github', 'FUNDING.yml');
|
|
5
|
+
const existing = await readFundingFileAsync(fundingPath);
|
|
6
|
+
if (fundingYaml === null) {
|
|
7
|
+
if (existing !== null && isParadoxOwnedFunding(existing))
|
|
8
|
+
await unlink(fundingPath);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (existing !== null && !isParadoxOwnedFunding(existing)) {
|
|
12
|
+
throw new Error('Refusing to overwrite existing non-Paradox .github/FUNDING.yml.');
|
|
13
|
+
}
|
|
14
|
+
await mkdir(dirname(fundingPath), { recursive: true });
|
|
15
|
+
await writeFile(fundingPath, fundingYaml);
|
|
16
|
+
}
|
|
17
|
+
const generatedFundingMarker = '# Generated by Paradox. Do not edit manually.';
|
|
18
|
+
function isParadoxOwnedFunding(content) {
|
|
19
|
+
return content.startsWith(`${generatedFundingMarker}\n`);
|
|
20
|
+
}
|
|
21
|
+
async function readFundingFileAsync(path) {
|
|
22
|
+
try {
|
|
23
|
+
return await readFile(path, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
|
|
27
|
+
return null;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
package/dist/write/write.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
|
+
import { syncFundingFileAsync } from './utils/syncFundingFileAsync.js';
|
|
3
4
|
/***
|
|
4
5
|
* Writes generated documentation artifacts to the configured output paths.
|
|
5
6
|
*/
|
|
@@ -25,5 +26,6 @@ export async function write(result, config, runtime) {
|
|
|
25
26
|
}
|
|
26
27
|
if (mode === 'write') {
|
|
27
28
|
await writeFile(join(root, 'README.md'), result.readme);
|
|
29
|
+
await syncFundingFileAsync(root, result.fundingYaml);
|
|
28
30
|
}
|
|
29
31
|
}
|