Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Updated MS Docs Commands documentation to support examples",
"packageName": "@minecraft/api-docs-generator",
"email": "jake@xbox.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Updated MS Docs Commands documentation to support examples",
"packageName": "@minecraft/markup-generators-plugin",
"email": "jake@xbox.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`General > Properly generates documentation for the input > # Of Files Generated 1`] = `42`;
exports[`General > Properly generates documentation for the input > # Of Files Generated 1`] = `45`;

exports[`General > Properly generates documentation for the input > msdocs/blocks/block_properties/diamonds_stored.md 1`] = `
"---
Expand Down Expand Up @@ -101,6 +101,14 @@ exports[`General > Properly generates documentation for the input > msdocs/comma
href: commands.md
- name: testcommand
href: commands/testcommand.md
- name: Command argument types
items:
- name: int
href: types/int.md
- name: position
href: types/position.md
- name: target
href: types/target.md
"
`;

Expand All @@ -121,9 +129,9 @@ description: List and descriptions of Minecraft commands and enums
# List and summary of command argument types and enums:
|Type |Description |Is Enum? |
|----------|-----------|-----------|
| int | A basic number | |
| position | | |
| target | | |
| [int](./types/int.md) | A basic number | |
| [position](./types/position.md) | | |
| [target](./types/target.md) | | |
"
`;

Expand All @@ -139,47 +147,68 @@ description: Description and usage of the testcommand command
# \`/testcommand\` Command
A fake command for testing documentation generation

<table>
<tr>
<th>Aliases</th>
<td>/notrealcommand, /fakecommand</td>
</tr>
<tr>
<th>Permission Level</th>
<td>Any</td>
</tr>
<tr>
<th>Requires Cheats?</th>
<td>Yes</td>
</tr>
</table>
| | |
| --- | --- |
| **Aliases** | \`/notrealcommand\`, \`/fakecommand\` |
| **Permission Level** | Any |
| **Requires Cheats** | Yes |

## Syntax Overview

\`/testcommand add <target: target> [amount: int]\`

\`/testcommand remove <target: target> [amount: int]\`

\`/testcommand set <center: x y z> <biome: TestBiomeEnum>\`

\`/testcommand set <center: target> <biome: TestBiomeEnum>\`

## Usage
### \`/testcommand add <target: target> [amount: int]\`
Adds an amount to a target

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| \`target\` | [target](../types/target.md) | Required | A target entity |
| \`amount\` | [int](../types/int.md) | Optional | |

### \`/testcommand remove <target: target> [amount: int]\`
Removes an amount from a target

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| \`target\` | [target](../types/target.md) | Required | A target entity |
| \`amount\` | [int](../types/int.md) | Optional | |

### Set based on Position
\`/testcommand set <center: x y z> <biome: TestBiomeEnum>\`

Sets an area to a biome centered on a position

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| \`center: x y z\` | [position](../types/position.md) | Required | The position that the biome will be centered on |
| \`biome\` | TestBiomeEnum | Required | |

### Set based on Target
\`/testcommand set <center: target> <biome: TestBiomeEnum>\`

Sets an area to a biome centered on a target

## Arguments
- \`amount\`: int
- \`biome\`: TestBiomeEnum
- \`center: x y z\`: position
The position that the biome will be centered on
- \`center\`: target
The target entity that the biome will be centered on
- \`target\`: target
A target entity
| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| \`center\` | [target](../types/target.md) | Required | The target entity that the biome will be centered on |
| \`biome\` | TestBiomeEnum | Required | |

## Arguments Reference

| Argument | Type | Description |
| --- | --- | --- |
| \`amount\` | [int](../types/int.md) | |
| \`biome\` | TestBiomeEnum | |
| \`center: x y z\` | [position](../types/position.md) | The position that the biome will be centered on |
| \`center\` | [target](../types/target.md) | The target entity that the biome will be centered on |
| \`target\` | [target](../types/target.md) | A target entity |

## Enums
### \`TestBiomeEnum\`
Expand All @@ -197,6 +226,47 @@ The plains biome.
"
`;

exports[`General > Properly generates documentation for the input > msdocs/commands/types/int.md 1`] = `
"---
# DO NOT TOUCH — This file was automatically generated by @minecraft/api-docs-generator, to report problems file an issue at https://github.com/Mojang/minecraft-scripting-libraries
author: jakeshirley
ms.author: jashir
ms.service: minecraft-bedrock-edition
title: int Command Argument Type
description: Description of the int command argument type
---
# \`int\` Command Argument Type
A basic number

"
`;

exports[`General > Properly generates documentation for the input > msdocs/commands/types/position.md 1`] = `
"---
# DO NOT TOUCH — This file was automatically generated by @minecraft/api-docs-generator, to report problems file an issue at https://github.com/Mojang/minecraft-scripting-libraries
author: jakeshirley
ms.author: jashir
ms.service: minecraft-bedrock-edition
title: position Command Argument Type
description: Description of the position command argument type
---
# \`position\` Command Argument Type
"
`;

exports[`General > Properly generates documentation for the input > msdocs/commands/types/target.md 1`] = `
"---
# DO NOT TOUCH — This file was automatically generated by @minecraft/api-docs-generator, to report problems file an issue at https://github.com/Mojang/minecraft-scripting-libraries
author: jakeshirley
ms.author: jashir
ms.service: minecraft-bedrock-edition
title: target Command Argument Type
description: Description of the target command argument type
---
# \`target\` Command Argument Type
"
`;

exports[`General > Properly generates documentation for the input > msdocs/scriptapi/TOC.yml 1`] = `
" - name: test-module2
items:
Expand Down
2 changes: 1 addition & 1 deletion tools/api-docs-generator/src/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ export class GeneratorContext {

if (config.documentationDirectory) {
const docsPath = path.resolve(config.documentationDirectory);
const loader = new FileLoader(docsPath, ['.json', '.js', '.ts']);
const loader = new FileLoader(docsPath, ['.json', '.js', '.ts', '.mcfunction']);
if (loader.loaded()) {
this.documentationFileLoader = loader;
} else {
Expand Down
3 changes: 2 additions & 1 deletion tools/api-docs-generator/src/filters/CommandFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function formatCommandArgumentTypes(moduleJson: MinecraftCommandModule) {
typeJson.name = enumJson.name;

typeJson.is_enum = true;
if (enumJson.command_references.length > 1) {
if (enumJson.values.length > 1 && enumJson.command_references.length > 1) {
typeJson.has_link = true;
}
if (enumJson.values.length === 1) {
Expand All @@ -121,6 +121,7 @@ function formatCommandArgumentTypes(moduleJson: MinecraftCommandModule) {
}
}
if (!typeJson.is_enum) {
typeJson.has_link = true;
const mappedTypeName = commandTypeNameMappings[typeJson.name];
if (mappedTypeName) {
typeJson.name = mappedTypeName;
Expand Down
94 changes: 80 additions & 14 deletions tools/api-docs-generator/src/filters/CommonFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
BlockPropertyDocsValidator,
CommandDocsValidator,
CommandEnumDocsValidator,
CommandExampleDocsData,
CommandExampleDocsValidator,
CommonDocsDescriptionValidator,
ScriptCommonDocsValidator,
ScriptFunctionDocsValidator,
Expand Down Expand Up @@ -671,14 +673,9 @@ function addExamples(
for (const examplePath of exampleFilePaths) {
const exampleName = path.basename(examplePath);

const exampleFileData = fileLoader.readFile(examplePath);
const exampleFileStrings: string[] = exampleFileData
.toString()
.split('\n')
.map(line => line.replace(/\n|\r/, ''));
if (exampleFileStrings.at(-1) === '') {
exampleFileStrings.splice(-1); // Remove newline at end of example file
}
const exampleFileData = fileLoader.readFileAsString(examplePath);
const exampleFileStrings =
exampleFileData.length === 0 ? [] : utils.normalizeExampleText(exampleFileData).split('\n');

const escapedExampleFileStrings = exampleFileStrings.map(line =>
line.replace(/\/\*/g, `/\\*`).replace(/\*\//g, `*\\/`)
Expand Down Expand Up @@ -1024,6 +1021,69 @@ function addCommandTypeDescriptions(
}
}

function addCommandExamples(fileLoader: FileLoader, commandJson: MinecraftCommand, commandFolderPath: string): void {
commandJson.command_examples = [];
for (const overload of commandJson.overloads) {
overload.overload_examples = [];
}

const examplesDirectory = path.join(commandFolderPath, '_examples');
const exampleFiles = utils
.getFiles(fileLoader.joinToRoot(examplesDirectory))
.filter(filename => fileLoader.canLoadFile(path.join(examplesDirectory, filename)))
.sort();
const sourceFiles = exampleFiles.filter(filename => path.extname(filename) === '.mcfunction');
for (const filename of exampleFiles.filter(filename => path.extname(filename) === '.json')) {
const sourceName = `${path.basename(filename, '.json')}.mcfunction`;
if (!sourceFiles.includes(sourceName)) {
log.error(
`Command example metadata '${path.join(examplesDirectory, filename)}' has no matching '${sourceName}' file.`
);
}
}

for (const filename of sourceFiles) {
const examplePath = path.join(examplesDirectory, filename);
const infoPath = path.join(examplesDirectory, `${path.basename(filename, '.mcfunction')}.json`);
let info: CommandExampleDocsData = {};
if (fileLoader.canLoadFile(infoPath)) {
const parsedInfo = parseJsonSafe(fileLoader, infoPath, CommandExampleDocsValidator);
if (!parsedInfo) {
continue;
}
info = parsedInfo;
}
if (info.title !== undefined && !info.title.trim()) {
log.error(`Command example metadata '${infoPath}' has an empty title.`);
continue;
}
const overload =
info.overload === undefined
? undefined
: commandJson.overloads.find(overload => Number(overload.name) === info.overload);
if (info.overload !== undefined && !overload) {
log.error(`Command example metadata '${infoPath}' references unknown overload '${info.overload}'.`);
continue;
}

const code = utils.normalizeExampleText(fileLoader.readFileAsString(examplePath));
if (!code.trim()) {
log.error(`Command example file '${examplePath}' is empty.`);
continue;
}
const examples = overload ? overload.overload_examples : commandJson.command_examples;
examples.push({
title: info.title ?? filename,
code,
description: info.description ? splitStringByNewline(info.description) : [],
});
commandJson.has_comments = true;
if (overload) {
overload.has_comments = true;
}
}
}

function addCommandDescriptions(fileLoader: FileLoader, commandJson: MinecraftCommand, moduleFolderPath: string) {
commandJson.has_comments = false;

Expand All @@ -1040,17 +1100,21 @@ function addCommandDescriptions(fileLoader: FileLoader, commandJson: MinecraftCo
if (infoJson.overloads) {
for (const overloadJson of commandJson.overloads) {
const overloadInfoJson = infoJson.overloads.find(o => Number(overloadJson.name) === o.id);
if (overloadInfoJson && overloadInfoJson.description) {
overloadJson.has_comments = true;
overloadJson.overload_description = splitStringByNewline(overloadInfoJson.description);
if (overloadInfoJson.header) {
overloadJson.overload_header = overloadInfoJson.header;
if (overloadInfoJson) {
overloadJson.overload_header = overloadInfoJson.header;
if (overloadInfoJson.description) {
overloadJson.has_comments = true;
overloadJson.overload_description = splitStringByNewline(overloadInfoJson.description);
}
}
}
}
if (infoJson.arguments) {
for (const argumentJson of commandJson.arguments) {
const argumentsToDocument = new Set([
...commandJson.arguments,
...commandJson.overloads.flatMap(overload => overload.params),
]);
for (const argumentJson of argumentsToDocument) {
const argInfoJson = infoJson.arguments.find(a => argumentJson.directory_name === a.name);
if (argInfoJson && argInfoJson.description) {
argumentJson.has_comments = true;
Expand All @@ -1060,6 +1124,8 @@ function addCommandDescriptions(fileLoader: FileLoader, commandJson: MinecraftCo
}
}

addCommandExamples(fileLoader, commandJson, commandFolderPath);

if (commandJson.command_enums) {
for (const enumJson of commandJson.command_enums) {
addCommandEnumDescriptions(fileLoader, enumJson, commandFolderPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ export const MinecraftCommandArgumentRecord = Record({
});
export type MinecraftCommandArgument = Static<typeof MinecraftCommandArgumentRecord>;

export const MinecraftCommandExampleRecord = Record({
title: String,
code: String,
description: Optional(Array(String)),
});
export type MinecraftCommandExample = Static<typeof MinecraftCommandExampleRecord>;

export const MinecraftCommandOverloadRecord = Record({
name: String,
params: Array(MinecraftCommandArgumentRecord),
Expand All @@ -79,6 +86,7 @@ export const MinecraftCommandOverloadRecord = Record({
has_comments: Optional(Boolean),
overload_description: Optional(Array(String)),
overload_header: Optional(String),
overload_examples: Optional(Array(MinecraftCommandExampleRecord)),
});
export type MinecraftCommandOverload = Static<typeof MinecraftCommandOverloadRecord>;

Expand All @@ -100,6 +108,7 @@ export const MinecraftCommandRecord = Record({

has_comments: Optional(Boolean),
command_description: Optional(Array(String)),
command_examples: Optional(Array(MinecraftCommandExampleRecord)),
});
export type MinecraftCommand = Static<typeof MinecraftCommandRecord>;

Expand Down
9 changes: 9 additions & 0 deletions tools/api-docs-generator/src/modules/MinecraftDocsTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ export type ScriptNestedFunctionDocsData = Static<typeof ScriptNestedFunctionDoc
export const ScriptFunctionDocsValidator = generatorValidatorFromNested(ScriptNestedFunctionDocsValidator);
export type ScriptFunctionDocsData = Static<typeof ScriptFunctionDocsValidator>;

export const CommandExampleDocsValidator = Intersect(
CommonDocsDescriptionValidator,
Record({
title: Optional(String),
overload: Optional(Number),
})
);
export type CommandExampleDocsData = Static<typeof CommandExampleDocsValidator>;

export const CommandDocsValidator = Intersect(
CommonDocsDescriptionValidator,
Record({
Expand Down
Loading
Loading