UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

850 lines (848 loc) 44.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExportMode = exports.MarkdownTop = void 0; const Utilities_1 = require("../core/Utilities"); const StorageUtilities_1 = require("../storage/StorageUtilities"); const DataFormUtilities_1 = require("../dataform/DataFormUtilities"); const IField_1 = require("../dataform/IField"); const EntityTypeDefinition_1 = require("../minecraft/EntityTypeDefinition"); const Database_1 = require("../minecraft/Database"); const ICondition_1 = require("../dataform/ICondition"); exports.MarkdownTop = `--- author: mammerla ms.author: mikeam title: "{0}" description: "{1}" ms.service: minecraft-bedrock-edition ms.date: 02/11/2025 --- `; var ExportMode; (function (ExportMode) { ExportMode[ExportMode["other"] = 0] = "other"; ExportMode[ExportMode["triggers"] = 1] = "triggers"; ExportMode[ExportMode["blockComponents"] = 2] = "blockComponents"; ExportMode[ExportMode["itemComponents"] = 3] = "itemComponents"; ExportMode[ExportMode["entityComponents"] = 4] = "entityComponents"; ExportMode[ExportMode["AIGoals"] = 5] = "AIGoals"; ExportMode[ExportMode["visuals"] = 6] = "visuals"; ExportMode[ExportMode["fogs"] = 7] = "fogs"; ExportMode[ExportMode["websockets"] = 8] = "websockets"; ExportMode[ExportMode["filters"] = 9] = "filters"; ExportMode[ExportMode["MCToolsVal"] = 10] = "MCToolsVal"; ExportMode[ExportMode["eventResponses"] = 11] = "eventResponses"; ExportMode[ExportMode["clientBiomes"] = 12] = "clientBiomes"; ExportMode[ExportMode["biomes"] = 13] = "biomes"; ExportMode[ExportMode["features"] = 14] = "features"; ExportMode[ExportMode["featureCore"] = 15] = "featureCore"; ExportMode[ExportMode["deferredRendering"] = 16] = "deferredRendering"; })(ExportMode = exports.ExportMode || (exports.ExportMode = {})); class FormMarkdownDocumentationGenerator { async generateMarkdown(formJsonInputFolder, outputFolder) { const formsByPath = {}; await this.loadFormJsonFromFolder(formsByPath, formJsonInputFolder, outputFolder); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.features, "/FeaturesReference/Examples/Features/", "/features/minecraft_", "Feature", "Feature Type"); this.exportMarkdownDocListPage(formsByPath, outputFolder, ExportMode.entityComponents, "/FeaturesReference/Examples/FeatureList.md", "/features/minecraft_", "Features", "Features"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.featureCore, "/FeaturesReference/Examples/Features/", "/feature/", "Feature", "Feature Type"); this.exportListYml(formsByPath, outputFolder, ExportMode.entityComponents, "/FeaturesReference/Examples/Features/TOC.yml", "/features/minecraft_", "- name: Features List\r\n href: ../FeatureList.md", "minecraft_"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.AIGoals, "/EntityReference/Examples/EntityGoals/", "/entity/minecraft_behavior", "Entity", "AI Behavior Component"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.visuals, "/VisualReference/", "/visual/", "Visuals", "Visual Element"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.fogs, "/FogsReference/", "/fogs/", "Fogs", "Fog Element"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.websockets, "/WebsocketsReference/", "/websockets/", "Websockets", "Websocket Packet"); this.exportValidatorMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.MCToolsVal, "/MCToolsValReference/", "/mctoolsval/", "MCTools Validation Rules", "MCTools Validation Rules"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.triggers, "/EntityReference/Examples/EntityTriggers/", "/entity/minecraft_on", "Entity", "Entity Trigger"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.filters, "/EntityReference/Examples/Filters/", "/entityfilters/", "Entity Filters", "Entity Filter Element"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.eventResponses, "/EntityReference/Examples/EventActions/", "/entityevents/", "Entity Actions", "Entity Action Types"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.blockComponents, "/BlockReference/Examples/BlockComponents/", "/block/minecraft_", "Block Components", "Block Component"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.itemComponents, "/ItemReference/Examples/ItemComponents/", "/item/minecraft_", "Items", "Item Component"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.entityComponents, "/EntityReference/Examples/EntityComponents/", "/entity/minecraft_", "Entity", "Entity Component"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.deferredRendering, "/DeferredRendering/", "/client_deferred_rendering/", "Deferred Rendering", "Deferred Rendering"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.clientBiomes, "/ClientBiomesReference/Examples/Components/", "/client_biome/", "Client Biome", "Client Biome"); this.exportMarkdownCatalogDocs(formsByPath, outputFolder, ExportMode.biomes, "/BiomesReference/Examples/Components/", "/biome/", "Biome", "Biome"); this.exportMarkdownDocListPage(formsByPath, outputFolder, ExportMode.entityComponents, "/EntityReference/Examples/ComponentList.md", "/entity/minecraft_", "Entity Components", "EntityComponents"); this.exportListYml(formsByPath, outputFolder, ExportMode.entityComponents, "/EntityReference/Examples/EntityComponents/TOC.yml", "/entity/minecraft_", "- name: Components List\r\n href: ../ComponentList.md", "minecraftComponent_"); this.exportMarkdownDocListPage(formsByPath, outputFolder, ExportMode.triggers, "/EntityReference/Examples/TriggerList.md", "/entity/minecraft_on", "Entity Triggers", "EntityTriggers"); this.exportListYml(formsByPath, outputFolder, ExportMode.entityComponents, "/EntityReference/Examples/EntityTriggers/TOC.yml", "/entity/minecraft_on", "- name: Triggers List\r\n href: ../TriggerList.md", "minecraftTrigger_"); this.exportMarkdownDocListPage(formsByPath, outputFolder, ExportMode.AIGoals, "/EntityReference/Examples/AIGoalList.md", "/entity/minecraft_behavior", "Entity Behavior (AI) Components", "EntityGoals"); this.exportListYml(formsByPath, outputFolder, ExportMode.AIGoals, "/EntityReference/Examples/EntityGoals/TOC.yml", "/entity/minecraft_behavior", "- name: AI Component List\r\n href: ../AIGoalList.md"); this.exportMarkdownDocListPage(formsByPath, outputFolder, ExportMode.filters, "/EntityReference/Examples/FilterList.md", "/entityfilters/", "Entity Filter Types", "Filters"); this.exportListYml(formsByPath, outputFolder, ExportMode.filters, "/EntityReference/Examples/Filters/TOC.yml", "/entityfilters/", "- name: Entity Filter List\r\n href: ../FilterList.md"); this.exportMarkdownDocListPage(formsByPath, outputFolder, ExportMode.eventResponses, "/EntityReference/Examples/EventActions.md", "/entityevents/", "Event Actions", "EventActions"); this.exportListYml(formsByPath, outputFolder, ExportMode.eventResponses, "/EntityReference/Examples/EventActions/TOC.yml", "/entityevents/", "- name: Entity Event List\r\n href: ../EventActions.md"); } getFileNameFromBaseName(baseName, exportMode) { let fileName = baseName; if (exportMode === ExportMode.triggers && fileName.startsWith("minecraft_on_")) { fileName = "minecraftTrigger_" + baseName.substring(10); } else if (exportMode === ExportMode.triggers && fileName.startsWith("minecraft_on_")) { fileName = "minecraftTrigger_" + baseName.substring(10); } else if (exportMode === ExportMode.AIGoals && fileName.startsWith("minecraft_behavior")) { fileName = "minecraftB" + baseName.substring(11); } else if (exportMode === ExportMode.entityComponents && fileName.startsWith("minecraft_")) { fileName = "minecraftComponent_" + baseName.substring(10); } else if (exportMode === ExportMode.blockComponents && fileName.startsWith("minecraft_")) { fileName = "minecraftBlock_" + baseName.substring(10); } else if (exportMode === ExportMode.itemComponents && fileName.startsWith("minecraft_")) { fileName = "minecraft_" + baseName.substring(10); } else if (exportMode === ExportMode.clientBiomes && fileName.startsWith("minecraft_")) { fileName = "minecraftClientBiomes_" + baseName.substring(10); } else if (exportMode === ExportMode.biomes && fileName.startsWith("minecraft_")) { fileName = "minecraftBiomes_" + baseName.substring(10); } fileName = fileName.replace("_horse_", "_horse."); fileName = fileName.replace("_jump_", "_jump."); if (fileName.indexOf("movement_tracking") < 0) { fileName = fileName.replace("_movement_", "_movement."); } fileName = fileName.replace("_navigation_", "_navigation."); fileName = fileName.replace("_player_", "_player."); return fileName; } async exportMarkdownAggregatedPage(formsByPath, outputFolder, exportMode, filePath, formsPath, category, categoryExtended) { const targetFolder = await outputFolder.ensureFolderFromRelativePath(filePath); if (!targetFolder) { return; } let hasEnsuredFolder = false; formsByPath = this.getFormsFromFilter(formsByPath, formsPath, exportMode); for (const formPath in formsByPath) { const formO = formsByPath[formPath]; if (formO) { let baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(formPath)); if (baseName.endsWith(".form")) { baseName = baseName.substring(0, baseName.length - 5); } if (!hasEnsuredFolder) { await targetFolder.ensureExists(); hasEnsuredFolder = true; } let fileName = this.getFileNameFromBaseName(baseName, exportMode); const markdownFile = targetFolder.ensureFile(fileName + ".md"); await this.saveMarkdownDocFromForm(markdownFile, formO, baseName, exportMode, category, categoryExtended); } } } async exportValidatorMarkdownCatalogDocs(formsByPath, outputFolder, exportMode, subFolderPath, formsPath, categoryPlural, categorySingular) { const targetFolder = await outputFolder.ensureFolderFromRelativePath(subFolderPath); if (!targetFolder) { return; } let hasEnsuredFolder = false; formsByPath = this.getFormsFromFilter(formsByPath, formsPath, exportMode); for (const formPath in formsByPath) { const formO = formsByPath[formPath]; if (formO) { let baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(formPath)); if (baseName.endsWith(".form")) { baseName = baseName.substring(0, baseName.length - 5); } if (!hasEnsuredFolder) { await targetFolder.ensureExists(); hasEnsuredFolder = true; } let fileName = this.getFileNameFromBaseName(baseName, exportMode); const markdownFile = targetFolder.ensureFile(fileName + ".md"); await this.saveValidatorMarkdownDocFromForm(markdownFile, formO, baseName, exportMode, categoryPlural, categorySingular); } } } async exportMarkdownCatalogDocs(formsByPath, outputFolder, exportMode, subFolderPath, formsPath, categoryPlural, categorySingular) { const targetFolder = await outputFolder.ensureFolderFromRelativePath(subFolderPath); if (!targetFolder) { return; } let hasEnsuredFolder = false; formsByPath = this.getFormsFromFilter(formsByPath, formsPath, exportMode); for (const formPath in formsByPath) { const formO = formsByPath[formPath]; if (formO) { let baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(formPath)); if (baseName.endsWith(".form")) { baseName = baseName.substring(0, baseName.length - 5); } if (!hasEnsuredFolder) { await targetFolder.ensureExists(); hasEnsuredFolder = true; } let fileName = this.getFileNameFromBaseName(baseName, exportMode); const markdownFile = targetFolder.ensureFile(fileName + ".md"); await this.saveMarkdownDocFromForm(markdownFile, formO, baseName, exportMode, categoryPlural, categorySingular); } } } async exportMarkdownDocListPage(formsByPath, outputFolder, exportMode, subFolderPath, formsPath, category, subFolderName) { const targetFile = await outputFolder.ensureFileFromRelativePath(subFolderPath); if (!targetFile) { return; } formsByPath = this.getFormsFromFilter(formsByPath, formsPath, exportMode); const content = []; content.push(Utilities_1.default.stringFormat(exports.MarkdownTop, category + " Documentation - " + category, "A reference document describing all current " + category)); let internalDepCount = 0; content.push("| " + category + " | Description |"); content.push("|:-----|:----------|"); for (const formPath in formsByPath) { const formO = formsByPath[formPath]; if (formO && !formO.isDeprecated && !formO.isInternal) { let baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(formPath)); if (baseName.endsWith(".form")) { baseName = baseName.substring(0, baseName.length - 5); } let canonName = EntityTypeDefinition_1.default.getComponentFromBaseFileName(baseName); if (formO.id) { canonName = formO.id; } else if (formO.title) { canonName = formO.title; } content.push("| [" + canonName + "](" + subFolderName + "/" + this.getFileNameFromBaseName(baseName, exportMode) + ".md)| " + (formO.description ? this.sanitizeForTable(this.getFirstSentence(formO.description)) : "") + " |"); } else if (formO) { internalDepCount++; } } if (internalDepCount > 0) { content.push(""); content.push("## Internal/Deprecated Components"); content.push("These components are either deprecated or internal to Minecraft and not usable in custom content."); content.push(""); content.push("| " + category + " | Description |"); content.push("|:-----|:----------|"); for (const formPath in formsByPath) { const formO = formsByPath[formPath]; if (formO && (formO.isDeprecated || formO.isInternal)) { let baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(formPath)); if (baseName.endsWith(".form")) { baseName = baseName.substring(0, baseName.length - 5); } let canonName = EntityTypeDefinition_1.default.getComponentFromBaseFileName(baseName); content.push("| [" + canonName + "](" + subFolderName + "/" + this.getFileNameFromBaseName(baseName, exportMode) + ".md)| " + (formO.description ? this.sanitizeForTable(this.getFirstSentence(formO.description)) : "") + " |"); } } } targetFile.setContent(content.join("\r\n")); await targetFile.saveContent(); } async exportListYml(formsByPath, outputFolder, exportMode, subFolderPath, formsPath, header, prefix) { const targetFile = await outputFolder.ensureFileFromRelativePath(subFolderPath); if (!targetFile) { return; } const content = []; if (header) { content.push(header); } formsByPath = this.getFormsFromFilter(formsByPath, formsPath, exportMode); for (const formPath in formsByPath) { const formO = formsByPath[formPath]; if (formO && !formO.isDeprecated && !formO.isInternal) { let baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(formPath)); if (baseName.endsWith(".form")) { baseName = baseName.substring(0, baseName.length - 5); } if (prefix && baseName.startsWith("minecraftComponent_")) { baseName = prefix + baseName.substring(19); } else if (prefix && baseName.startsWith("minecraft_")) { baseName = prefix + baseName.substring(10); } else if (prefix) { baseName = prefix + baseName; } content.push("- name: " + (formO.id ? formO.id : formO.title)); content.push(" href: " + this.getFileNameFromBaseName(baseName, exportMode) + ".md"); } } targetFile.setContent(content.join("\r\n")); await targetFile.saveContent(); } getFirstSentence(description) { let endOfSentence = description.indexOf(". "); if (endOfSentence >= 0) { description = description.substring(0, endOfSentence + 1); } return description; } async saveMarkdownDocFromForm(markdownFile, form, baseName, exportMode, category, categoryExtended) { const content = []; let canonName = "minecraft:" + EntityTypeDefinition_1.default.getComponentFromBaseFileName(baseName); if (exportMode === ExportMode.websockets && form.id) { canonName = form.id; } content.push(Utilities_1.default.stringFormat(exports.MarkdownTop, category + " Documentation - " + canonName, "Describes the " + canonName + " " + categoryExtended.toLowerCase())); content.push("# " + category + " Documentation - " + canonName + "\r\n"); if (form.isDeprecated) { content.push("> [!IMPORTANT]"); content.push("> This type is now deprecated, and no longer in use in the latest versions of Minecraft."); content.push(""); } if (form.isInternal) { content.push("> [!IMPORTANT]"); content.push("> This type is internal to vanilla Minecraft usage, and is not functional or supported within custom Minecraft content."); content.push(""); } await this.appendForm(form, content, 0); if (form.samples) { content.push("\r\n## Samples\r\n"); let samplesAdded = 0; const linesAdded = []; for (const samplePath in form.samples) { let sampleArr = form.samples[samplePath]; let addedHeader = false; if (sampleArr && samplesAdded < 12) { const sampBaseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(samplePath)); let targetPath = samplePath; if (!Array.isArray(sampleArr)) { console.log("Malformed sample node at `" + samplePath + "` for file at `" + markdownFile.fullPath + "`"); } else { for (const sample of sampleArr) { let line = "\r\n```json\r\n"; if (baseName.startsWith("minecraft_") && (typeof sample.content !== "string" || !sample.content.startsWith("minecraft:"))) { line += '"' + canonName + '": '; } if (typeof sample.content === "object" || Array.isArray(sample.content)) { line += JSON.stringify(sample.content, undefined, 2) + "\r\n```\r\n"; } else { if (typeof sample.content === "string") { let cont = sample.content.trim(); if (cont.startsWith("{") && cont.endsWith("}")) { line += cont + "\r\n```\r\n"; } else { line += '"' + cont + '"\r\n```\r\n'; } } else { line += sample.content + "\r\n```\r\n"; } } if (!linesAdded.includes(line)) { if (!addedHeader) { addedHeader = true; if (targetPath !== "samples" && targetPath !== "sample") { if (targetPath.startsWith("/vanilla")) { targetPath = "https://github.com/Mojang/bedrock-samples/tree/preview" + targetPath.substring(8); } else if (targetPath.startsWith("/samples")) { targetPath = "https://github.com/microsoft/minecraft-samples/tree/main" + targetPath.substring(8); } content.push("#### [" + Utilities_1.default.humanifyMinecraftName(sampBaseName.substring(0, 1).toUpperCase() + sampBaseName.substring(1)) + "](" + targetPath + ")\r\n"); } } if (sampleArr.length > 1) { content.push("At " + sample.path + ": "); } linesAdded.push(line); content.push(line); samplesAdded++; } } } } } } markdownFile.setContent(content.join("\r\n")); await markdownFile.saveContent(); } async saveValidatorMarkdownDocFromForm(markdownFile, form, baseName, exportMode, category, categoryExtended) { const content = []; let canonName = "minecraft:" + EntityTypeDefinition_1.default.getComponentFromBaseFileName(baseName); if (exportMode === ExportMode.websockets && form.id) { canonName = form.id; } content.push(Utilities_1.default.stringFormat(exports.MarkdownTop, category + " Documentation - " + canonName, "Describes the " + canonName + " " + categoryExtended.toLowerCase())); content.push("# " + category + " Documentation - " + canonName + "\r\n"); if (form.isDeprecated) { content.push("> [!IMPORTANT]"); content.push("> This type is now deprecated, and no longer in use in the latest versions of Minecraft."); content.push(""); } await this.appendValidatorForm(form, content, 0); markdownFile.setContent(content.join("\r\n")); await markdownFile.saveContent(); } sanitizeDescription(description) { description = description.trim(); if (description.length > 10 && !description.endsWith(".") && !description.endsWith(":")) { description += "."; } return description; } getFileNameFromJsonKey(key) { key = key.toLowerCase(); key = key.replace(/ /gi, "_"); key = key.replace(/::/gi, "_"); key = key.replace(/:/gi, "_"); return key; } async appendForm(form, content, depth, altTitle) { if (form.description) { content.push(this.sanitizeDescription(form.description) + "\r\n"); } if (form.note) { content.push("> [!Note]"); content.push("> " + this.sanitizeDescription(form.note) + "\r\n"); } if (form.note2) { content.push("> [!Note]"); content.push("> " + this.sanitizeDescription(form.note2) + "\r\n"); } if (form.note3) { content.push("> [!Note]"); content.push("> " + this.sanitizeDescription(form.note3) + "\r\n"); } if (form.requires) { let descStr = ""; const entityComponents = []; if (!Array.isArray(form.requires)) { console.log("Malformed requires node at `" + JSON.stringify(form.requires) + "`"); } else { for (const dep of form.requires) { if (dep.type === "tame_owner") { content.push("> [!Note]"); content.push("> Requires a player to be set as the tame owner via taming (or the `tame` command, or the tame API on EntityTameableComponent) in order to work properly."); } else if (dep.type === "targeting_entity_component") { content.push("> [!Note]"); content.push("> Requires a target in order to work properly. Entities can generate targets via one of the following behaviors:"); content.push("> "); content.push("> * [minecraft:behavior.nearest_attackable_target](../EntityGoals/minecraftBehavior_nearest_attackable_target.md)"); content.push("> * [minecraft:behavior.hurt_by_target](../EntityGoals/minecraftBehavior_hurt_by_target.md)"); } else if (dep.type === "entity_component" || dep.type === "item_component" || dep.type === "block_component") { if (dep.description) { if (descStr.length > 0) { descStr += " "; } descStr += dep.description; } entityComponents.push(dep.id); } } } if (entityComponents.length > 0) { content.push("> [!Note]"); if (entityComponents.length === 1) { content.push("> Requires the following component in order to work properly:"); } else { content.push("> Requires the following components in order to work properly:"); } content.push("> "); for (const entityComponent of entityComponents) { content.push("> * [" + Utilities_1.default.humanifyMinecraftName(entityComponent) + " (" + entityComponent + ")](../EntityComponents/minecraftComponent_" + this.getFileNameFromJsonKey(entityComponent.substring(10)) + ".md)"); } if (descStr.length >= 0) { content.push("> " + descStr); } } } if (form.restrictions) { const entityTypes = []; let descStr = ""; for (const restriction of form.restrictions) { if (restriction.type === "entity_type") { entityTypes.push(restriction.id); if (restriction.description) { if (descStr.length > 0) { descStr += " "; } descStr += restriction.description; } } } if (entityTypes.length > 0) { content.push("> [!Note]"); if (entityTypes.length === 1) { content.push("> Can only be used on the following type of entity:"); } else { content.push("> Can only be used on the following types of entity:"); } content.push("> "); for (const entityType of entityTypes) { content.push("> * " + Utilities_1.default.humanifyMinecraftName(entityType) + " (" + entityType + ")"); } if (descStr.length >= 0) { content.push("> " + descStr); } } } const scalarField = DataFormUtilities_1.default.getScalarField(form); if (scalarField) { content.push("## Alternate Simple Representations\r\n"); for (const scalarFieldInst of DataFormUtilities_1.default.getFieldAndAlternates(scalarField)) { content.push("This item can also be represented as a `" + DataFormUtilities_1.default.getFieldTypeDescription(scalarFieldInst.dataType) + "`."); } content.push(""); } let title = undefined; if (form.title) { if (form.title === form.id) { title = Utilities_1.default.humanifyMinecraftName(form.id); } else { title = form.title; } } else if (form.id) { title = Utilities_1.default.humanifyMinecraftName(form.id); } else if (altTitle) { title = altTitle; } else { title = "Item"; } if (form.fields && form.fields.length > 0) { const subContent = []; if (depth > 0) { content.push("\r\n#### " + title + " Properties\r\n"); } else { content.push("\r\n## " + title + " Properties\r\n"); } content.push("|Name |Default Value |Type |Description |Example Values |"); content.push("|:----------|:-------------|:----|:-----------|:------------- |"); form.fields.sort((a, b) => { return a.id.localeCompare(b.id); }); let fullFieldList = []; for (const field of form.fields) { fullFieldList.push(field); if (field.alternates) { let i = 0; for (const altField of field.alternates) { i++; if (!altField.id || altField.id === field.id) { altField.id = field.id + " (Alternate " + i + ")"; } fullFieldList.push(altField); } } } for (const field of fullFieldList) { let fieldRow = "| " + field.id + " | "; if (field.defaultValue !== undefined) { fieldRow += this.getValueAsString(field.defaultValue); } else { fieldRow += "*not set*"; } const fieldName = Utilities_1.default.humanifyMinecraftName(field.id); const fieldLink = "(#" + this.getMarkdownBookmark(fieldName) + "-" + (field.choices ? "choices" : "item-type") + ")"; let subForm = field.subForm; if (!subForm && field.subFormId) { subForm = await Database_1.default.ensureFormLoadedByPath(field.subFormId); } if (subForm && subForm.fields && subForm.fields.length > 0) { if (field.dataType === IField_1.FieldDataType.objectArray) { fieldRow += " | Array of [" + fieldName + "]" + fieldLink + " items | "; } else if (field.dataType === IField_1.FieldDataType.keyedObjectCollection) { fieldRow += " | Key/item pairs of [" + fieldName + "]" + fieldLink + " items | "; } else { fieldRow += " | [" + fieldName + "]" + fieldLink + " item | "; } } else if (field.choices) { fieldRow += " | [" + fieldName + "]" + fieldLink + " choices | "; subContent.push("\r\n### " + fieldName + " choices\r\n"); subContent.push("|Value |Title |Description |"); subContent.push("|:-----------|:-----|:-----------|"); for (const choice of field.choices) { let choiceRow = ""; choiceRow += "| " + choice.id; choiceRow += " | " + (choice.title ? this.sanitizeForTable(choice.title) : Utilities_1.default.humanifyMinecraftName(choice.id)); choiceRow += " | " + (choice.description ? this.sanitizeForTable(choice.description) : "") + "|"; subContent.push(choiceRow); } } else if (field.dataType === IField_1.FieldDataType.minecraftEventTrigger) { fieldRow += " | [" + DataFormUtilities_1.default.getFieldTypeDescription(field.dataType) + "](../Definitions/NestedTables/triggers.md) | "; } else { let fieldTypes = ""; fieldTypes = DataFormUtilities_1.default.getFieldTypeDescription(field.dataType); fieldRow += " | " + fieldTypes + " | "; } if (field.description) { let descrip = field.description; descrip += " " + this.addAdditionalNotes(field); descrip = descrip.trim(); fieldRow += this.sanitizeForTable(descrip); if (field.note) { fieldRow += " " + this.sanitizeForTable(field.note); } if (field.note2) { fieldRow += " " + this.sanitizeForTable(field.note2); } if (field.note3) { fieldRow += " " + this.sanitizeForTable(field.note3); } } fieldRow += " | "; if (subForm && subForm.fields.length > 0) { subContent.push("\r\n## " + fieldName + " item type"); await this.appendForm(subForm, subContent, depth + 1, fieldName); } if (field.samples) { let samplesAdded = 0; const samplesUsed = []; let addedKey = false; for (const samplePath in field.samples) { let sampleArr = field.samples[samplePath]; if (sampleArr && samplesAdded < 3) { const sampleSet = {}; for (const sample of sampleArr) { const sampleVal = JSON.stringify(sample.content); if (!samplesUsed.includes(sampleVal)) { samplesUsed.push(sampleVal); const baseName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(samplePath)); samplesAdded++; const key = baseName.substring(0, 1).toUpperCase() + baseName.substring(1); if (!sampleSet[key]) { sampleSet[key] = "`" + sampleVal + "`"; } else { sampleSet[key] = sampleSet[key] + ", `" + sampleVal + "`"; } } } for (const key in sampleSet) { if (addedKey) { fieldRow += ", "; } fieldRow += Utilities_1.default.humanifyMinecraftName(key) + ": " + this.sanitizeForTable(sampleSet[key]); addedKey = true; } } } } fieldRow += " | "; content.push(fieldRow); } content.push(...subContent); } } addAdditionalNotes(field) { let descrip = ""; if (field.minLength) { descrip += "Value must have at least " + field.minLength + " items. "; } if (field.maxLength) { descrip += "Value must have at most " + field.maxLength + " items. "; } if (field.validity) { for (const cond of field.validity) { if (cond.comparison === ICondition_1.ComparisonType.matchesPattern) { descrip += 'Value must be match patern "' + cond.value + '". '; } else if (cond.comparison) { descrip += "Value must be " + cond.comparison + " " + cond.value + ". "; } } } return descrip; } async appendValidatorForm(form, content, depth, altTitle) { if (form.description) { content.push(this.sanitizeDescription(form.description) + "\r\n"); } if (form.note) { content.push("> [!Note]"); content.push("> " + this.sanitizeDescription(form.note) + "\r\n"); } if (form.note2) { content.push("> [!Note]"); content.push("> " + this.sanitizeDescription(form.note2) + "\r\n"); } if (form.note3) { content.push("> [!Note]"); content.push("> " + this.sanitizeDescription(form.note3) + "\r\n"); } let title = undefined; if (form.title) { if (form.title === form.id) { title = Utilities_1.default.humanifyMinecraftName(form.id); } else { title = form.title; } } else if (form.id) { title = Utilities_1.default.humanifyMinecraftName(form.id); } else if (altTitle) { title = altTitle; } else { title = "Item"; } if (form.fields && form.fields.length > 0) { const subContent = []; if (depth > 0) { content.push("\r\n#### " + title + " Properties\r\n"); } else { content.push("\r\n## " + title + " Properties\r\n"); } content.push("|Name |Description |"); content.push("|:----------|:-------------|"); form.fields.sort((a, b) => { return a.id.localeCompare(b.id); }); let fullFieldList = []; for (const field of form.fields) { fullFieldList.push(field); if (field.alternates) { let i = 0; for (const altField of field.alternates) { i++; if (!altField.id || altField.id === field.id) { altField.id = field.id + " (Alternate " + i + ")"; } fullFieldList.push(altField); } } } for (const field of fullFieldList) { let fieldRow = "| " + field.id + " | "; if (field.description) { fieldRow += this.sanitizeForTable(field.description); if (field.note) { fieldRow += " " + this.sanitizeForTable(field.note); } if (field.note2) { fieldRow += " " + this.sanitizeForTable(field.note2); } if (field.note3) { fieldRow += " " + this.sanitizeForTable(field.note3); } } fieldRow += " | "; content.push(fieldRow); } content.push(...subContent); } } getValueAsString(value) { if (Array.isArray(value)) { let result = "["; let index = 0; for (const subVal of value) { if (index > 0) { result += ", "; } result += subVal.toString(); index++; } return result + "]"; } return value.toString(); } sanitizeForTable(value) { value = value.replace(/\\r/gi, " "); value = value.replace(/\\t/gi, " "); value = value.replace(/\\n/gi, "<br>"); value = value.replace(/\\"/gi, '"'); value = value.replace(/\r/gi, " "); value = value.replace(/\n/gi, "<br>"); value = value.replace(/ /gi, " "); value = value.replace(/ /gi, " "); value = value.trim(); return value; } getMarkdownBookmark(id) { return id.toLowerCase().replace(/ /gi, "-"); } getFormsFromFilter(formsByPath, formsPath, mode) { const filteredList = {}; for (const formPath in formsByPath) { let includeFile = true; if (formPath.indexOf("index") >= 0 || formPath.indexOf("overview") >= 0 || formPath.indexOf("describes") >= 0 || formPath.indexOf("versioned") >= 0) { includeFile = false; } if (includeFile && formPath.toLowerCase().startsWith(formsPath) && formsByPath[formPath] && (formsPath.indexOf("behavior") >= 0 || formPath.indexOf("behavior") < 0) && (formsPath.indexOf("_on") >= 0 || formPath.indexOf("minecraft_on") < 0)) { filteredList[formPath] = formsByPath[formPath]; } } return filteredList; } async loadFormJsonFromFolder(formsByPath, inputFolder, outputFolder) { await inputFolder.load(); const fileList = { files: [], folders: [] }; for (const folderName in inputFolder.folders) { const folder = inputFolder.folders[folderName]; if (folder) { await this.loadFormJsonFromFolder(formsByPath, folder, outputFolder.ensureFolder(folderName)); fileList.folders.push(folderName); } } for (const fileName in inputFolder.files) { const file = inputFolder.files[fileName]; if (file) { await file.loadContent(); const jsonO = StorageUtilities_1.default.getJsonObject(file); if (jsonO) { formsByPath[file.storageRelativePath] = jsonO; } } } } } exports.default = FormMarkdownDocumentationGenerator; //# sourceMappingURL=../maps/docgen/FormMarkdownDocumentationGenerator.js.map