intelligent-system-design-language 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/langium-language-designer.md +38 -0
- package/.claude/agents/typescript-vscode-expert.md +29 -0
- package/.claude/agents/ui-ux-designer.md +36 -0
- package/.claude/settings.local.json +33 -0
- package/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/.idea/isdl.iml +14 -0
- package/.idea/modules.xml +9 -0
- package/.idea/vcs.xml +7 -0
- package/.idea/watcherTasks.xml +4 -0
- package/.vscodeignore +18 -0
- package/LICENSE +674 -0
- package/README.md +86 -0
- package/bin/cli.js +4 -0
- package/bin/lsp.js +8 -0
- package/isdl.png +0 -0
- package/out/_backgrounds.scss +91 -0
- package/out/_handlebars.scss +505 -0
- package/out/_isdlStyles.scss +1357 -0
- package/out/_vuetifyOverrides.scss +425 -0
- package/out/_vuetifyStyles.scss +31957 -0
- package/out/cli/cli-util.js +39 -0
- package/out/cli/cli-util.js.map +1 -0
- package/out/cli/components/_backgrounds.scss +91 -0
- package/out/cli/components/_handlebars.scss +505 -0
- package/out/cli/components/_isdlStyles.scss +1357 -0
- package/out/cli/components/_vuetifyOverrides.scss +425 -0
- package/out/cli/components/_vuetifyStyles.scss +31957 -0
- package/out/cli/components/active-effect-sheet-generator.js +643 -0
- package/out/cli/components/active-effect-sheet-generator.js.map +1 -0
- package/out/cli/components/base-actor-sheet-generator.js +125 -0
- package/out/cli/components/base-actor-sheet-generator.js.map +1 -0
- package/out/cli/components/base-sheet-generator.js +525 -0
- package/out/cli/components/base-sheet-generator.js.map +1 -0
- package/out/cli/components/chat-card-generator.js +683 -0
- package/out/cli/components/chat-card-generator.js.map +1 -0
- package/out/cli/components/css-generator.js +58 -0
- package/out/cli/components/css-generator.js.map +1 -0
- package/out/cli/components/damage-roll-generator.js +173 -0
- package/out/cli/components/damage-roll-generator.js.map +1 -0
- package/out/cli/components/datamodel-generator.js +672 -0
- package/out/cli/components/datamodel-generator.js.map +1 -0
- package/out/cli/components/derived-data-generator.js +1340 -0
- package/out/cli/components/derived-data-generator.js.map +1 -0
- package/out/cli/components/hotbar-drop-hook-generator.js +95 -0
- package/out/cli/components/hotbar-drop-hook-generator.js.map +1 -0
- package/out/cli/components/init-hook-generator.js +597 -0
- package/out/cli/components/init-hook-generator.js.map +1 -0
- package/out/cli/components/keywords-generator.js +220 -0
- package/out/cli/components/keywords-generator.js.map +1 -0
- package/out/cli/components/language-generator.js +110 -0
- package/out/cli/components/language-generator.js.map +1 -0
- package/out/cli/components/measured-template-preview.js +234 -0
- package/out/cli/components/measured-template-preview.js.map +1 -0
- package/out/cli/components/method-generator.js +1812 -0
- package/out/cli/components/method-generator.js.map +1 -0
- package/out/cli/components/ready-hook-generator.js +448 -0
- package/out/cli/components/ready-hook-generator.js.map +1 -0
- package/out/cli/components/token-generator.js +138 -0
- package/out/cli/components/token-generator.js.map +1 -0
- package/out/cli/components/utils.js +176 -0
- package/out/cli/components/utils.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-attribute.js +148 -0
- package/out/cli/components/vue/base-components/vue-attribute.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-boolean.js +77 -0
- package/out/cli/components/vue/base-components/vue-boolean.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-calculator.js +106 -0
- package/out/cli/components/vue/base-components/vue-calculator.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-application.js +369 -0
- package/out/cli/components/vue/base-components/vue-damage-application.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-bonuses.js +225 -0
- package/out/cli/components/vue/base-components/vue-damage-bonuses.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-resistances.js +256 -0
- package/out/cli/components/vue/base-components/vue-damage-resistances.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-track.js +134 -0
- package/out/cli/components/vue/base-components/vue-damage-track.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-date-time.js +55 -0
- package/out/cli/components/vue/base-components/vue-date-time.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-dice.js +111 -0
- package/out/cli/components/vue/base-components/vue-dice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-die.js +86 -0
- package/out/cli/components/vue/base-components/vue-die.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-document-choice.js +172 -0
- package/out/cli/components/vue/base-components/vue-document-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-document-choices.js +203 -0
- package/out/cli/components/vue/base-components/vue-document-choices.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-document-link.js +73 -0
- package/out/cli/components/vue/base-components/vue-document-link.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-extended-choice.js +101 -0
- package/out/cli/components/vue/base-components/vue-extended-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-inventory.js +532 -0
- package/out/cli/components/vue/base-components/vue-inventory.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-macro-choice.js +150 -0
- package/out/cli/components/vue/base-components/vue-macro-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-measured-template.js +543 -0
- package/out/cli/components/vue/base-components/vue-measured-template.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-money.js +496 -0
- package/out/cli/components/vue/base-components/vue-money.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-number.js +184 -0
- package/out/cli/components/vue/base-components/vue-number.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-paperdoll.js +56 -0
- package/out/cli/components/vue/base-components/vue-paperdoll.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-parent-property-reference.js +89 -0
- package/out/cli/components/vue/base-components/vue-parent-property-reference.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-prosemirror.js +31 -0
- package/out/cli/components/vue/base-components/vue-prosemirror.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-resource.js +149 -0
- package/out/cli/components/vue/base-components/vue-resource.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js +121 -0
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-self-property-reference.js +75 -0
- package/out/cli/components/vue/base-components/vue-self-property-reference.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-string-choice.js +111 -0
- package/out/cli/components/vue/base-components/vue-string-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-string-choices.js +216 -0
- package/out/cli/components/vue/base-components/vue-string-choices.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-string.js +73 -0
- package/out/cli/components/vue/base-components/vue-string.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-text-field.js +66 -0
- package/out/cli/components/vue/base-components/vue-text-field.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-tracker.js +444 -0
- package/out/cli/components/vue/base-components/vue-tracker.js.map +1 -0
- package/out/cli/components/vue/vue-action-component-generator.js +88 -0
- package/out/cli/components/vue/vue-action-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-active-effect-sheet-generator.js +1016 -0
- package/out/cli/components/vue/vue-active-effect-sheet-generator.js.map +1 -0
- package/out/cli/components/vue/vue-base-components-generator.js +59 -0
- package/out/cli/components/vue/vue-base-components-generator.js.map +1 -0
- package/out/cli/components/vue/vue-datatable-component-generator.js +307 -0
- package/out/cli/components/vue/vue-datatable-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-datatable-sheet-class-generator.js +342 -0
- package/out/cli/components/vue/vue-datatable-sheet-class-generator.js.map +1 -0
- package/out/cli/components/vue/vue-datatable2-component-generator.js +939 -0
- package/out/cli/components/vue/vue-datatable2-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-document-creation-app.js +140 -0
- package/out/cli/components/vue/vue-document-creation-app.js.map +1 -0
- package/out/cli/components/vue/vue-document-creation-sheet.js +105 -0
- package/out/cli/components/vue/vue-document-creation-sheet.js.map +1 -0
- package/out/cli/components/vue/vue-generator.js +240 -0
- package/out/cli/components/vue/vue-generator.js.map +1 -0
- package/out/cli/components/vue/vue-mixin.js +338 -0
- package/out/cli/components/vue/vue-mixin.js.map +1 -0
- package/out/cli/components/vue/vue-pinned-datatable-component-generator.js +306 -0
- package/out/cli/components/vue/vue-pinned-datatable-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-prompt-generator.js +201 -0
- package/out/cli/components/vue/vue-prompt-generator.js.map +1 -0
- package/out/cli/components/vue/vue-prompt-sheet-class-generator.js +252 -0
- package/out/cli/components/vue/vue-prompt-sheet-class-generator.js.map +1 -0
- package/out/cli/components/vue/vue-sheet-application-generator.js +2008 -0
- package/out/cli/components/vue/vue-sheet-application-generator.js.map +1 -0
- package/out/cli/components/vue/vue-sheet-class-generator.js +484 -0
- package/out/cli/components/vue/vue-sheet-class-generator.js.map +1 -0
- package/out/cli/generator.js +659 -0
- package/out/cli/generator.js.map +1 -0
- package/out/cli/main.js +43 -0
- package/out/cli/main.js.map +1 -0
- package/out/datatables.min.css +54 -0
- package/out/datatables.min.js +178 -0
- package/out/extension/github/githubAuthProvider.js +345 -0
- package/out/extension/github/githubAuthProvider.js.map +1 -0
- package/out/extension/github/githubConfig.js +132 -0
- package/out/extension/github/githubConfig.js.map +1 -0
- package/out/extension/github/githubGistActions.js +251 -0
- package/out/extension/github/githubGistActions.js.map +1 -0
- package/out/extension/github/githubGistManager.js +255 -0
- package/out/extension/github/githubGistManager.js.map +1 -0
- package/out/extension/github/githubManager.js +1735 -0
- package/out/extension/github/githubManager.js.map +1 -0
- package/out/extension/github/githubQuickActions.js +659 -0
- package/out/extension/github/githubQuickActions.js.map +1 -0
- package/out/extension/github/githubTreeProvider.js +181 -0
- package/out/extension/github/githubTreeProvider.js.map +1 -0
- package/out/extension/github/system-workflow.yml +48 -0
- package/out/extension/main.cjs +70315 -0
- package/out/extension/main.cjs.map +7 -0
- package/out/extension/main.js +237 -0
- package/out/extension/main.js.map +1 -0
- package/out/extension/package.json +426 -0
- package/out/isdl.png +0 -0
- package/out/language/generated/ast.js +2992 -0
- package/out/language/generated/ast.js.map +1 -0
- package/out/language/generated/grammar.js +13970 -0
- package/out/language/generated/grammar.js.map +1 -0
- package/out/language/generated/module.js +20 -0
- package/out/language/generated/module.js.map +1 -0
- package/out/language/intelligent-system-design-language-formatter.js +85 -0
- package/out/language/intelligent-system-design-language-formatter.js.map +1 -0
- package/out/language/intelligent-system-design-language-module.js +69 -0
- package/out/language/intelligent-system-design-language-module.js.map +1 -0
- package/out/language/intelligent-system-design-language-quickfixes.js +37 -0
- package/out/language/intelligent-system-design-language-quickfixes.js.map +1 -0
- package/out/language/intelligent-system-design-language-validator.js +515 -0
- package/out/language/intelligent-system-design-language-validator.js.map +1 -0
- package/out/language/isdl-hover-provider.js +77 -0
- package/out/language/isdl-hover-provider.js.map +1 -0
- package/out/language/isdl-scope-provider.js +149 -0
- package/out/language/isdl-scope-provider.js.map +1 -0
- package/out/language/main.cjs +47655 -0
- package/out/language/main.cjs.map +7 -0
- package/out/language/main.js +11 -0
- package/out/language/main.js.map +1 -0
- package/out/missing-character.png +0 -0
- package/out/package.json +426 -0
- package/out/paperdoll_default.png +0 -0
- package/out/progressbar.min.js +7 -0
- package/out/styles.scss +722 -0
- package/out/test/formatting/formatter.test.js +46 -0
- package/out/test/formatting/formatter.test.js.map +1 -0
- package/out/vuetify.esm.js +30279 -0
- package/package.json +426 -0
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import { expandToNode, joinToNode, toString } from 'langium/generate';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { isAccess, isAction, isActor, isAttributeExp, isBooleanExp, isHookHandler, isHtmlExp, isIfStatement, isInitiativeProperty, isNumberExp, isNumberParamValue, isProperty, isResourceExp, isSection, isStatusProperty, isStringExp, isTrackerExp, isLayout, isMacroField, isDamageTypeChoiceField, isStringParamChoices } from '../../language/generated/ast.js';
|
|
5
|
+
import { getSystemPath, getAllOfType } from './utils.js';
|
|
6
|
+
export function generateBaseActiveEffectBaseSheet(entry, id, destination) {
|
|
7
|
+
const generatedFileDir = path.join(destination, "system", "sheets", "vue");
|
|
8
|
+
const generatedFilePath = path.join(generatedFileDir, `active-effect-sheet.mjs`);
|
|
9
|
+
if (!fs.existsSync(generatedFileDir)) {
|
|
10
|
+
fs.mkdirSync(generatedFileDir, { recursive: true });
|
|
11
|
+
}
|
|
12
|
+
function generateAddValue(document, property) {
|
|
13
|
+
if (isAccess(property) || isAction(property) || isIfStatement(property) || isHookHandler(property) || isMacroField(property))
|
|
14
|
+
return undefined;
|
|
15
|
+
if (isLayout(property)) {
|
|
16
|
+
return joinToNode(property.body, property => generateAddValue(document, property), { appendNewLineIfNotEmpty: true });
|
|
17
|
+
}
|
|
18
|
+
if (isHtmlExp(property) || isInitiativeProperty(property) || isStatusProperty(property) || !isProperty(property))
|
|
19
|
+
return;
|
|
20
|
+
if (property.modifier == "locked")
|
|
21
|
+
return;
|
|
22
|
+
if (isResourceExp(property)) {
|
|
23
|
+
return expandToNode `
|
|
24
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value", 1);
|
|
25
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max");
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
if (isTrackerExp(property)) {
|
|
29
|
+
return expandToNode `
|
|
30
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.min");
|
|
31
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value", 1);
|
|
32
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.temp", 1);
|
|
33
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max");
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
36
|
+
if (isAttributeExp(property)) {
|
|
37
|
+
return expandToNode `
|
|
38
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value");
|
|
39
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max");
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
if (isNumberExp(property)) {
|
|
43
|
+
return expandToNode `
|
|
44
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${property.name.toLowerCase()}", 1);
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
return expandToNode `
|
|
48
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.${getSystemPath(property)}");
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
function generateDamageTypeActiveEffectFields(entry, document) {
|
|
52
|
+
if (!isActor(document))
|
|
53
|
+
return expandToNode ``;
|
|
54
|
+
const damageTypes = collectDamageTypes(entry);
|
|
55
|
+
if (damageTypes.length === 0) {
|
|
56
|
+
return expandToNode ``;
|
|
57
|
+
}
|
|
58
|
+
const damageTypeFields = damageTypes.map(damageType => {
|
|
59
|
+
const safeTypeName = damageType.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
60
|
+
return expandToNode `
|
|
61
|
+
// ${damageType} damage type Active Effect fields
|
|
62
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${safeTypeName}bonusdamage");
|
|
63
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${safeTypeName}damageresistanceflat");
|
|
64
|
+
addChange("${document.name.toLowerCase()}", "${document.name.toLowerCase()}.system.${safeTypeName}damageresistancepercent");
|
|
65
|
+
`;
|
|
66
|
+
});
|
|
67
|
+
return expandToNode `
|
|
68
|
+
// Auto-generated damage type Active Effect fields
|
|
69
|
+
${joinToNode(damageTypeFields, field => field, { appendNewLineIfNotEmpty: true })}
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
// Collect all damage types from the entry (same function as in datamodel-generator)
|
|
73
|
+
function collectDamageTypes(entry) {
|
|
74
|
+
var _a;
|
|
75
|
+
const damageTypes = new Set();
|
|
76
|
+
// Search through all documents for damage type choice fields
|
|
77
|
+
for (const document of entry.documents) {
|
|
78
|
+
const damageTypeFields = getAllOfType(document.body, isDamageTypeChoiceField);
|
|
79
|
+
for (const field of damageTypeFields) {
|
|
80
|
+
const damageField = field; // Cast to access params
|
|
81
|
+
const choicesParam = (_a = damageField.params) === null || _a === void 0 ? void 0 : _a.find((p) => isStringParamChoices(p));
|
|
82
|
+
if (choicesParam && choicesParam.choices) {
|
|
83
|
+
for (const choice of choicesParam.choices) {
|
|
84
|
+
// Handle simple string choices like "None"
|
|
85
|
+
if (typeof choice.value === 'string') {
|
|
86
|
+
damageTypes.add(choice.value);
|
|
87
|
+
}
|
|
88
|
+
// Handle extended choices like { label: "🔥Fire", value: "Fire", ... }
|
|
89
|
+
else if (choice.value && typeof choice.value === 'object') {
|
|
90
|
+
const extendedChoice = choice.value;
|
|
91
|
+
// Try direct access to value property first
|
|
92
|
+
if (extendedChoice.value && typeof extendedChoice.value === 'string') {
|
|
93
|
+
damageTypes.add(extendedChoice.value);
|
|
94
|
+
}
|
|
95
|
+
// Try properties array access
|
|
96
|
+
else if (extendedChoice.properties && Array.isArray(extendedChoice.properties)) {
|
|
97
|
+
// Based on the ISDL syntax { label: "🔥Fire", value: "Fire", icon: "...", color: "...", ... }
|
|
98
|
+
// Property 0 = label, Property 1 = value, Property 2 = icon, Property 3 = color, rest = custom
|
|
99
|
+
if (extendedChoice.properties.length > 1 && extendedChoice.properties[1].value) {
|
|
100
|
+
const damageTypeValue = extendedChoice.properties[1].value;
|
|
101
|
+
damageTypes.add(damageTypeValue);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return Array.from(damageTypes).sort();
|
|
110
|
+
}
|
|
111
|
+
// let stringChoices = document.body.filter(x => isStringExp(x) && x.choices != undefined && x.choices.length > 0).map(x => x as StringExp);
|
|
112
|
+
// for (let section of document.body.filter(x => isSection(x))) {
|
|
113
|
+
// stringChoices = stringChoices.concat((section as Section).body.filter(x => isStringExp(x) && x.choices != undefined && x.choices.length > 0).map(x => x as StringExp));
|
|
114
|
+
// }
|
|
115
|
+
// function generateStringChoices(document: Document, property: StringExp): CompositeGeneratorNode | undefined {
|
|
116
|
+
// // We need to map an array of form [ "A", "B", "C" ] to an object of form { A: "A", B: "B", C: "C" }
|
|
117
|
+
// return expandToNode`
|
|
118
|
+
// context.${property.name.toLowerCase()}Choices = {
|
|
119
|
+
// ${joinToNode(property.choices, x => expandToNode`${toMachineIdentifier(x)}: "${document.name}.${property.name}.${x}",`.appendNewLineIfNotEmpty())}
|
|
120
|
+
// };
|
|
121
|
+
// `;
|
|
122
|
+
// }
|
|
123
|
+
const fileNode = expandToNode `
|
|
124
|
+
import VueRenderingMixin from './VueRenderingMixin.mjs';
|
|
125
|
+
import { ActiveEffectApp } from "./components/components.vue.es.mjs";
|
|
126
|
+
const { DOCUMENT_OWNERSHIP_LEVELS } = CONST;
|
|
127
|
+
export default class ${entry.config.name}EffectVueSheet extends VueRenderingMixin(foundry.applications.api.DocumentSheetV2) {
|
|
128
|
+
|
|
129
|
+
vueParts = {
|
|
130
|
+
"active-effect": {
|
|
131
|
+
component: ActiveEffectApp,
|
|
132
|
+
template: "<active-effect :context=\\"context\\">Vue rendering for sheet failed.</active-effect>"
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
_arrayEntryKey = 0;
|
|
137
|
+
_renderKey = 0;
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
/** @override */
|
|
141
|
+
static DEFAULT_OPTIONS = {
|
|
142
|
+
classes: ["${id}", "sheet", "vue-sheet", "active-effect", "active-effect-sheet"],
|
|
143
|
+
viewPermission: DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
|
|
144
|
+
editPermission: DOCUMENT_OWNERSHIP_LEVELS.OWNER,
|
|
145
|
+
position: {
|
|
146
|
+
width: 600,
|
|
147
|
+
height: 600,
|
|
148
|
+
},
|
|
149
|
+
window: {
|
|
150
|
+
resizable: true,
|
|
151
|
+
title: "Active Effect"
|
|
152
|
+
},
|
|
153
|
+
tag: "form",
|
|
154
|
+
actions: {
|
|
155
|
+
onEditImage: this._onEditImage
|
|
156
|
+
},
|
|
157
|
+
changeActions: {
|
|
158
|
+
},
|
|
159
|
+
// Custom property that's merged into this.options
|
|
160
|
+
dragDrop: [
|
|
161
|
+
],
|
|
162
|
+
form: {
|
|
163
|
+
handler: ${entry.config.name}EffectVueSheet._onSubmitForm,
|
|
164
|
+
submitOnChange: false,
|
|
165
|
+
submitOnClose: true,
|
|
166
|
+
closeOnSubmit: false
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/* -------------------------------------------- */
|
|
171
|
+
|
|
172
|
+
static async _onEditImage(event, target) {
|
|
173
|
+
const current = foundry.utils.getProperty(this.document, target.dataset.edit);
|
|
174
|
+
const fp = new FilePicker({
|
|
175
|
+
current,
|
|
176
|
+
type: "image",
|
|
177
|
+
callback: (path) => {
|
|
178
|
+
this.document.update({ [target.dataset.edit]: path });
|
|
179
|
+
},
|
|
180
|
+
top: this.position.top + 40,
|
|
181
|
+
left: this.position.left + 10
|
|
182
|
+
});
|
|
183
|
+
return fp.browse();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* -------------------------------------------- */
|
|
187
|
+
|
|
188
|
+
async _prepareContext(options) {
|
|
189
|
+
const context = await super._prepareContext(options);
|
|
190
|
+
this.object = this.document.toObject();
|
|
191
|
+
context.effect = this.object;
|
|
192
|
+
context.descriptionHTML = await TextEditor.enrichHTML(this.object.description, {secrets: this.object.isOwner});
|
|
193
|
+
|
|
194
|
+
// Status Conditions
|
|
195
|
+
const statuses = CONFIG.statusEffects.map(s => {
|
|
196
|
+
return {
|
|
197
|
+
id: s.id,
|
|
198
|
+
label: game.i18n.localize(s.name),
|
|
199
|
+
selected: context.effect.statuses.includes(s.id) ? "selected" : ""
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
context.statuses = statuses;
|
|
203
|
+
if ( context.effect.origin ) {
|
|
204
|
+
context.originLink = await TextEditor.enrichHTML("@UUID[" + context.effect.origin + "]");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function setValue(obj, access, value, mode) {
|
|
208
|
+
if ( typeof(access)=='string' ) {
|
|
209
|
+
access = access.split('.');
|
|
210
|
+
}
|
|
211
|
+
// Split up an access path into sub-objects, such as "system.attribute.value" => "system": {"attribute": {"value": ...}}
|
|
212
|
+
if ( access.length > 1 ) {
|
|
213
|
+
const key = access.shift();
|
|
214
|
+
if ( !obj[key] ) obj[key] = {};
|
|
215
|
+
setValue(obj[key], access, value, mode);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
obj[access[0]] = value;
|
|
219
|
+
obj[access[0] + "-mode"] = mode;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Turn the changes into the friendlier format
|
|
224
|
+
for ( const change of context.effect.changes ) {
|
|
225
|
+
setValue(context, change.key, change.value, change.mode);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Output initialization
|
|
229
|
+
const vueContext = {
|
|
230
|
+
// Validates both permissions and compendium status
|
|
231
|
+
editable: this.isEditable,
|
|
232
|
+
owner: this.document.isOwner,
|
|
233
|
+
limited: this.document.limited,
|
|
234
|
+
|
|
235
|
+
// Add the document.
|
|
236
|
+
object: context.effect,
|
|
237
|
+
document: this.document,
|
|
238
|
+
|
|
239
|
+
// Add the data to context.data for easier access, as well as flags.
|
|
240
|
+
system: this.document.system,
|
|
241
|
+
flags: this.document.flags,
|
|
242
|
+
|
|
243
|
+
// Editors
|
|
244
|
+
editors: {},
|
|
245
|
+
|
|
246
|
+
// Force re-renders. Defined in the vue mixin.
|
|
247
|
+
_renderKey: this._renderKey ?? 0,
|
|
248
|
+
_arrayEntryKey: this._arrayEntryKey ?? 0,
|
|
249
|
+
isItemEffect: this.document.parent.documentName === "Item",
|
|
250
|
+
originLink: context.originLink
|
|
251
|
+
// tabs: this._getTabs(options.parts),
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
await this._enrichEditor(vueContext, "description");
|
|
255
|
+
|
|
256
|
+
const numberTypes = ['multiply', 'add', 'downgrade', 'upgrade', 'override'];
|
|
257
|
+
const stringTypes = ['override'];
|
|
258
|
+
const booleanTypes = ['override'];
|
|
259
|
+
|
|
260
|
+
vueContext.numberModes = numberTypes.map(type => ({
|
|
261
|
+
value: type,
|
|
262
|
+
label: game.i18n.localize(\`EFFECT.CHANGES.TYPES.\${type}\`)
|
|
263
|
+
}));
|
|
264
|
+
vueContext.numberModes.push({
|
|
265
|
+
value: 'custom',
|
|
266
|
+
label: game.i18n.localize("EFFECTS.AddOnce")
|
|
267
|
+
});
|
|
268
|
+
vueContext.basicNumberModes = numberTypes.map(type => ({
|
|
269
|
+
value: type,
|
|
270
|
+
label: game.i18n.localize(\`EFFECT.CHANGES.TYPES.\${type}\`)
|
|
271
|
+
}));
|
|
272
|
+
vueContext.stringModes = stringTypes.map(type => ({
|
|
273
|
+
value: type,
|
|
274
|
+
label: game.i18n.localize(\`EFFECT.CHANGES.TYPES.\${type}\`)
|
|
275
|
+
}));
|
|
276
|
+
vueContext.booleanModes = booleanTypes.map(type => ({
|
|
277
|
+
value: type,
|
|
278
|
+
label: game.i18n.localize(\`EFFECT.CHANGES.TYPES.\${type}\`)
|
|
279
|
+
}));
|
|
280
|
+
vueContext.resourceModes = [
|
|
281
|
+
{ value: 'custom', label: game.i18n.localize("EFFECTS.AddOnce") }
|
|
282
|
+
];
|
|
283
|
+
vueContext.trackerModes = [
|
|
284
|
+
{ value: 'custom', label: game.i18n.localize("EFFECTS.AddOnce") }
|
|
285
|
+
];
|
|
286
|
+
|
|
287
|
+
// Copy current change values into vueContext so the Vue component can read them
|
|
288
|
+
for ( const change of context.effect.changes ) {
|
|
289
|
+
setValue(vueContext, change.key, change.value, change.mode);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
console.dir("Vue Active Effect Context", vueContext);
|
|
293
|
+
return vueContext;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
async _enrichEditor(context, field) {
|
|
298
|
+
const enrichmentOptions = {
|
|
299
|
+
// Whether to show secret blocks in the finished html
|
|
300
|
+
secrets: this.document.isOwner,
|
|
301
|
+
// Data to fill in for inline rolls
|
|
302
|
+
rollData: {},
|
|
303
|
+
// Relative UUID resolution
|
|
304
|
+
relativeTo: this.document
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const editorOptions = {
|
|
308
|
+
toggled: true,
|
|
309
|
+
collaborate: true,
|
|
310
|
+
documentUUID: this.document.uuid,
|
|
311
|
+
height: 300
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const editorValue = this.document.system?.[field] ?? foundry.utils.getProperty(this.document.system, field);
|
|
315
|
+
context.editors[\`\${field}\`] = {
|
|
316
|
+
enriched: await TextEditor.enrichHTML(editorValue, enrichmentOptions),
|
|
317
|
+
element: foundry.applications.elements.HTMLProseMirrorElement.create({
|
|
318
|
+
...editorOptions,
|
|
319
|
+
name: \`system.\${field}\`,
|
|
320
|
+
value: editorValue ?? ""
|
|
321
|
+
})
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* -------------------------------------------- */
|
|
326
|
+
|
|
327
|
+
_prepareSubmitData(event, form, formData) {
|
|
328
|
+
// We don't modify the image via the sheet itself, so we can remove it from the submit data to avoid errors.
|
|
329
|
+
delete formData.object.img;
|
|
330
|
+
return super._prepareSubmitData(event, form, formData);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* -------------------------------------------- */
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Process form submission for the sheet
|
|
337
|
+
* @this {${entry.config.name}EffectVueSheet} The handler is called with the application as its bound scope
|
|
338
|
+
* @param {SubmitEvent} event The originating form submission event
|
|
339
|
+
* @param {HTMLFormElement} form The form element that was submitted
|
|
340
|
+
* @param {FormDataExtended} formData Processed data for the submitted form
|
|
341
|
+
* @returns {Promise<void>}
|
|
342
|
+
*/
|
|
343
|
+
static async _onSubmitForm(event, form, formData) {
|
|
344
|
+
console.log("Updating Active Effect", formData);
|
|
345
|
+
const flags = foundry.utils.duplicate(this.document.flags);
|
|
346
|
+
if ( !flags["${id}"] ) {
|
|
347
|
+
flags["${id}"] = {};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Retrieve the existing effects.
|
|
351
|
+
let changes = this.document.changes ? [...this.document.changes] : [];
|
|
352
|
+
|
|
353
|
+
// Build an array of effects from the form data
|
|
354
|
+
let newChanges = [];
|
|
355
|
+
|
|
356
|
+
function addChange(documentName, key, customMode) {
|
|
357
|
+
const value = foundry.utils.getProperty(formData.object, key);
|
|
358
|
+
if ( value === undefined ) {
|
|
359
|
+
// Field not rendered in the form - preserve any existing change.
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if ( !value ) {
|
|
363
|
+
// Field explicitly cleared (empty string / zero) - remove the change.
|
|
364
|
+
changes = changes.filter(c => c.key !== key);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const type = foundry.utils.getProperty(formData.object, key + "-type") ?? 'add';
|
|
368
|
+
newChanges.push({
|
|
369
|
+
key: key,
|
|
370
|
+
value: value,
|
|
371
|
+
type: type
|
|
372
|
+
});
|
|
373
|
+
if ( customMode ) flags["${id}"][key + "-custommode"] = customMode;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
${joinToNode(entry.documents.filter(d => isActor(d)), document => joinToNode(document.body, property => generateAddValue(document, property), { appendNewLineIfNotEmpty: true }))}
|
|
377
|
+
|
|
378
|
+
// Auto-generated damage type Active Effect fields
|
|
379
|
+
${joinToNode(entry.documents.filter(d => isActor(d)), document => generateDamageTypeActiveEffectFields(entry, document), { appendNewLineIfNotEmpty: true })}
|
|
380
|
+
|
|
381
|
+
// Update the existing changes to replace duplicates.
|
|
382
|
+
for (let i = 0; i < changes.length; i++) {
|
|
383
|
+
const newChange = newChanges.find(c => c.key == changes[i].key);
|
|
384
|
+
if (newChange) {
|
|
385
|
+
// Replace with the new change and update the array to prevent duplicates.
|
|
386
|
+
changes[i] = newChange;
|
|
387
|
+
newChanges = newChanges.filter(c => c.key != changes[i].key);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Filter changes for empty form fields.
|
|
392
|
+
const finalChanges = changes.concat(newChanges).filter(c => c.value !== null && c.value !== undefined && c.value !== '');
|
|
393
|
+
console.log("Active Effect Changes", finalChanges);
|
|
394
|
+
await this.document.update({
|
|
395
|
+
name: formData.object.name,
|
|
396
|
+
description: formData.object.description ?? '',
|
|
397
|
+
disabled: formData.object.disabled ?? false,
|
|
398
|
+
transfer: formData.object.transfer ?? false,
|
|
399
|
+
changes: finalChanges,
|
|
400
|
+
flags: flags
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Rerender the parent sheets to update the effect lists.
|
|
404
|
+
this.document.parent?.sheet?.render();
|
|
405
|
+
if ( this.document.parent?.documentName === "Item" ) {
|
|
406
|
+
this.document.parent?.parent?.applyActiveEffects();
|
|
407
|
+
|
|
408
|
+
// Wait half a second
|
|
409
|
+
await new Promise(r => setTimeout(r, 500));
|
|
410
|
+
this.document.parent?.parent?.sheet?.render();
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
`.appendNewLineIfNotEmpty();
|
|
415
|
+
fs.writeFileSync(generatedFilePath, toString(fileNode));
|
|
416
|
+
}
|
|
417
|
+
export function generateActiveEffectHandlebars(id, entry, destination) {
|
|
418
|
+
const generatedFileDir = path.join(destination, "system", "templates");
|
|
419
|
+
const generatedFilePath = path.join(generatedFileDir, `active-effect-sheet.hbs`);
|
|
420
|
+
if (!fs.existsSync(generatedFileDir)) {
|
|
421
|
+
fs.mkdirSync(generatedFileDir, { recursive: true });
|
|
422
|
+
}
|
|
423
|
+
function generateField(document, property) {
|
|
424
|
+
if (isAccess(property) || isAction(property) || isIfStatement(property))
|
|
425
|
+
return undefined;
|
|
426
|
+
if (isSection(property)) {
|
|
427
|
+
if (property.body.length == 0)
|
|
428
|
+
return undefined;
|
|
429
|
+
let fields = [];
|
|
430
|
+
for (let p of property.body) {
|
|
431
|
+
let field = generateField(document, p);
|
|
432
|
+
if (field != undefined)
|
|
433
|
+
fields.push(field);
|
|
434
|
+
}
|
|
435
|
+
if (fields.length == 0)
|
|
436
|
+
return undefined;
|
|
437
|
+
return expandToNode `
|
|
438
|
+
<!-- ${property.name} Section -->
|
|
439
|
+
<fieldset>
|
|
440
|
+
<legend>{{localize "${property.name}"}}</legend>
|
|
441
|
+
${joinToNode(fields, field => field, { appendNewLineIfNotEmpty: true })}
|
|
442
|
+
</fieldset>
|
|
443
|
+
`;
|
|
444
|
+
}
|
|
445
|
+
if (isLayout(property)) {
|
|
446
|
+
return joinToNode(property.body, property => generateField(document, property), { appendNewLineIfNotEmpty: true });
|
|
447
|
+
}
|
|
448
|
+
if (isHtmlExp(property) || isInitiativeProperty(property) || isStatusProperty(property) || isHookHandler(property) || !isProperty(property))
|
|
449
|
+
return;
|
|
450
|
+
if (property.modifier == "locked")
|
|
451
|
+
return;
|
|
452
|
+
if (isNumberExp(property)) {
|
|
453
|
+
// If this is calculated, it's implicitly locked
|
|
454
|
+
if (property.params.find(x => isNumberParamValue(x)))
|
|
455
|
+
return;
|
|
456
|
+
return expandToNode `
|
|
457
|
+
<div class="form-group">
|
|
458
|
+
<label>{{localize "${property.name}"}}</label>
|
|
459
|
+
<select name="${document.name.toLowerCase()}.${getSystemPath(property)}-mode" data-dtype="Number">
|
|
460
|
+
{{selectOptions numberModes selected=${document.name.toLowerCase()}.${getSystemPath(property)}-mode}}
|
|
461
|
+
</select>
|
|
462
|
+
<input type="number" name="${document.name.toLowerCase()}.${getSystemPath(property)}" value="{{${document.name.toLowerCase()}.${getSystemPath(property)}}}" />
|
|
463
|
+
</div>
|
|
464
|
+
`;
|
|
465
|
+
}
|
|
466
|
+
if (isAttributeExp(property)) {
|
|
467
|
+
// return expandToNode`
|
|
468
|
+
// <div class="form-group">
|
|
469
|
+
// <label>{{localize "${property.name}"}} Value</label>
|
|
470
|
+
// <select name="${document.name.toLowerCase()}.${getSystemPath(property)}-mode" data-dtype="Number">
|
|
471
|
+
// {{selectOptions numberModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value-mode}}
|
|
472
|
+
// </select>
|
|
473
|
+
// <input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value}}" />
|
|
474
|
+
// </div>
|
|
475
|
+
// <div class="form-group">
|
|
476
|
+
// <label>{{localize "${property.name}"}} Max</label>
|
|
477
|
+
// <select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max-mode" data-dtype="Number">
|
|
478
|
+
// {{selectOptions numberModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max-mode}}
|
|
479
|
+
// </select>
|
|
480
|
+
// <input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max}}" />
|
|
481
|
+
// </div>
|
|
482
|
+
// `;
|
|
483
|
+
return expandToNode `
|
|
484
|
+
<div class="form-group">
|
|
485
|
+
<label>{{localize "${property.name}"}} Value</label>
|
|
486
|
+
<select name="${document.name.toLowerCase()}.${getSystemPath(property)}-mode" data-dtype="Number">
|
|
487
|
+
{{selectOptions numberModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value-mode}}
|
|
488
|
+
</select>
|
|
489
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value}}" />
|
|
490
|
+
</div>
|
|
491
|
+
`;
|
|
492
|
+
}
|
|
493
|
+
if (isResourceExp(property)) {
|
|
494
|
+
return expandToNode `
|
|
495
|
+
<div class="form-group">
|
|
496
|
+
<label>{{localize "${property.name}"}} Current</label>
|
|
497
|
+
<select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value-mode" data-dtype="Number">
|
|
498
|
+
{{selectOptions resourceModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value-mode}}
|
|
499
|
+
</select>
|
|
500
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value}}" />
|
|
501
|
+
</div>
|
|
502
|
+
<div class="form-group">
|
|
503
|
+
<label>{{localize "${property.name}"}} Max</label>
|
|
504
|
+
<select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max-mode" data-dtype="Number">
|
|
505
|
+
{{selectOptions numberModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max-mode}}
|
|
506
|
+
</select>
|
|
507
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max}}" />
|
|
508
|
+
</div>
|
|
509
|
+
`;
|
|
510
|
+
}
|
|
511
|
+
if (isTrackerExp(property)) {
|
|
512
|
+
return expandToNode `
|
|
513
|
+
<div class="form-group">
|
|
514
|
+
<label>{{localize "${property.name}"}} Min</label>
|
|
515
|
+
<select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.min-mode" data-dtype="Number">
|
|
516
|
+
{{selectOptions numberModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.min-mode}}
|
|
517
|
+
</select>
|
|
518
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.min" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.min}}" />
|
|
519
|
+
</div>
|
|
520
|
+
<div class="form-group">
|
|
521
|
+
<label>{{localize "${property.name}"}} Current</label>
|
|
522
|
+
<select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value-mode" data-dtype="Number">
|
|
523
|
+
{{selectOptions resourceModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value-mode}}
|
|
524
|
+
</select>
|
|
525
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.value}}" />
|
|
526
|
+
</div>
|
|
527
|
+
<div class="form-group">
|
|
528
|
+
<label>{{localize "${property.name}"}} Temp</label>
|
|
529
|
+
<select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.temp-mode" data-dtype="Number">
|
|
530
|
+
{{selectOptions resourceModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.temp-mode}}
|
|
531
|
+
</select>
|
|
532
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.temp" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.temp}}" />
|
|
533
|
+
</div>
|
|
534
|
+
<div class="form-group">
|
|
535
|
+
<label>{{localize "${property.name}"}} Max</label>
|
|
536
|
+
<select name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max-mode" data-dtype="Number">
|
|
537
|
+
{{selectOptions numberModes selected=${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max-mode}}
|
|
538
|
+
</select>
|
|
539
|
+
<input type="number" name="${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max" value="{{${document.name.toLowerCase()}.system.${property.name.toLowerCase()}.max}}" />
|
|
540
|
+
</div>
|
|
541
|
+
`;
|
|
542
|
+
}
|
|
543
|
+
if (isStringExp(property)) {
|
|
544
|
+
// if (property.choices != undefined && property.choices.length > 0) {
|
|
545
|
+
// return expandToNode`
|
|
546
|
+
// <div class="form-group">
|
|
547
|
+
// <label>{{localize "${property.name}"}}</label>
|
|
548
|
+
// <select name="${document.name.toLowerCase()}.${getSystemPath(property)}-mode" data-dtype="String">
|
|
549
|
+
// {{selectOptions stringModes selected=${document.name.toLowerCase()}.${getSystemPath(property)}-mode}}
|
|
550
|
+
// </select>
|
|
551
|
+
// <select name="${document.name.toLowerCase()}.${getSystemPath(property)}">
|
|
552
|
+
// {{selectOptions ${property.name.toLowerCase()}Choices selected=${document.name.toLowerCase()}.${getSystemPath(property)} localize=true }}
|
|
553
|
+
// </select>
|
|
554
|
+
// </div>
|
|
555
|
+
// `;
|
|
556
|
+
// }
|
|
557
|
+
return expandToNode `
|
|
558
|
+
<div class="form-group">
|
|
559
|
+
<label>{{localize "${property.name}"}}</label>
|
|
560
|
+
<select name="${document.name.toLowerCase()}.${getSystemPath(property)}-mode" data-dtype="String">
|
|
561
|
+
{{selectOptions stringModes selected=${document.name.toLowerCase()}.${getSystemPath(property)}-mode}}
|
|
562
|
+
</select>
|
|
563
|
+
<input type="text" name="${document.name.toLowerCase()}.${getSystemPath(property)}" value="{{${document.name.toLowerCase()}.${getSystemPath(property)}}}" />
|
|
564
|
+
</div>
|
|
565
|
+
`;
|
|
566
|
+
}
|
|
567
|
+
if (isBooleanExp(property)) {
|
|
568
|
+
return expandToNode `
|
|
569
|
+
<div class="form-group">
|
|
570
|
+
<label>{{localize "${property.name}"}}</label>
|
|
571
|
+
<select name="${document.name.toLowerCase()}.${getSystemPath(property)}-mode" data-dtype="Boolean">
|
|
572
|
+
{{selectOptions booleanModes selected=${document.name.toLowerCase()}.${getSystemPath(property)}-mode}}
|
|
573
|
+
</select>
|
|
574
|
+
<input type="checkbox" name="${document.name.toLowerCase()}.${getSystemPath(property)}" {{checked ${document.name.toLowerCase()}.${getSystemPath(property)}}} />
|
|
575
|
+
</div>
|
|
576
|
+
`;
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
function generateDocumentTab(document) {
|
|
581
|
+
return expandToNode `
|
|
582
|
+
<!-- ${document.name} Tab -->
|
|
583
|
+
<section class="tab" data-tab="${document.name.toLowerCase()}">
|
|
584
|
+
${joinToNode(document.body, property => generateField(document, property), { appendNewLineIfNotEmpty: true })}
|
|
585
|
+
</section>
|
|
586
|
+
`;
|
|
587
|
+
}
|
|
588
|
+
const fileNode = expandToNode `
|
|
589
|
+
<form class="{{cssClass}}" autocomplete="off">
|
|
590
|
+
<!-- Effect Header -->
|
|
591
|
+
<header class="sheet-header">
|
|
592
|
+
<img class="effect-icon effect-img" src="{{ effect.img }}" data-edit="img">
|
|
593
|
+
<h1 class="effect-title"><input type="text" name="name" value="{{effect.name}}" placeholder="{{localize 'ARCHMAGE.name'}}"/></h1>
|
|
594
|
+
</header>
|
|
595
|
+
|
|
596
|
+
<article class="sheet-content">
|
|
597
|
+
<section class="sheet-body">
|
|
598
|
+
<!-- Effect Configuration Tabs -->
|
|
599
|
+
<nav class="sheet-tabs tabs">
|
|
600
|
+
<a class="item" data-tab="info"><i class="fas fa-book"></i> {{localize "Info"}}</a>
|
|
601
|
+
${joinToNode(entry.documents.filter(d => isActor(d)), property => `<a class="item" data-tab="${property.name.toLowerCase()}">{{localize "${property.name}"}}</a>`, { appendNewLineIfNotEmpty: true })}
|
|
602
|
+
</nav>
|
|
603
|
+
|
|
604
|
+
<div class="sheet-tabs-content">
|
|
605
|
+
<!-- Info Tab -->
|
|
606
|
+
<section class="tab" data-tab="info">
|
|
607
|
+
<div class="form-group stacked">
|
|
608
|
+
<label>{{ localize "EFFECT.Description" }}</label>
|
|
609
|
+
{{editor descriptionHTML target="description" button=false editable=editable engine="prosemirror" collaborate=false}}
|
|
610
|
+
</div>
|
|
611
|
+
|
|
612
|
+
<div class="form-group">
|
|
613
|
+
<label>{{ localize "EFFECT.Disabled" }}</label>
|
|
614
|
+
<input type="checkbox" name="disabled" {{ checked effect.disabled }}/>
|
|
615
|
+
</div>
|
|
616
|
+
|
|
617
|
+
{{#if originLink}}
|
|
618
|
+
<div class="form-group">
|
|
619
|
+
<label>{{ localize "EFFECT.Origin" }}</label>
|
|
620
|
+
{{{originLink}}}
|
|
621
|
+
</div>
|
|
622
|
+
{{/if}}
|
|
623
|
+
|
|
624
|
+
{{#if isItemEffect}}
|
|
625
|
+
<div class="form-group">
|
|
626
|
+
<label>{{ labels.transfer.name }}</label>
|
|
627
|
+
<div class="form-fields">
|
|
628
|
+
<input type="checkbox" name="transfer" {{checked data.transfer}}/>
|
|
629
|
+
</div>
|
|
630
|
+
<p class="hint">{{ labels.transfer.hint }}</p>
|
|
631
|
+
</div>
|
|
632
|
+
{{/if}}
|
|
633
|
+
</div>
|
|
634
|
+
|
|
635
|
+
${joinToNode(entry.documents, property => generateDocumentTab(property), { appendNewLineIfNotEmpty: true })}
|
|
636
|
+
</section>
|
|
637
|
+
</section>
|
|
638
|
+
</article>
|
|
639
|
+
</form>
|
|
640
|
+
`.appendNewLineIfNotEmpty();
|
|
641
|
+
fs.writeFileSync(generatedFilePath, toString(fileNode));
|
|
642
|
+
}
|
|
643
|
+
//# sourceMappingURL=active-effect-sheet-generator.js.map
|