diff --git a/@types/index.ts b/@types/index.ts index 113a338a..3befad94 100644 --- a/@types/index.ts +++ b/@types/index.ts @@ -62,18 +62,6 @@ export interface Monster { layout?: string; } -/* export interface StatblockMonster - extends Omit< - Monster, - "traits" | "actions" | "legendary_actions" | "reactions" - > { - traits: Map; - actions: Map; - legendary_actions: Map; - reactions: Map; - monster?: string; -} */ - export type Spell = string | { [key: string]: string }; export interface Trait { diff --git a/src/data/constants.ts b/src/data/constants.ts index 24dff64c..9b95c914 100644 --- a/src/data/constants.ts +++ b/src/data/constants.ts @@ -24,7 +24,12 @@ export type StatblockItemType = | "spells" | "inline" | "group"; - +export interface DiceProps { + callback?: string; + property?: keyof Monster; + text?: string; + parse?: boolean; +} interface CommonProps { type: StatblockItemType; id: string; @@ -32,10 +37,10 @@ interface CommonProps { conditioned?: boolean; fallback?: string; hasRule?: boolean; - dice?: { - property?: keyof Monster; - parse?: boolean; - }; + dice?: boolean; + diceProperty?: keyof Monster; + diceText?: string; + diceCallback?: string; } type GroupProps = { @@ -150,10 +155,9 @@ export const Statblock5e: StatblockItem[] = [ id: nanoid(), properties: ["hp"], display: "Hit Points", - dice: { - property: "hit_dice", - parse: true - }, + dice: true, + diceProperty: "hit_dice", + diceCallback: `return [{ text: monster["hit_dice"] }]`, conditioned: true }, { @@ -197,20 +201,15 @@ export const Statblock5e: StatblockItem[] = [ id: nanoid(), display: "Saves", properties: ["saves"], - conditioned: true, - dice: { - parse: true - } + conditioned: true + /* dice: true */ }, { type: "saves", id: nanoid(), display: "Skills", properties: ["skillsaves"], - conditioned: true, - dice: { - parse: true - } + conditioned: true }, { type: "property", @@ -296,18 +295,17 @@ return "";` id: nanoid(), properties: ["traits"], conditioned: true, - dice: { - parse: true - } + dice: true, + diceCallback: `return plugin.parseForDice(property);` }, { type: "spells", id: nanoid(), properties: ["spells"], conditioned: true, - dice: { - parse: true - } + + dice: true, + diceCallback: `return plugin.parseForDice(property);` }, { type: "traits", @@ -315,9 +313,9 @@ return "";` properties: ["actions"], heading: "Actions", conditioned: true, - dice: { - parse: true - } + + dice: true, + diceCallback: `return plugin.parseForDice(property);` }, { type: "traits", @@ -325,9 +323,9 @@ return "";` properties: ["legendary_actions"], heading: "Legendary Actions", conditioned: true, - dice: { - parse: true - } + + dice: true, + diceCallback: `return plugin.parseForDice(property);` }, { type: "traits", @@ -335,9 +333,9 @@ return "";` properties: ["reactions"], heading: "Reactions", conditioned: true, - dice: { - parse: true - } + + dice: true, + diceCallback: `return plugin.parseForDice(property);` } ]; diff --git a/src/main.ts b/src/main.ts index 60f06b48..9762a6b0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,6 +28,13 @@ import StatblockSettingTab from "./settings/settings"; import "./main.css"; import { sort } from "fast-sort"; declare module "obsidian" { + interface App { + plugins: { + plugins: { + "obsidian-dice-roller": DiceRollerPlugin; + }; + }; + } interface Workspace { on( name: "dice-roller:rendered-result", @@ -43,6 +50,7 @@ export interface StatblockData { useDice: boolean; renderDice: boolean; export: boolean; + showAdvanced: boolean; version: { major: number; minor: number; @@ -57,6 +65,7 @@ const DEFAULT_DATA: StatblockData = { useDice: true, renderDice: false, export: true, + showAdvanced: false, version: { major: null, minor: null, @@ -64,16 +73,6 @@ const DEFAULT_DATA: StatblockData = { } }; -declare module "obsidian" { - interface App { - plugins: { - plugins: { - "obsidian-dice-roller": DiceRollerPlugin; - }; - }; - } -} - export default class StatBlockPlugin extends Plugin { settings: StatblockData; data: Map; @@ -115,7 +114,7 @@ export default class StatBlockPlugin extends Plugin { ); addIcon( "statblock-conditioned", - `` + `` ); addIcon( "dice-roller-dice", @@ -278,6 +277,65 @@ export default class StatBlockPlugin extends Plugin { }); } + parseForDice(property: string) { + const roller = (str: string) => { + let text: string; + let original: string; + if (/\w+ [\+\-]\d+/.test(str.trim())) { + let [, save, sign, number] = + str.match(/(\w+ )([\+\-])(\d+)/) ?? []; + let mult = 1; + if (sign === "-") { + mult = -1; + } + if (!isNaN(Number(number))) { + text = `1d20+${mult * Number(number)}`; + original = `${save} ${sign}${number}`; + } + } else if (/[\+\-]\d+ to hit/.test(str.trim())) { + let [, sign, number] = str.match(/([\+\-])(\d+)/) ?? []; + + let mult = 1; + if (sign === "-") { + mult = -1; + } + if (!isNaN(Number(number))) { + text = `1d20+${mult * Number(number)}`; + original = str; + } + } else if (/\d+\s\(\d+d\d+(?:\s*[+\-]\s*\d+)?\)/.test(str.trim())) { + let [, base, dice] = + str.match(/(\d+)\s\((\d+d\d+(?:\s*[+\-]\s*\d+)?)\)/) ?? []; + if (!isNaN(Number(base)) && dice) { + text = dice; + } + } + return { text, original }; + }; + + const match = (str: string) => { + return ( + /\w+ [\+\-]\d+/.test(str.trim()) || + /[\+\-]\d+ to hit/.test(str.trim()) || + /\d+\s\(\d+d\d+(?:\s*[+\-]\s*\d+)?\)/.test(str.trim()) + ); + }; + + return property + .split( + /([\+\-]\d+ to hit|\d+\s\(\d+d\d+(?:\s*[+\-]\s*\d+)?\)|\w+ [\+\-]\d+)/ + ) + .map((v) => (match(v) ? roller(v) : v)); + } + + get defaultLayout() { + return ( + this.settings.layouts?.find( + (layout) => layout.name == this.settings.default + ) ?? Layout5e + ); + } + async postprocessor( source: string, el: HTMLElement, diff --git a/src/settings/StatblockCreator.svelte b/src/settings/StatblockCreator.svelte index ed8de6ce..acec5398 100644 --- a/src/settings/StatblockCreator.svelte +++ b/src/settings/StatblockCreator.svelte @@ -10,7 +10,6 @@ import { createEventDispatcher } from "svelte"; import { generate } from "./add"; - import AddButton from "./ui/AddButton.svelte"; import Creator from "./ui/Creator.svelte"; export let layout: Layout; @@ -90,15 +89,20 @@ }); }; - const add = async (e: CustomEvent) => { - const block = await generate(plugin, e.detail); + const add = async (e: MouseEvent) => { + const block = await generate(plugin, e); if (block) layout.blocks = [...layout.blocks, block]; }; + const addButton = (node: HTMLDivElement) => { + new ExtraButtonComponent(node) + .setIcon("plus-with-circle") + .setTooltip("Add Block"); + };
- +
add(evt)} />
{#key layout} diff --git a/src/settings/add.ts b/src/settings/add.ts index 20ce8d61..b25a113d 100644 --- a/src/settings/add.ts +++ b/src/settings/add.ts @@ -30,7 +30,7 @@ function blockGenerator(type: string): StatblockItem { case "inline": case "group": { return { - type: "group", + type: type, id: nanoid(), properties: [], nested: [] diff --git a/src/settings/settings.css b/src/settings/settings.css index f9f303ec..f6a5ff77 100644 --- a/src/settings/settings.css +++ b/src/settings/settings.css @@ -10,7 +10,6 @@ .statblock-additional-container > .additional > .setting-item { - padding-top: 0rem; color: var(--text-muted); } .statblock-edit-block .statblock-additional-container > :not(.additional) { @@ -19,6 +18,8 @@ .statblock-edit-block .setting-item { border: 0; + + padding-top: 0rem; } .statblock-edit-block textarea { diff --git a/src/settings/settings.ts b/src/settings/settings.ts index 0396441b..37cf8ee4 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -487,6 +487,17 @@ export default class StatblockSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); }); }); + new Setting(statblockAdditional) + .setName("Show Advanced Options") + .setDesc("Show advanced options when editing layout blocks.") + .addToggle((t) => + t + .setValue(this.plugin.settings.showAdvanced) + .onChange(async (v) => { + this.plugin.settings.showAdvanced = v; + await this.plugin.saveSettings(); + }) + ); const layoutContainer = statblockCreatorContainer.createDiv("additional"); diff --git a/src/settings/ui/AddButton.svelte b/src/settings/ui/AddButton.svelte deleted file mode 100644 index 6e066cb2..00000000 --- a/src/settings/ui/AddButton.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
dispatch("add", evt)} /> - - diff --git a/src/settings/ui/Block.svelte b/src/settings/ui/Block.svelte index 11039138..888ded77 100644 --- a/src/settings/ui/Block.svelte +++ b/src/settings/ui/Block.svelte @@ -1,12 +1,11 @@ - -
Heading
- - diff --git a/src/settings/ui/Blocks/SubheadingBlock.svelte b/src/settings/ui/Blocks/SubheadingBlock.svelte deleted file mode 100644 index accd59b5..00000000 --- a/src/settings/ui/Blocks/SubheadingBlock.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -
Subheading
- - diff --git a/src/settings/ui/Blocks/PropertyBlock.svelte b/src/settings/ui/PropertyBlock.svelte similarity index 83% rename from src/settings/ui/Blocks/PropertyBlock.svelte rename to src/settings/ui/PropertyBlock.svelte index 2c4dfc39..301d98fd 100644 --- a/src/settings/ui/Blocks/PropertyBlock.svelte +++ b/src/settings/ui/PropertyBlock.svelte @@ -15,7 +15,7 @@ }; const conditioned = (node: HTMLDivElement) => { - setIcon(node, "question-mark-glyph"); + setIcon(node, "statblock-conditioned"); }; const dice = (node: HTMLDivElement) => { setIcon(node, "dice-roller-dice"); @@ -30,7 +30,15 @@
- {transform(block.type)} +
+ {transform(block.type)} + {#if block.type == "table" && block.headers?.length} + + ({block.headers.join(" | ")}) + + {/if} +
+ {block.properties.join(", ")}
@@ -78,7 +86,11 @@ .context { display: flex; align-items: center; - gap: 0.1rem; + gap: 0.25rem; color: var(--text-muted); } + .context-item { + display: flex; + align-items: center; + } diff --git a/src/settings/ui/TableHeaders.svelte b/src/settings/ui/TableHeaders.svelte new file mode 100644 index 00000000..4c32c578 --- /dev/null +++ b/src/settings/ui/TableHeaders.svelte @@ -0,0 +1,119 @@ + + +
+
+ {#each items.filter((x) => x.id !== SHADOW_PLACEHOLDER_ITEM_ID) as header (header.id)} +
+ + {header.name} +
trash(header)} /> +
+ {/each} +
+
+ + diff --git a/src/settings/ui/block.ts b/src/settings/ui/block.ts index 2c0ccd3b..5f10de56 100644 --- a/src/settings/ui/block.ts +++ b/src/settings/ui/block.ts @@ -1,12 +1,25 @@ import type { Monster } from "@types"; import copy from "fast-copy"; -import { Modal, Notice, Setting, TextAreaComponent } from "obsidian"; -import type { StatblockItem, PropertyItem } from "src/data/constants"; +import { + ExtraButtonComponent, + Modal, + Notice, + Setting, + TextAreaComponent +} from "obsidian"; +import type { + StatblockItem, + PropertyItem, + TableItem, + TraitsItem +} from "src/data/constants"; import type StatBlockPlugin from "src/main"; +import TableHeaders from "./TableHeaders.svelte"; export class BlockModal extends Modal { block: StatblockItem; saved: boolean; + advanced: boolean = this.plugin.settings.showAdvanced; constructor(public plugin: StatBlockPlugin, block?: StatblockItem) { super(plugin.app); if (block) this.block = copy(block); @@ -16,6 +29,7 @@ export class BlockModal extends Modal { return ["group", "inline"].contains(this.block.type); } onOpen() { + this.titleEl.setText("Edit Block"); this.display(); } buildProperties(el: HTMLDivElement) { @@ -82,6 +96,96 @@ export class BlockModal extends Modal { ); }); } + if (this.block.type == "traits") { + new Setting(this.contentEl) + .setName("Section Heading") + .setDesc( + "This text will be used for the section heading. Can be left blank." + ) + .addText((t) => { + t.setValue((this.block as TraitsItem).heading).onChange( + (v) => ((this.block as TraitsItem).heading = v) + ); + }); + } + if (this.block.type == "table") { + const container = el.createDiv( + "statblock-additional-container" + ); + let tempProp = ""; + new Setting(container) + .setHeading() + .setName("Table Headers") + .addText((t) => + t + .setPlaceholder("header") + .setValue(tempProp) + .onChange((v) => (tempProp = v)) + ) + .addExtraButton((b) => + b.setIcon("plus-with-circle").onClick(() => { + if (!tempProp || !tempProp.length) { + new Notice( + "A valid property must be supplied." + ); + return; + } + (this.block as TableItem).headers.push( + tempProp as keyof Monster + ); + this.buildProperties(el); + }) + ); + const additional = container.createDiv("additional"); + new TableHeaders({ + target: additional, + props: { + headers: this.block.headers + } + }).$on("sorted", (e: CustomEvent<{ name: string }[]>) => { + (this.block as TableItem).headers = [ + ...(e.detail?.map((v) => v.name) ?? []) + ]; + }); + /* for (const property of this.block.headers) { + const header = additional.createDiv("header-container"); + header.createSpan({ text: property }); + new ExtraButtonComponent(header.createDiv()) + .setIcon("cross-in-box") + .onClick(() => { + (this.block as TableItem).headers = ( + this.block as TableItem + ).headers.filter((v) => v != property); + this.buildProperties(el); + }); + } */ + } + if (!this.advanced) return; + if (this.block.type == "property") { + new Setting(el) + .setHeading() + .setName("Callback") + .setDesc( + createFragment((e) => { + e.createSpan({ + text: "The block will run the callback and use the returned string as the property." + }); + e.createEl("br"); + e.createSpan({ + text: "The callback will receive the " + }); + e.createEl("code", { text: "plugin" }); + e.createSpan({ text: " and " }); + e.createEl("code", { text: "monster" }); + e.createSpan({ text: "parameters." }); + }) + ); + new TextAreaComponent(el) + .setValue(this.block.callback) + .onChange((v) => { + (this.block as PropertyItem).callback = v; + }); + } } } buildConditions(el: HTMLDivElement) { @@ -128,70 +232,72 @@ export class BlockModal extends Modal { new Setting(el) .setName("Enable Dice") .setDesc( - "The plugin will attempt to parse out common dice roller strings and add dice rollers." + "The plugin will attempt to add dice rollers as specified." ) .addToggle((t) => - t.setValue(this.block.dice?.parse).onChange((v) => { - if (!this.block.dice) { - this.block.dice = {}; - } - this.block.dice.parse = v; + t.setValue(this.block.dice).onChange((v) => { + this.block.dice = v; this.buildDice(el); }) ); - if (this.block.type == "property" && this.block.dice?.parse) { + if (this.block.dice) { new Setting(el.createDiv()) .setName("Link Dice to Property") .setDesc( "The dice roller will parse this property instead of the original." ) .addText((t) => { - t.setValue(this.block.dice?.property).onChange((v) => { - if (!this.block.dice) { - this.block.dice = {}; - } - this.block.dice.property = v as keyof Monster; + t.setValue(this.block.diceProperty).onChange((v) => { + this.block.diceProperty = v as keyof Monster; }); }); } } - } - buildCallback(el: HTMLDivElement) { - el.empty(); - if (this.block.type == "property") { - new Setting(el) - .setHeading() - .setName("Callback") - .setDesc( - createFragment((e) => { - e.createSpan({ - text: "The block will run the callback and use the returned string as the property." - }); - e.createEl("br"); - e.createSpan({ - text: "The callback will receive the " - }); - e.createEl("code", { text: "plugin" }); - e.createSpan({ text: " and " }); - e.createEl("code", { text: "monster" }); - e.createSpan({ text: "parameters." }); - }) - ); - new TextAreaComponent(el) - .setValue(this.block.callback) - .onChange((v) => { - (this.block as PropertyItem).callback = v; - }); - } + + if (!this.advanced) return; + new Setting(el) + .setHeading() + .setName("Dice Callback") + .setDesc( + createFragment((e) => { + e.createSpan({ + text: "The block will run the callback and use the returned values for the dice strings." + }); + e.createEl("br"); + e.createSpan({ + text: "The callback will receive the " + }); + e.createEl("code", { text: "plugin" }); + e.createSpan({ text: ", " }); + e.createEl("code", { text: "monster" }); + e.createSpan({ text: " and " }); + e.createEl("code", { text: "property" }); + e.createSpan({ text: "parameters." }); + }) + ); + new TextAreaComponent(el) + .setValue(this.block.diceCallback) + .onChange((v) => { + this.block.diceCallback = v; + }); } async display() { - this.titleEl.setText("Edit Block"); + this.contentEl.empty(); + new Setting(this.contentEl) + .setName("Show Advanced Options") + .addToggle((t) => { + t.setValue( + this.advanced ?? this.plugin.settings.showAdvanced + ).onChange((v) => { + this.advanced = v; + this.display(); + }); + }); this.buildProperties(this.contentEl.createDiv()); this.buildConditions(this.contentEl.createDiv()); this.buildDice(this.contentEl.createDiv()); - this.buildCallback(this.contentEl.createDiv()); this.buildButtons(this.contentEl.createDiv()); } diff --git a/src/util/suggester.ts b/src/util/suggester.ts index 4ea83a2e..da47dbde 100644 --- a/src/util/suggester.ts +++ b/src/util/suggester.ts @@ -4,6 +4,7 @@ import { FuzzyMatch, FuzzySuggestModal, Modal, + Platform, Scope, Setting, SuggestModal, @@ -304,21 +305,16 @@ class ViewMonsterModal extends Modal { super(plugin.app); } async display() { - const renderer = new StatBlockRenderer( + if (!Platform.isMobile) { + this.contentEl.style.maxWidth = "85vw"; + } + new StatBlockRenderer( this.contentEl, this.monster, this.plugin, false, - false + this.plugin.defaultLayout ); - renderer.loaded = true; - let columns = - this.contentEl.getBoundingClientRect().height > 500 - ? Math.ceil(this.contentEl.getBoundingClientRect().height / 750) - : 1; - if (columns >= 1) renderer.setWidth(columns * 400, true); - if (columns === 0) renderer.setMaxWidth(400); - renderer.statblockEl.toggleVisibility(true); } onOpen() { this.display(); diff --git a/src/view/Statblock.svelte b/src/view/Statblock.svelte index 5b936390..2a8cbdac 100644 --- a/src/view/Statblock.svelte +++ b/src/view/Statblock.svelte @@ -32,6 +32,7 @@ let canRender = monster.render ?? plugin.settings.renderDice; setContext("plugin", plugin); + setContext("monster", monster); setContext("dice", canDice); setContext("render", canRender); @@ -106,14 +107,7 @@
{#key columns} - + {/key} {:else} diff --git a/src/view/test.ts b/src/view/test.ts new file mode 100644 index 00000000..fcc2ca4e --- /dev/null +++ b/src/view/test.ts @@ -0,0 +1,37 @@ +const split = property.split( + /([\+\-]\d+ to hit|\d+\s\(\d+d\d+(?:\s*[+\-]\s*\d+)?\)|\w+ [\+\-]\d+)/ +); + +const roller = (str: string) => { + let text: string; + let original: string; + if (/\w+ [\+\-]\d+/.test(str.trim())) { + let [, save, sign, number] = str.match(/(\w+ )([\+\-])(\d+)/) ?? []; + let mult = 1; + if (sign === "-") { + mult = -1; + } + if (!isNaN(Number(number))) { + text = `1d20+${mult * Number(number)}`; + original = `${save} ${sign}${number}`; + } + } else if (/[\+\-]\d+ to hit/.test(str.trim())) { + let [, sign, number] = str.match(/([\+\-])(\d+)/) ?? []; + + let mult = 1; + if (sign === "-") { + mult = -1; + } + if (!isNaN(Number(number))) { + text = `1d20+${mult * Number(number)}`; + original = str; + } + } else if (/\d+\s\(\d+d\d+(?:\s*[+\-]\s*\d+)?\)/.test(str.trim())) { + let [, base, dice] = + str.match(/(\d+)\s\((\d+d\d+(?:\s*[+\-]\s*\d+)?)\)/) ?? []; + if (!isNaN(Number(base)) && dice) { + text = dice; + } + } + return { text, original }; +}; diff --git a/src/view/ui/Content.svelte b/src/view/ui/Content.svelte index f36ff1bf..01bd336b 100644 --- a/src/view/ui/Content.svelte +++ b/src/view/ui/Content.svelte @@ -11,14 +11,19 @@ import SectionHeading from "./SectionHeading.svelte"; import Subheading from "./Subheading.svelte"; import Table from "./Table.svelte"; - import { onMount, createEventDispatcher, getAllContexts } from "svelte"; + import { + onMount, + createEventDispatcher, + getAllContexts, + getContext + } from "svelte"; const dispatch = createEventDispatcher(); - export let monster: Monster; export let statblock: StatblockItem[]; export let columns: number = 1; export let ready: boolean; + const monster = getContext("monster"); const checkConditioned = (item: StatblockItem) => { if (!item.conditioned) return true; @@ -53,7 +58,7 @@ ): HTMLDivElement[] => { const targets: HTMLDivElement[] = []; const target = container ?? createDiv("statblock-item-container"); - + context.set("item", item); if (!checkConditioned(item)) { return []; } @@ -116,8 +121,7 @@ target: prop, props: { name: block.name, - desc: block.desc, - dice: item.dice?.parse + desc: block.desc }, context }); @@ -135,8 +139,7 @@ new Spells({ target, props: { - monster, - item + monster }, context }); diff --git a/src/view/ui/DiceHolder.svelte b/src/view/ui/DiceHolder.svelte new file mode 100644 index 00000000..63f6a4a9 --- /dev/null +++ b/src/view/ui/DiceHolder.svelte @@ -0,0 +1,72 @@ + + +{#if !dice} + {property} +{:else} + {#each split as test} + {#if typeof test != "string" && typeof test == "object" && "text" in test} + + {:else} + {test} + {/if} + {/each} +{/if} + + diff --git a/src/view/ui/DiceRoll.svelte b/src/view/ui/DiceRoll.svelte index 373eb7a5..3f65190d 100644 --- a/src/view/ui/DiceRoll.svelte +++ b/src/view/ui/DiceRoll.svelte @@ -5,7 +5,8 @@ import type { Writable } from "svelte/store"; import type { StackRoller } from "../../../../obsidian-dice-roller/src/roller/dice"; - export let text: string | number; + export let text: string; + export let original: string | number = text; const plugin = getContext("plugin"); const render = getContext("render"); @@ -21,31 +22,37 @@ }); }); - export let roller: StackRoller = null; + let roller: StackRoller = null; if (!roller && plugin.canUseDiceRoller) { roller = plugin.getRoller(`${text}`) as StackRoller; } let defaultValue = 0; + let error = false; onMount(async () => { - await roller.roll(); - defaultValue = roller.dice.reduce( - (a, dice) => - a + - (dice.static - ? dice.result - : Math.ceil( - ((dice.faces.min + dice.faces.max) / 2) * dice.rolls - )), - 0 - ); + try { + await roller.roll(); + defaultValue = roller.dice.reduce( + (a, dice) => + a + + (dice.static + ? dice.result + : Math.ceil( + ((dice.faces.min + dice.faces.max) / 2) * + dice.rolls + )), + 0 + ); - await roller.applyResult({ - type: "dice", - result: defaultValue, - tooltip: "Average" - }); - roller.shouldRender = render; + await roller.applyResult({ + type: "dice", + result: defaultValue, + tooltip: "Average" + }); + roller.shouldRender = render; + } catch (e) { + error = true; + } }); const rollerEl = (node: HTMLElement) => { @@ -53,10 +60,16 @@ }; - -{#if typeof text == "number" || (text && text.length)} - ({text}) -{/if} +{#key error} + {#if error} + {text} + {:else} + + {#if typeof original == "number" || (original && original.length)} + ({original}) + {/if} + {/if} +{/key} diff --git a/src/view/ui/PropertyBlock.svelte b/src/view/ui/PropertyBlock.svelte index 99eb7f13..034cdb3f 100644 --- a/src/view/ui/PropertyBlock.svelte +++ b/src/view/ui/PropertyBlock.svelte @@ -1,18 +1,14 @@
{name}
- +
diff --git a/src/view/ui/PropertyLine.svelte b/src/view/ui/PropertyLine.svelte index dd3f5395..27f311a4 100644 --- a/src/view/ui/PropertyLine.svelte +++ b/src/view/ui/PropertyLine.svelte @@ -1,10 +1,11 @@
{display} - {#if dice} - - {:else if parse} -
- -
- {:else} - {property} - {/if} +
diff --git a/src/view/ui/Saves.svelte b/src/view/ui/Saves.svelte index 7cbfb659..fe959791 100644 --- a/src/view/ui/Saves.svelte +++ b/src/view/ui/Saves.svelte @@ -1,10 +1,9 @@
- +
    {#each spells as spellItem, index} {#if index == spells.length - 1 && !spells.includes(":")} diff --git a/src/view/ui/Subheading.svelte b/src/view/ui/Subheading.svelte index afdebc19..179d37f2 100644 --- a/src/view/ui/Subheading.svelte +++ b/src/view/ui/Subheading.svelte @@ -1,6 +1,6 @@
    - {#each values as value, index} + {#each values.slice(0, headers.length) as value, index}
    {`${headers[index]}`.toUpperCase()} {value} ({getMod(value)}) diff --git a/src/view/ui/Trait.svelte b/src/view/ui/Trait.svelte deleted file mode 100644 index 0e6ebf96..00000000 --- a/src/view/ui/Trait.svelte +++ /dev/null @@ -1,75 +0,0 @@ - - -{#if !dice} - {trait} -{:else} - {#each split as str} - {#if !match(str)} - {str} - {:else} - - {/if} - {/each} -{/if}