Skip to content

Commit 0c96bb2

Browse files
committed
fix more tests
1 parent 6767f01 commit 0c96bb2

File tree

12 files changed

+246
-42
lines changed

12 files changed

+246
-42
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
layout: default
3+
title: Markdown Generator
4+
parent: API Reference
5+
nav_order: 2
6+
---
7+
8+
# MarkdownGenerator API
9+
10+
The `MarkdownGenerator` class generates Markdown documentation from a parsed API/type definition object, such as the output of your Lua/Luau parser or a custom API description.
11+
12+
---
13+
14+
## Installation
15+
16+
The Markdown generator is included in LuaTS. Import it as follows:
17+
18+
```typescript
19+
import { MarkdownGenerator } from 'luats/dist/generators/markdown/generator';
20+
```
21+
22+
---
23+
24+
## Usage
25+
26+
### Basic Example
27+
28+
```typescript
29+
import { MarkdownGenerator } from 'luats/dist/generators/markdown/generator';
30+
31+
const apiObject = {
32+
name: "My API",
33+
description: "This is an example API.",
34+
functions: [
35+
{
36+
name: "foo",
37+
description: "Does foo things.",
38+
signature: "function foo(bar: string): number",
39+
parameters: [
40+
{ name: "bar", type: "string", description: "The bar argument." }
41+
],
42+
returns: { type: "number", description: "The result." }
43+
}
44+
],
45+
types: [
46+
{
47+
name: "FooType",
48+
description: "A type for foo.",
49+
definition: "type FooType = { bar: string }"
50+
}
51+
],
52+
examples: [
53+
{
54+
title: "Basic usage",
55+
description: "How to use foo.",
56+
code: "foo('hello')"
57+
}
58+
]
59+
};
60+
61+
const generator = new MarkdownGenerator({ title: "API Reference" });
62+
const markdown = generator.generate(apiObject);
63+
64+
console.log(markdown);
65+
```
66+
67+
---
68+
69+
## Options
70+
71+
| Option | Type | Description |
72+
|------------------|-----------|------------------------------------------------------------------|
73+
| `title` | `string` | Title for the generated Markdown (overrides `api.name`) |
74+
| `description` | `string` | Description for the Markdown (overrides `api.description`) |
75+
| `includeTypes` | `boolean` | Whether to include the Types section (default: `true`) |
76+
| `includeExamples`| `boolean` | Whether to include the Examples section (default: `true`) |
77+
78+
---
79+
80+
## API Object Structure
81+
82+
- `name`: (string) Name of the API/module.
83+
- `description`: (string) Description of the API/module.
84+
- `functions`: (array) List of function objects.
85+
- `name`: (string) Function name.
86+
- `description`: (string) Function description.
87+
- `signature`: (string, optional) Function signature (if omitted, generated from parameters).
88+
- `parameters`: (array) List of parameter objects:
89+
- `name`: (string) Parameter name.
90+
- `type`: (string) Parameter type.
91+
- `description`: (string, optional) Parameter description.
92+
- `returns`: (object, optional)
93+
- `type`: (string) Return type.
94+
- `description`: (string, optional) Return description.
95+
- `types`: (array) List of type objects.
96+
- `name`: (string) Type name.
97+
- `description`: (string, optional) Type description.
98+
- `definition`: (string) Type definition (as Lua/Luau code).
99+
- `examples`: (array) List of example objects.
100+
- `title`: (string, optional) Example title.
101+
- `description`: (string, optional) Example description.
102+
- `code`: (string) Example code (Lua/Luau).
103+
104+
---
105+
106+
## Output Format
107+
108+
The generated Markdown includes:
109+
110+
- Title and description
111+
- Table of Contents
112+
- Functions section (with signatures, parameters, and return types)
113+
- Types section (with code blocks)
114+
- Examples section (with code blocks)
115+
116+
---
117+
118+
## Advanced
119+
120+
- You can customize the API object structure to fit your needs, as long as you provide the required fields.
121+
- The generator is designed to work with the output of the LuaTS parser, but you can use it with any compatible object.
122+
123+
---
124+
125+
## See Also
126+
127+
- [LuaTS TypeScript Generator](./api-typescript-generator.md)
128+
- [API Reference](./api-reference.md)

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@
5757
"lint:fix": "eslint src/**/*.ts --fix",
5858
"format": "prettier --write src/**/*.ts",
5959
"prepublishOnly": "bun run build",
60-
"test:report": "bun run ./scripts/test-report.ts",
61-
"test:coverage": "bun test --reporter=junit --reporter-outfile=./test/junit.xml"
60+
"test": "bun test",
61+
"test:report": "bun test --reporter=junit --reporter-outfile=./test/junit.xml && bun run scripts/test-report-junit.ts",
62+
"test:coverage": "bun test --coverage --reporter=junit --reporter-outfile=./test/junit.xml && bun run scripts/test-report-junit.ts"
6263
},
6364
"keywords": [
6465
"lua",

src/cli/config.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,16 @@ export interface LuatsConfig {
3535
inferTypes?: boolean;
3636
strictNullChecks?: boolean;
3737
robloxTypes?: boolean;
38+
useUnknown?: boolean;
39+
interfacePrefix?: string;
40+
semicolons?: boolean;
41+
generateComments?: boolean; // Add explicit option
3842
};
3943

44+
// Comment preservation settings
45+
preserveComments?: boolean;
46+
commentStyle?: 'jsdoc' | 'inline';
47+
4048
// Plugin configuration
4149
plugins?: string[];
4250

@@ -70,9 +78,15 @@ export const defaultConfig: LuatsConfig = {
7078
moduleType: 'esm',
7179
inferTypes: true,
7280
strictNullChecks: true,
73-
robloxTypes: false
81+
robloxTypes: false,
82+
generateComments: true, // Enable by default
83+
useUnknown: false,
84+
semicolons: true
7485
},
7586

87+
preserveComments: true, // Enable by default
88+
commentStyle: 'jsdoc',
89+
7690
plugins: [],
7791

7892
verbose: false,

src/cli/processor.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ export async function processFile(
1616
// Read the input file
1717
const luaCode = fs.readFileSync(inputPath, 'utf-8');
1818

19-
// Generate TypeScript code
20-
const tsCode = await generateTypeScript(luaCode, config);
19+
// Generate TypeScript code with proper options
20+
const tsCode = await generateTypeScript(luaCode, {
21+
...config.typeGeneratorOptions,
22+
// Fix: Pass the properties directly from typeGeneratorOptions or use defaults
23+
preserveComments: config.preserveComments ?? true,
24+
commentStyle: config.commentStyle ?? 'jsdoc'
25+
});
2126

2227
// Ensure output directory exists
2328
const outputDir = path.dirname(outputPath);
@@ -78,8 +83,14 @@ export async function processDirectory(
7883
*/
7984
async function generateTypeScript(
8085
luaCode: string,
81-
config: LuatsConfig
86+
config: any // Change type to 'any' temporarily to fix the error
8287
): Promise<string> {
83-
// Use the real generator
84-
return generateTypes(luaCode, config.typeGeneratorOptions || {});
88+
// Use the real generator with all options passed
89+
return generateTypes(luaCode, {
90+
useUnknown: config.typeGeneratorOptions?.useUnknown,
91+
interfacePrefix: config.typeGeneratorOptions?.interfacePrefix,
92+
semicolons: config.typeGeneratorOptions?.semicolons,
93+
preserveComments: config.preserveComments,
94+
commentStyle: config.commentStyle
95+
});
8596
}

src/generators/typescript/generator.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,17 @@ export class TypeGenerator {
4747
} else if (node.name && node.definition) {
4848
name = node.name.name || node.name;
4949
value = node.definition;
50-
comments = node.comments || node.comments;
50+
// Prefer node.comments, fallback to node.definition.comments
51+
comments = node.comments || (node.definition ? node.definition.comments : undefined);
5152
} else {
5253
return;
5354
}
5455
if (typeof name !== 'string') return;
5556

57+
// Process comments for the type alias
58+
const commentStr = comments && comments.length > 0 ?
59+
formatComments(comments) : undefined;
60+
5661
// --- Handle Record types as type aliases ---
5762
if (
5863
value.type === 'TableType' &&
@@ -65,7 +70,7 @@ export class TypeGenerator {
6570
name,
6671
type: `Record<${keyType}, ${this.getTypeString(value.fields[0].valueType)}>`,
6772

68-
description: comments ? formatComments(comments) : undefined
73+
description: commentStr
6974
};
7075
this.types.set(name, tsType);
7176
return;
@@ -92,7 +97,7 @@ export class TypeGenerator {
9297
const tsType: TypeScriptType = {
9398
name,
9499
type: `(${params.join(', ')}) => ${ret}`,
95-
description: comments ? formatComments(comments) : undefined
100+
description: commentStr
96101
};
97102
this.types.set(name, tsType);
98103
return;
@@ -103,16 +108,18 @@ export class TypeGenerator {
103108
const tsInterface: TypeScriptInterface = {
104109
name,
105110
properties: [],
106-
description: comments ? formatComments(comments) : undefined
111+
description: commentStr
107112
};
108113
if (value.fields) {
109114
for (const field of value.fields) {
115+
// Extract field-level comments if present
116+
const fieldComments = field.comments ? formatComments(field.comments) : undefined;
117+
110118
const property: TypeScriptProperty = {
111119
name: field.name?.name || field.key || '',
112120
type: this.getTypeString(field.valueType),
113121
optional: field.optional || false,
114-
// Attach field comments if present
115-
description: field.comments ? formatComments(field.comments) : undefined
122+
description: fieldComments
116123
};
117124
tsInterface.properties.push(property);
118125
}
@@ -126,7 +133,7 @@ export class TypeGenerator {
126133
const tsType: TypeScriptType = {
127134
name,
128135
type: this.getTypeString(value),
129-
description: comments ? formatComments(comments) : undefined
136+
description: commentStr
130137
};
131138
this.types.set(name, tsType);
132139
return;
@@ -136,7 +143,7 @@ export class TypeGenerator {
136143
const tsType: TypeScriptType = {
137144
name,
138145
type: this.getTypeString(value),
139-
description: comments ? formatComments(comments) : undefined
146+
description: commentStr
140147
};
141148
this.types.set(name, tsType);
142149
}

src/generators/typescript/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ export interface TypeGeneratorOptions {
3737
interfacePrefix?: string;
3838
semicolons?: boolean;
3939
commentStyle?: 'jsdoc' | 'inline';
40+
generateComments?: boolean; // Add explicit option for comment generation
4041
}

src/generators/typescript/utils.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@ import { TypeScriptParameter } from './types';
22

33
export function formatComments(comments: any[]): string {
44
if (!comments || comments.length === 0) return '';
5-
// If any comment is a block, treat as multi-line JSDoc
6-
if (comments.length === 1 && comments[0].type !== 'Block') {
7-
return `/** ${comments[0].value.trim()} */`;
8-
} else {
9-
return [
10-
'/**',
11-
...comments.map((c: any) =>
12-
c.value
13-
.split('\n')
14-
.map((line: string) => ` * ${line.trim()}`)
15-
.join('\n')
16-
),
17-
' */'
18-
].join('\n');
5+
// Flatten all comment values, split by newlines, trim, and filter empty lines
6+
const lines: string[] = [];
7+
for (const c of comments) {
8+
if (!c || typeof c.value !== 'string') continue;
9+
// Split multiline comments into lines, trim each
10+
for (const line of c.value.split('\n')) {
11+
const trimmed = line.trim();
12+
if (trimmed) lines.push(trimmed);
13+
}
1914
}
15+
if (lines.length === 0) return '';
16+
if (lines.length === 1) {
17+
return `/** ${lines[0]} */`;
18+
}
19+
return [
20+
'/**',
21+
...lines.map(line => ` * ${line}`),
22+
' */'
23+
].join('\n');
2024
}
2125

2226
export function getParameters(node: any, getTypeString: (typeNode: any) => string, useUnknown: boolean): TypeScriptParameter[] {

src/parsers/luau.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,22 @@ export class LuauParser {
115115
this.consume(TokenType.ASSIGN, "Expected '=' after type name");
116116
const definition = this.parseType();
117117

118-
// Attach pending comments to fields if present
119-
if (pendingComments && pendingComments.length && definition && definition.type === 'TableType' && definition.fields) {
120-
for (const field of definition.fields) {
121-
(field as any).comments = pendingComments;
122-
}
123-
pendingComments.length = 0;
124-
}
125-
126-
return {
127-
type: 'TypeAlias',
118+
// Create the TypeAlias node with comments
119+
const typeAlias: AST.TypeAlias = {
120+
type: 'TypeAlias' as const,
128121
name,
129122
typeParameters,
130123
definition,
131124
location: this.getLocation(),
132125
};
126+
127+
// Attach comments to the type alias if they exist
128+
if (pendingComments && pendingComments.length) {
129+
(typeAlias as any).comments = pendingComments;
130+
pendingComments.length = 0;
131+
}
132+
133+
return typeAlias;
133134
}
134135

135136

test/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Use the debug scripts in this directory for troubleshooting:
7878
- `debug/test-multiple.ts`: Tests for multiple type definitions
7979
- `debug/test-demo-structure.ts`: Tests for the demo code structure
8080

81+
82+
8183
<!-- TEST_RESULTS_START -->
8284
## Test Results
8385

test/all.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ import './features.test.js';
66
import './types.test.js';
77
import './snapshots.test.js';
88
import './plugins.test.js';
9-
import './cli.test.js';
9+
import './cli.test.js';
10+
11+
describe('LuaTS Test Suite', () => {
12+
// This is just a container for all the tests
13+
// Each imported test file will run its own tests
14+
// This file helps organize and run all tests at once
15+
});

0 commit comments

Comments
 (0)