Tools: doc templates - add support for iterating tags

- Support iterating tags
- Generate (update) all docs
This commit is contained in:
ljacqu 2016-04-07 17:19:52 +02:00
parent d46ad9ab5e
commit b3a3843b60
16 changed files with 209 additions and 106 deletions

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sun Feb 14 19:00:30 CET 2016. See commands/commands.tpl.md -->
<!-- File auto-generated on Thu Apr 07 17:17:20 CEST 2016. See commands/commands.tpl.md -->
## AuthMe Commands
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
@ -7,74 +7,72 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
- **/authme**: The main AuthMeReloaded command. The root for all admin commands.
- **/authme register** &lt;player> &lt;password>: Register the specified player with the specified password.
<br />Requires `authme.admin.register`
<br />Requires `authme.admin.register`
- **/authme unregister** &lt;player>: Unregister the specified player.
<br />Requires `authme.admin.unregister`
<br />Requires `authme.admin.unregister`
- **/authme forcelogin** [player]: Enforce the specified player to login.
<br />Requires `authme.player.canbeforced`
<br />Requires `authme.admin.forcelogin`
- **/authme password** &lt;player> &lt;pwd>: Change the password of a player.
<br />Requires `authme.admin.changepassword`
<br />Requires `authme.admin.changepassword`
- **/authme lastlogin** [player]: View the date of the specified players last login.
<br />Requires `authme.admin.lastlogin`
<br />Requires `authme.admin.lastlogin`
- **/authme accounts** [player]: Display all accounts of a player by his player name or IP.
<br />Requires `authme.admin.accounts`
<br />Requires `authme.admin.accounts`
- **/authme email** [player]: Display the email address of the specified player if set.
<br />Requires `authme.admin.getemail`
<br />Requires `authme.admin.getemail`
- **/authme setemail** &lt;player> &lt;email>: Change the email address of the specified player.
<br />Requires `authme.admin.changemail`
<br />Requires `authme.admin.changemail`
- **/authme getip** &lt;player>: Get the IP address of the specified online player.
<br />Requires `authme.admin.getip`
- **/authme spawn** &lt;player>: Teleport to the spawn.
<br />Requires `authme.admin.spawn`
<br />Requires `authme.admin.getip`
- **/authme spawn**: Teleport to the spawn.
<br />Requires `authme.admin.spawn`
- **/authme setspawn**: Change the player's spawn to your current position.
<br />Requires `authme.admin.setspawn`
<br />Requires `authme.admin.setspawn`
- **/authme firstspawn**: Teleport to the first spawn.
<br />Requires `authme.admin.firstspawn`
<br />Requires `authme.admin.firstspawn`
- **/authme setfirstspawn**: Change the first player's spawn to your current position.
<br />Requires `authme.admin.setfirstspawn`
<br />Requires `authme.admin.setfirstspawn`
- **/authme purge** &lt;days>: Purge old AuthMeReloaded data longer than the specified amount of days ago.
<br />Requires `authme.admin.purge`
<br />Requires `authme.admin.purge`
- **/authme resetpos** &lt;player/*>: Purge the last know position of the specified player or all of them.
<br />Requires `authme.admin.purgelastpos`
<br />Requires `authme.admin.purgelastpos`
- **/authme purgebannedplayers**: Purge all AuthMeReloaded data for banned players.
<br />Requires `authme.admin.purgebannedplayers`
<br />Requires `authme.admin.purgebannedplayers`
- **/authme switchantibot** [mode]: Switch or toggle the AntiBot mode to the specified state.
<br />Requires `authme.admin.switchantibot`
<br />Requires `authme.admin.switchantibot`
- **/authme reload**: Reload the AuthMeReloaded plugin.
<br />Requires `authme.admin.reload`
<br />Requires `authme.admin.reload`
- **/authme version**: Show detailed information about the installed AuthMeReloaded version, the developers, contributors, and license.
- **/authme converter** &lt;job>: Converter command for AuthMeReloaded.
<br />Requires `authme.admin.converter`
- **/authme help** [query]: View detailed help for /authme commands.
- **/login** &lt;password>: Command to log in using AuthMeReloaded.
<br />Requires `authme.player.login`
<br />Requires `authme.player.login`
- **/login help** [query]: View detailed help for /login commands.
- **/logout**: Command to logout using AuthMeReloaded.
<br />Requires `authme.player.logout`
<br />Requires `authme.player.logout`
- **/logout help** [query]: View detailed help for /logout commands.
- **/register** [password] [verifyPassword]: Command to register using AuthMeReloaded.
<br />Requires `authme.player.register`
<br />Requires `authme.player.register`
- **/register help** [query]: View detailed help for /register commands.
- **/unreg** &lt;password>: Command to unregister using AuthMeReloaded.
<br />Requires `authme.player.unregister`
<br />Requires `authme.player.unregister`
- **/unreg help** [query]: View detailed help for /unreg commands.
- **/changepassword** &lt;oldPassword> &lt;newPassword>: Command to change your password using AuthMeReloaded.
<br />Requires `authme.player.changepassword`
<br />Requires `authme.player.changepassword`
- **/changepassword help** [query]: View detailed help for /changepassword commands.
- **/email**: The AuthMeReloaded Email command base.
- **/email add** &lt;email> &lt;verifyEmail>: Add a new email address to your account.
<br />Requires `authme.player.email.add`
<br />Requires `authme.player.email.add`
- **/email change** &lt;oldEmail> &lt;newEmail>: Change an email address of your account.
<br />Requires `authme.player.email.change`
<br />Requires `authme.player.email.change`
- **/email recover** &lt;email>: Recover your account using an Email address by sending a mail containing a new password.
<br />Requires `authme.player.email.recover`
<br />Requires `authme.player.email.recover`
- **/email help** [query]: View detailed help for /email commands.
- **/captcha** &lt;captcha>: Captcha command for AuthMeReloaded.
<br />Requires `authme.player.captcha`
<br />Requires `authme.player.captcha`
- **/captcha help** [query]: View detailed help for /captcha commands.
- **/converter** &lt;job>: Converter command for AuthMeReloaded.
<br />Requires `authme.admin.converter`
- **/converter help** [query]: View detailed help for /converter commands.
---
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Sun Feb 14 19:00:30 CET 2016
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Thu Apr 07 17:17:20 CEST 2016

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sun Feb 14 19:00:32 CET 2016. See hashmethods/hash_algorithms.tpl.md -->
<!-- File auto-generated on Thu Apr 07 17:17:22 CEST 2016. See hashmethods/hash_algorithms.tpl.md -->
## Hash Algorithms
AuthMe supports the following hash algorithms for storing your passwords safely.
@ -17,7 +17,7 @@ JOOMLA | Recommended | 65 | | | Text | 32 |
MD5 | Do not use | 32 | | | None | |
MD5VB | Acceptable | 56 | | | Text | 16 |
MYBB | Acceptable | 32 | | | Text | 8 | Y
PBKDF2 | Does not work | 330 | | | Text | 12 |
PBKDF2 | Does not work | 328 | | | Text | 12 |
PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
PHPBB | Acceptable | 34 | | | Text | 16 |
PHPFUSION | Do not use | 64 | Y | | | | Y
@ -82,4 +82,4 @@ or bad.
---
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Sun Feb 14 19:00:32 CET 2016
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Thu Apr 07 17:17:22 CEST 2016

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sun Feb 14 19:00:34 CET 2016. See permissions/permission_nodes.tpl.md -->
<!-- File auto-generated on Thu Apr 07 17:17:24 CEST 2016. See permissions/permission_nodes.tpl.md -->
## AuthMe Permission Nodes
The following are the permission nodes that are currently supported by the latest dev builds.
@ -42,7 +42,6 @@ The following are the permission nodes that are currently supported by the lates
- **authme.player.unregister** Command permission to unregister.
- **authme.vip** Permission node to identify VIP users.
---
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Sun Feb 14 19:00:34 CET 2016
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Thu Apr 07 17:17:24 CEST 2016

View File

@ -1,6 +1,5 @@
package commands;
import com.google.common.collect.ImmutableMap;
import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.command.CommandInitializer;
@ -8,12 +7,12 @@ import fr.xephi.authme.command.CommandPermissions;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.permission.PermissionNode;
import utils.FileUtils;
import utils.TagReplacer;
import utils.TagValue.NestedTagValue;
import utils.TagValueHolder;
import utils.ToolTask;
import utils.ToolsConstants;
import java.util.Collection;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
@ -29,31 +28,27 @@ public class CommandPageCreater implements ToolTask {
@Override
public void execute(Scanner scanner) {
final Set<CommandDescription> baseCommands = CommandInitializer.buildCommands();
final String template = FileUtils.readFromFile(ToolsConstants.TOOLS_SOURCE_ROOT
+ "commands/command_entry.tpl.md");
StringBuilder commandsResult = new StringBuilder();
addCommandsInfo(commandsResult, baseCommands, template);
NestedTagValue commandTags = new NestedTagValue();
addCommandsInfo(commandTags, baseCommands);
FileUtils.generateFileFromTemplate(
ToolsConstants.TOOLS_SOURCE_ROOT + "commands/commands.tpl.md",
OUTPUT_FILE,
ImmutableMap.of("commands", commandsResult.toString()));
TagValueHolder.create().put("commands", commandTags));
System.out.println("Wrote to '" + OUTPUT_FILE + "' with " + baseCommands.size() + " base commands.");
}
private static void addCommandsInfo(StringBuilder sb, Collection<CommandDescription> commands,
final String template) {
private static void addCommandsInfo(NestedTagValue commandTags, Collection<CommandDescription> commands) {
for (CommandDescription command : commands) {
Map<String, String> tags = ImmutableMap.of(
"command", CommandUtils.constructCommandPath(command),
"description", command.getDetailedDescription(),
"arguments", formatArguments(command.getArguments()),
"permissions", formatPermissions(command.getCommandPermissions()));
sb.append(TagReplacer.applyReplacements(template, tags));
TagValueHolder tags = TagValueHolder.create()
.put("command", CommandUtils.constructCommandPath(command))
.put("description", command.getDetailedDescription())
.put("arguments", formatArguments(command.getArguments()))
.put("permissions", formatPermissions(command.getCommandPermissions()));
commandTags.add(tags);
if (!command.getChildren().isEmpty()) {
addCommandsInfo(sb, command.getChildren(), template);
addCommandsInfo(commandTags, command.getChildren());
}
}
}

View File

@ -1,2 +0,0 @@
- **{command}**{arguments}: {description}[permissions]
<br />Requires `{permissions}`[/permissions]

View File

@ -5,6 +5,9 @@
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
brackets; optional arguments are enclosed in square brackets (`[ ]`).
{commands}
[#commands]
- **{command}**{arguments}: {description}[permissions]
<br />Requires `{permissions}`[/permissions]
[/#commands]
{gen_footer}

View File

@ -1,11 +1,11 @@
package hashmethods;
import com.google.common.collect.ImmutableMap;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.WrapperMock;
import utils.FileUtils;
import utils.TagReplacer;
import utils.TagValue.NestedTagValue;
import utils.TagValueHolder;
import utils.ToolTask;
import utils.ToolsConstants;
@ -33,30 +33,28 @@ public class HashAlgorithmsDescriptionTask implements ToolTask {
// Gather info and construct a row for each method
EncryptionMethodInfoGatherer infoGatherer = new EncryptionMethodInfoGatherer();
Map<HashAlgorithm, MethodDescription> descriptions = infoGatherer.getDescriptions();
final String methodRows = constructMethodRows(descriptions);
final NestedTagValue methodRows = constructMethodRows(descriptions);
// Write to the docs file
Map<String, String> tags = ImmutableMap.of("method_rows", methodRows);
TagValueHolder tags = TagValueHolder.create().put("algorithms", methodRows);
FileUtils.generateFileFromTemplate(CUR_FOLDER + "hash_algorithms.tpl.md", OUTPUT_FILE, tags);
}
private static String constructMethodRows(Map<HashAlgorithm, MethodDescription> descriptions) {
final String rowTemplate = FileUtils.readFromFile(CUR_FOLDER + "hash_algorithms_row.tpl.md");
StringBuilder result = new StringBuilder();
private static NestedTagValue constructMethodRows(Map<HashAlgorithm, MethodDescription> descriptions) {
NestedTagValue methodTags = new NestedTagValue();
for (Map.Entry<HashAlgorithm, MethodDescription> entry : descriptions.entrySet()) {
MethodDescription description = entry.getValue();
Map<String, String> tags = ImmutableMap.<String, String>builder()
TagValueHolder tags = TagValueHolder.create()
.put("name", asString(entry.getKey()))
.put("recommendation", asString(description.getUsage()))
.put("hash_length", asString(description.getHashLength()))
.put("ascii_restricted", asString(description.isAsciiRestricted()))
.put("salt_type", asString(description.getSaltType()))
.put("salt_length", asString(description.getSaltLength()))
.put("separate_salt", asString(description.hasSeparateSalt()))
.build();
result.append(TagReplacer.applyReplacements(rowTemplate, tags));
.put("separate_salt", asString(description.hasSeparateSalt()));
methodTags.add(tags);
}
return result.toString();
return methodTags;
}
@Override

View File

@ -7,7 +7,10 @@ AuthMe supports the following hash algorithms for storing your passwords safely.
Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate?
--------- | -------------- | ----------- | ----- | --- | --------- | ------ | ---------
{method_rows}CUSTOM | | | | | | | |
[#algorithms]
{name} | {recommendation} | {hash_length} | {ascii_restricted} | | {salt_type} | {salt_length} | {separate_salt}
[/#algorithms]
CUSTOM | | | | | | | |
<!-- {gen_warning} -->

View File

@ -1 +0,0 @@
{name} | {recommendation} | {hash_length} | {ascii_restricted} | | {salt_type} | {salt_length} | {separate_salt}

View File

@ -1,8 +1,8 @@
package permissions;
import com.google.common.collect.ImmutableMap;
import utils.FileUtils;
import utils.TagReplacer;
import utils.TagValue.NestedTagValue;
import utils.TagValueHolder;
import utils.ToolTask;
import utils.ToolsConstants;
@ -45,29 +45,25 @@ public class PermissionsListWriter implements ToolTask {
}
private static void generateAndWriteFile() {
final String permissionsTagValue = generatePermissionsList();
final NestedTagValue permissionsTagValue = generatePermissionsList();
Map<String, String> tags = ImmutableMap.of("permissions", permissionsTagValue);
TagValueHolder tags = TagValueHolder.create().put("nodes", permissionsTagValue);
FileUtils.generateFileFromTemplate(
ToolsConstants.TOOLS_SOURCE_ROOT + "permissions/permission_nodes.tpl.md", PERMISSIONS_OUTPUT_FILE, tags);
System.out.println("Wrote to '" + PERMISSIONS_OUTPUT_FILE + "'");
System.out.println("Before committing, please verify the output!");
}
private static String generatePermissionsList() {
private static NestedTagValue generatePermissionsList() {
PermissionNodesGatherer gatherer = new PermissionNodesGatherer();
Map<String, String> permissions = gatherer.gatherNodesWithJavaDoc();
final String template = FileUtils.readFromToolsFile("permissions/permission_node_entry.tpl.md");
StringBuilder sb = new StringBuilder();
NestedTagValue permissionTags = new NestedTagValue();
for (Map.Entry<String, String> entry : permissions.entrySet()) {
Map<String, String> tags = ImmutableMap.of(
"node", entry.getKey(),
"description", entry.getValue());
sb.append(TagReplacer.applyReplacements(template, tags));
permissionTags.add(TagValueHolder.create()
.put("node", entry.getKey())
.put("description", entry.getValue()));
}
return sb.toString();
return permissionTags;
}
private static void outputSimpleList() {

View File

@ -1 +0,0 @@
- **{node}** {description}

View File

@ -4,6 +4,8 @@
## AuthMe Permission Nodes
The following are the permission nodes that are currently supported by the latest dev builds.
{permissions}
[#nodes]
- **{node}** {description}
[/#nodes]
{gen_footer}

View File

@ -6,7 +6,6 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
/**
* Utility class for reading from and writing to files.
@ -18,7 +17,7 @@ public final class FileUtils {
private FileUtils() {
}
public static void generateFileFromTemplate(String templateFile, String destinationFile, Map<String, String> tags) {
public static void generateFileFromTemplate(String templateFile, String destinationFile, TagValueHolder tags) {
String template = readFromFile(templateFile);
String result = TagReplacer.applyReplacements(template, tags);
writeToFile(destinationFile, result);
@ -56,8 +55,4 @@ public final class FileUtils {
}
}
public static String readFromToolsFile(String file) {
return readFromFile(ToolsConstants.TOOLS_SOURCE_ROOT + file);
}
}

View File

@ -1,6 +1,7 @@
package utils;
import fr.xephi.authme.util.StringUtils;
import utils.TagValue.NestedTagValue;
import utils.TagValue.TextTagValue;
import java.util.Date;
import java.util.Map;
@ -26,18 +27,25 @@ public class TagReplacer {
* Replace a template with default tags and custom ones supplied by a map.
*
* @param template The template to process
* @param tags Map with additional tags, e.g. a map entry with key "foo" and value "bar" will replace
* @param tagValues Map with additional tags, e.g. a map entry with key "foo" and value "bar" will replace
* any occurrences of "{foo}" to "bar".
* @return The filled template
*/
public static String applyReplacements(String template, Map<String, String> tags) {
public static String applyReplacements(String template, TagValueHolder tagValues) {
String result = template;
for (Map.Entry<String, String> tagRule : tags.entrySet()) {
for (Map.Entry<String, TagValue<?>> tagRule : tagValues.getValues().entrySet()) {
final String name = tagRule.getKey();
final String value = tagRule.getValue();
result = replaceOptionalTag(result, name, value)
.replace("{" + name + "}", value);
if (tagRule.getValue() instanceof TextTagValue) {
final TextTagValue value = (TextTagValue) tagRule.getValue();
result = replaceOptionalTag(result, name, value)
.replace("{" + name + "}", value.getValue());
} else if (tagRule.getValue() instanceof NestedTagValue) {
final NestedTagValue value = (NestedTagValue) tagRule.getValue();
result = replaceIterateTag(replaceOptionalTag(result, name, value), name, value);
} else {
throw new IllegalStateException("Unknown tag value type");
}
}
return applyReplacements(result);
}
@ -58,14 +66,14 @@ public class TagReplacer {
+ " on " + curDate);
}
private static String replaceOptionalTag(String text, String tagName, String tagValue) {
private static String replaceOptionalTag(String text, String tagName, TagValue<?> tagValue) {
Pattern regex = Pattern.compile("\\[" + tagName + "](.*?)\\[/" + tagName + "]", Pattern.DOTALL);
Matcher matcher = regex.matcher(text);
if (!matcher.find()) {
// Couldn't find results, so just return text as it is
return text;
} else if (StringUtils.isEmpty(tagValue)) {
} else if (tagValue.isEmpty()) {
// Tag is empty, replace [tagName]some_text[/tagName] to nothing
return matcher.replaceAll("");
} else {
@ -74,5 +82,30 @@ public class TagReplacer {
}
}
/**
* Replace iterating tags with the value. Tags of the type [#tag]...[/#tag] specify to iterate over the
* entries in {@link NestedTagValue} and to apply any replacements in there.
*
* @param text The file text
* @param tagName The tag name to handle
* @param tagValue The associated value
* @return The text with the applied replacement
*/
private static String replaceIterateTag(String text, String tagName, NestedTagValue tagValue) {
Pattern regex = Pattern.compile("\\[#" + tagName + "](.*?)\\[/#" + tagName + "]\\s?", Pattern.DOTALL);
Matcher matcher = regex.matcher(text);
if (!matcher.find()) {
return text;
} else if (tagValue.isEmpty()) {
return matcher.replaceAll("");
}
final String innerTemplate = matcher.group(1).trim() + "\n";
String result = "";
for (TagValueHolder entry : tagValue.getValue()) {
result += applyReplacements(innerTemplate, entry);
}
return matcher.replaceAll(result);
}
}

View File

@ -0,0 +1,51 @@
package utils;
import java.util.ArrayList;
import java.util.List;
public abstract class TagValue<T> {
private final T value;
public TagValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public abstract boolean isEmpty();
public static final class TextTagValue extends TagValue<String> {
public TextTagValue(String value) {
super(value);
}
@Override
public boolean isEmpty() {
return getValue().isEmpty();
}
@Override
public int hashCode() {
return super.hashCode();
}
}
public static final class NestedTagValue extends TagValue<List<TagValueHolder>> {
public NestedTagValue() {
super(new ArrayList<TagValueHolder>());
}
@Override
public boolean isEmpty() {
return getValue().isEmpty();
}
public void add(TagValueHolder entry) {
getValue().add(entry);
}
}
}

View File

@ -0,0 +1,34 @@
package utils;
import utils.TagValue.TextTagValue;
import java.util.HashMap;
import java.util.Map;
public class TagValueHolder {
private Map<String, TagValue<?>> values;
private TagValueHolder() {
this.values = new HashMap<>();
}
public static TagValueHolder create() {
return new TagValueHolder();
}
public TagValueHolder put(String key, TagValue<?> value) {
values.put(key, value);
return this;
}
public TagValueHolder put(String key, String value) {
values.put(key, new TextTagValue(value));
return this;
}
public Map<String, TagValue<?>> getValues() {
return values;
}
}