Skip to content

Commit

Permalink
Removed weapon docs export as markdown string
Browse files Browse the repository at this point in the history
And added a Python script to generate weapon docs markdown from JSON
  • Loading branch information
penev92 committed Mar 12, 2022
1 parent d36bf1a commit 43cf428
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 69 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/documentation.yml
Expand Up @@ -92,7 +92,7 @@ jobs:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
./utility.sh all --docs "${GIT_TAG}" > "docs/api/playtest/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/playtest/weapons.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/playtest/weapons.json" && python3 ./packaging/docs-weapons.py "docs/api/playtest/weapons.json" "docs/api/playtest/weapons.md"
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/api/playtest/lua.md"
- name: Update docs.openra.net (Release)
Expand All @@ -101,7 +101,7 @@ jobs:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
./utility.sh all --docs "${GIT_TAG}" > "docs/api/release/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/release/weapons.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/release/weapons.json" && python3 ./packaging/docs-weapons.py "docs/api/release/weapons.json" "docs/api/release/weapons.md"
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/api/release/lua.md"
- name: Push docs.openra.net
Expand All @@ -111,7 +111,7 @@ jobs:
cd docs
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add --all
git add *.md
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
git push origin master
71 changes: 5 additions & 66 deletions OpenRA.Mods.Common/UtilityCommands/ExtractWeaponDocsCommand.cs
Expand Up @@ -12,7 +12,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.GameRules;
using OpenRA.Primitives;
using OpenRA.Traits;
Expand All @@ -28,7 +27,7 @@ bool IUtilityCommand.ValidateArguments(string[] args)
return true;
}

[Desc("[VERSION]", "Generate weaponry documentation in MarkDown format.")]
[Desc("[VERSION]", "Generate weaponry documentation in JSON format.")]
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Expand All @@ -45,69 +44,11 @@ void IUtilityCommand.Run(Utility utility, string[] args)

var weaponTypes = weaponInfo.Concat(projectiles).Concat(warheads);

if (args.Length > 2 && args[2].ToLowerInvariant() == "json")
GenerateJson(version, weaponTypes, objectCreator);
else
GenerateMarkdown(version, weaponTypes, objectCreator);
var json = GenerateJson(version, weaponTypes, objectCreator);
Console.WriteLine(json);
}

static void GenerateMarkdown(string version, IEnumerable<Type> weaponTypes, ObjectCreator objectCreator)
{
var doc = new StringBuilder();

doc.AppendLine(
"This documentation is aimed at modders. It displays a template for weapon definitions " +
"as well as its contained types (warheads and projectiles) with default values and developer commentary. " +
"Please do not edit it directly, but add new `[Desc(\"String\")]` tags to the source code. This file has been " +
$"automatically generated for version {version} of OpenRA.");
doc.AppendLine();

var currentNamespace = "";

foreach (var t in weaponTypes)
{
// skip helpers like TraitInfo<T>
if (t.ContainsGenericParameters || t.IsAbstract)
continue;

if (currentNamespace != t.Namespace)
{
currentNamespace = t.Namespace;
doc.AppendLine();
doc.AppendLine($"## {currentNamespace}");
}

var traitName = t.Name.EndsWith("Info") ? t.Name.Substring(0, t.Name.Length - 4) : t.Name;
doc.AppendLine();
doc.AppendLine($"### {traitName}");

var traitDescLines = t.GetCustomAttributes<DescAttribute>(false).SelectMany(d => d.Lines);
foreach (var line in traitDescLines)
doc.AppendLine(line);

var infos = FieldLoader.GetTypeLoadInfo(t);
if (!infos.Any())
continue;

doc.AppendLine();
doc.AppendLine("| Property | Default Value | Type | Description |");
doc.AppendLine("| -------- | ------------- | ---- | ----------- |");

var liveTraitInfo = objectCreator.CreateBasic(t);
foreach (var info in infos)
{
var defaultValue = FieldSaver.SaveField(liveTraitInfo, info.Field.Name).Value.Value;
var fieldType = Util.FriendlyTypeName(info.Field.FieldType);
var fieldDescLines = info.Field.GetCustomAttributes<DescAttribute>(true).SelectMany(d => d.Lines);

doc.AppendLine($"| {info.YamlName} | {defaultValue} | {fieldType} | {string.Join(" ", fieldDescLines)} |");
}
}

Console.Write(doc.ToString());
}

static void GenerateJson(string version, IEnumerable<Type> weaponTypes, ObjectCreator objectCreator)
static string GenerateJson(string version, IEnumerable<Type> weaponTypes, ObjectCreator objectCreator)
{
var weaponTypesInfo = weaponTypes.Where(x => !x.ContainsGenericParameters && !x.IsAbstract)
.Select(t => new
Expand Down Expand Up @@ -149,9 +90,7 @@ static void GenerateJson(string version, IEnumerable<Type> weaponTypes, ObjectCr
WeaponTypes = weaponTypesInfo
};

var serializedResult = Newtonsoft.Json.JsonConvert.SerializeObject(result);

Console.WriteLine(serializedResult);
return Newtonsoft.Json.JsonConvert.SerializeObject(result);
}
}
}
65 changes: 65 additions & 0 deletions packaging/docs-weapons.py
@@ -0,0 +1,65 @@
# Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
# This file is part of OpenRA, which is free software. It is made
# available to you under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version. For more
# information, see COPYING.

import argparse
import json
from collections import OrderedDict

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('input', type=str)
parser.add_argument('output', type=str)
args = parser.parse_args()

inputFile = open(args.input, "r")
weaponInfo = json.loads(inputFile.read())
inputFile.close()

weaponsByNamespace = OrderedDict()
for currentWeapon in weaponInfo["WeaponTypes"]:
if currentWeapon["Namespace"] in weaponsByNamespace:
weaponsByNamespace[currentWeapon["Namespace"]].append(currentWeapon)
else:
weaponsByNamespace[currentWeapon["Namespace"]] = [currentWeapon]

version = weaponInfo["Version"]

outputFile = open(args.output, "w")
outputFile.write("#### This documentation is aimed at modders. It displays a template for weapon definitions " +
"as well as its contained types (warheads and projectiles) with default values and developer commentary. " +
"Please do not edit it directly, but add new `[Desc(\"String\")]` tags to the source code.\n\n")

outputFile.write(f"This file has been automatically generated for version **{version}** of OpenRA.")
outputFile.write('\n\n#\n\n')

for namespace in weaponsByNamespace:
outputFile.write(f'## {namespace}\n')
outputFile.write('\n')

for weapon in weaponsByNamespace[namespace]:
outputFile.write(f'### {weapon["Name"]}\n')
outputFile.write(f'#### {weapon["Description"]}\n')

if weapon["InheritedTypes"]:
outputFile.write("Inherits from: " + ", ".join([f'`{x}`' for x in weapon["InheritedTypes"]]) + '\n')

outputFile.write('\n')
outputFile.write('| Property | Default Value | Type | Attributes | Description |\n')
outputFile.write('| -------- | ------------- | ---- | ---------- | ----------- |\n')

for prop in weapon["Properties"]:
attributesList = [f'{x["Name"]}{"(" + str(x["Value"][0]) + ")" if x["Value"] else ""}' for x in prop["OtherAttributes"] if x["Name"]]
if not attributesList:
attributes = ''
else:
attributes = ", ".join(attributesList)

outputFile.write(f'| {prop["Name"]} | {prop["DefaultValue"]} | {prop["Type"]} | {attributes} | {prop["Description"]} |\n')

outputFile.write('\n\n')

outputFile.close()

0 comments on commit 43cf428

Please sign in to comment.