@optolith/entity-descriptions 0.13.0 → 0.13.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [0.13.2](https://github.com/Optolith/entity-descriptions/compare/v0.13.1...v0.13.2) (2026-09-16)
6
+
7
+ ### Features
8
+
9
+ * add focus rule badges to activatable entries, spellworks and liturgical chants and ceremonies ([dd142b4](https://github.com/Optolith/entity-descriptions/commit/dd142b47f3cd29620d29a2561e4a8ae8ad1d2a2d)), closes [#41](https://github.com/Optolith/entity-descriptions/issues/41)
10
+ ## [0.13.1](https://github.com/Optolith/entity-descriptions/compare/v0.13.0...v0.13.1) (2026-09-16)
11
+
12
+ ### Bug Fixes
13
+
14
+ * prepend levels to activatable name in library according to name builder rules ([d97c05b](https://github.com/Optolith/entity-descriptions/commit/d97c05b6301a10f4d7add81d2903f0f51d9f2d0a))
15
+ * print correct any special ability of group prerequisite translation ([0196e4b](https://github.com/Optolith/entity-descriptions/commit/0196e4b5f069ac3893b834275eaf30c16f9e3e18))
5
16
  ## [0.13.0](https://github.com/Optolith/entity-descriptions/compare/v0.12.0...v0.13.0) (2026-09-16)
6
17
 
7
18
  ### ⚠ BREAKING CHANGES
@@ -1,4 +1,4 @@
1
- import type { ActivatableIdentifier, AdvancedSpecialAbility, AdvantageDisadvantagePrerequisites, AdvantageDisadvantageSubtype, AdventurePointsValue, ApplicableCombatTechniques, Aspect_ID, Brew_ID, DaggerRitualCost, EnchantmentCost, Errata, GeneralPrerequisites, MagicalSignCost, Penalty, PropertyDeclaration, PublicationRefs, RatedIdentifier, SelectOptions, SpecialRule, Volume } from "@optolith/database-schema/gen";
1
+ import type { ActivatableIdentifier, ActivatableNameBuilderRules, AdvancedSpecialAbility, AdvantageDisadvantagePrerequisites, AdvantageDisadvantageSubtype, AdventurePointsValue, ApplicableCombatTechniques, Aspect_ID, Brew_ID, DaggerRitualCost, EnchantmentCost, Errata, GeneralPrerequisites, MagicalSignCost, Penalty, PropertyDeclaration, PublicationRefs, RatedIdentifier, SelectOptions, SpecialRule, Volume } from "@optolith/database-schema/gen";
2
2
  import { Case } from "tsondb/schema/gen";
3
3
  import type { GetAllInstances, GetInstanceById } from "../helpers/getTypes.js";
4
4
  import type { GetAllResolvedNewSkillApplications, GetAllResolvedSelectOptions, GetAllResolvedSkillUses } from "../index.js";
@@ -9,6 +9,7 @@ type AdvancedIdentifierSpecialAbility = string | Case<AdvancedSpecialAbilityKind
9
9
  * The base fields for a special ability entity in the database.
10
10
  */
11
11
  export type BaseActivatable = {
12
+ nameBuilderRules?: ActivatableNameBuilderRules;
12
13
  levels?: number;
13
14
  subtype?: AdvantageDisadvantageSubtype;
14
15
  maximum?: number;
@@ -50,7 +51,7 @@ export type BaseActivatableTranslation = {
50
51
  * Get a JSON representation of the rules text for a special ability.
51
52
  */
52
53
  export declare const getActivatableEntityDescription: import("../creator.js").EntityDescriptionCreator<"Advantage" | "Disadvantage" | "AdvancedCombatSpecialAbility" | "AdvancedKarmaSpecialAbility" | "AdvancedMagicalSpecialAbility" | "AdvancedSkillSpecialAbility" | "AncestorGlyph" | "ArcaneOrbEnchantment" | "AttireEnchantment" | "Beutelzauber" | "BlessedTradition" | "BowlEnchantment" | "BrawlingSpecialAbility" | "CauldronEnchantment" | "CeremonialItemSpecialAbility" | "ChronicleEnchantment" | "CombatSpecialAbility" | "CombatStyleSpecialAbility" | "CommandSpecialAbility" | "DaggerRitual" | "FamiliarSpecialAbility" | "FatePointSexSpecialAbility" | "FatePointSpecialAbility" | "FoolsHatEnchantment" | "GeneralSpecialAbility" | "Haubenzauber" | "Hauerkettenzauber" | "InstrumentEnchantment" | "KarmaSpecialAbility" | "Keulenzauber" | "Krallenkettenzauber" | "Kristallkugelzauber" | "LiturgicalStyleSpecialAbility" | "LycantropicGift" | "MagicalSign" | "MagicalSpecialAbility" | "MagicalTradition" | "MagicStyleSpecialAbility" | "OrbEnchantment" | "PactGift" | "ProtectiveWardingCircleSpecialAbility" | "RingEnchantment" | "Schweinetrommelzauber" | "Sermon" | "SexSpecialAbility" | "SickleRitual" | "SikaryanDrainSpecialAbility" | "SkillStyleSpecialAbility" | "SpellSwordEnchantment" | "StaffEnchantment" | "ToyEnchantment" | "Trinkhornzauber" | "VampiricGift" | "Vision" | "WandEnchantment" | "WeaponEnchantment", {
53
- getInstanceById: GetInstanceById<"Publication" | "Subject" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "TradeSecret" | "Aspect" | "Property" | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Weapon" | "Patron" | "PersonalityTrait" | "Brew" | "Blessing" | "Cantrip">;
54
+ getInstanceById: GetInstanceById<"Publication" | "Subject" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "TradeSecret" | "Aspect" | "Property" | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Weapon" | "Patron" | "PersonalityTrait" | "Brew" | "Blessing" | "Cantrip" | "FocusRule">;
54
55
  getAllInstances: GetAllInstances<"Script">;
55
56
  getResolvedSelectOptionById: GetResolvedSelectOptionById;
56
57
  getAllResolvedSelectOptions: GetAllResolvedSelectOptions;
@@ -2,7 +2,7 @@ import { stripInlineMarkdown } from "@elyukai/markdown/render/strip";
2
2
  import { isNotEmpty } from "@elyukai/utils/array/nonEmpty";
3
3
  import { count } from "@elyukai/utils/array/reductions";
4
4
  import { deepEqual } from "@elyukai/utils/equality";
5
- import { constant, on } from "@elyukai/utils/function";
5
+ import { constant, identity, on } from "@elyukai/utils/function";
6
6
  import { isNotNullish } from "@elyukai/utils/nullable";
7
7
  import { reduceCompare } from "@elyukai/utils/ordering";
8
8
  import { Reader } from "@elyukai/utils/reader";
@@ -18,7 +18,7 @@ import { renderAdventurePointsValue } from "./partial/adventurePointsValue.js";
18
18
  import { renderParameterMap } from "./partial/map.js";
19
19
  import { attributedName } from "./partial/markdown.js";
20
20
  import { additionFormatter } from "./partial/mathOperation.js";
21
- import { printAdvantageDisadvantagePrerequisites, printGeneralPrerequisites, } from "./partial/prerequisites/index.js";
21
+ import { getDerivedFocusRuleBadgeFromPrerequisites, printAdvantageDisadvantagePrerequisites, printGeneralPrerequisites, } from "./partial/prerequisites/index.js";
22
22
  import { printActivatableName, } from "./partial/prerequisites/single/activatable.js";
23
23
  import { renderStandaloneCostMap } from "./partial/rated/activatable/cost.js";
24
24
  import { parensIf } from "./partial/rated/activatable/parensIf.js";
@@ -809,13 +809,27 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
809
809
  const makeTraditionName = entityName === "BlessedTradition" || entityName === "MagicalTradition"
810
810
  ? name => translate("Tradition ({$tradition})", { tradition: name })
811
811
  : name => name;
812
+ const { levels } = baseEntry;
813
+ const addLevels = levels === undefined
814
+ ? identity
815
+ : baseEntry.nameBuilderRules?.levelPlacement?.kind === "BeforeOptions"
816
+ ? name => {
817
+ const nameParts = name.split("(");
818
+ if (nameParts.length > 1) {
819
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- array is checked to have at least two elements
820
+ return `${nameParts[0]}I–${romanize(levels)} (${nameParts.slice(1).join("(")}`;
821
+ }
822
+ return `${name} I–${romanize(levels)}`;
823
+ }
824
+ : name => `${name} I–${romanize(levels)}`;
812
825
  return {
813
- title: makeTraditionName(translation.name_in_library ?? translation.name + parensIf(translation.additionalName)) + (baseEntry.levels !== undefined ? ` I–${romanize(baseEntry.levels)}` : ""),
826
+ title: addLevels(makeTraditionName(translation.name_in_library ?? translation.name + parensIf(translation.additionalName))),
814
827
  subtitle: mapNullable(baseEntry.subtype, subtype => renderAdvantageDisadvantageSubtype(subtype).run(env)) ??
815
828
  mapNullable(baseEntry.usage_type, usageType => renderCombatSpecialAbilityType(usageType).run(env)),
816
- badge: mapNullable(entityName === "CombatStyleSpecialAbility" || entityName === "AdvancedCombatSpecialAbility"
829
+ badge: mapNullable(entityName === "CombatStyleSpecialAbility" ||
830
+ entityName === "AdvancedCombatSpecialAbility"
817
831
  ? entry.type
818
- : undefined, combatType => {
832
+ : undefined, (combatType) => {
819
833
  switch (combatType.kind) {
820
834
  case "Armed":
821
835
  return { type: "armedCombat", value: translate("AC") };
@@ -824,7 +838,8 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
824
838
  default:
825
839
  return assertExhaustive(combatType);
826
840
  }
827
- }),
841
+ }) ??
842
+ mapNullable(baseEntry.prerequisites, getDerivedFocusRuleBadgeFromPrerequisites)?.run(env),
828
843
  className: "special-ability",
829
844
  body: [
830
845
  mapNullable(translation.special_rules, specialRules => ({
@@ -877,9 +892,9 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
877
892
  label: translate("Prerequisites"),
878
893
  value: wrappedId.kind === "Advantage" || wrappedId.kind === "Disadvantage"
879
894
  ? printAdvantageDisadvantagePrerequisites(prerequisites, translation.name, wrappedId.kind).run(env)
880
- : printGeneralPrerequisites(prerequisites, mapNullable(baseEntry.levels, levels => ({
895
+ : printGeneralPrerequisites(prerequisites, mapNullable(levels, safeLevels => ({
881
896
  id: wrappedId,
882
- levels,
897
+ levels: safeLevels,
883
898
  })), renderTrailingAdvancedPrerequisitesNote(translate, entityName)).run(env),
884
899
  })),
885
900
  mapNullable(baseEntry.combat_techniques, combatTechniques => ({
@@ -12,7 +12,7 @@ export declare const getBlessingEntityDescription: import("../creator.js").Entit
12
12
  * Get a JSON representation of the rules text for a liturgical chant.
13
13
  */
14
14
  export declare const getLiturgicalChantEntityDescription: import("../creator.js").EntityDescriptionCreator<"LiturgicalChant", {
15
- getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Aspect" | "BlessedTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement">;
15
+ getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Aspect" | "BlessedTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement" | "FocusRule">;
16
16
  getChildInstancesForInstanceId: GetAllChildInstancesForParent<"Enhancement">;
17
17
  idMap: IdMap;
18
18
  }, import("../index.js").EntityDescription>;
@@ -20,7 +20,7 @@ export declare const getLiturgicalChantEntityDescription: import("../creator.js"
20
20
  * Get a JSON representation of the rules text for a ceremony.
21
21
  */
22
22
  export declare const getCeremonyEntityDescription: import("../creator.js").EntityDescriptionCreator<"Ceremony", {
23
- getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Aspect" | "BlessedTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement">;
23
+ getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Aspect" | "BlessedTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement" | "FocusRule">;
24
24
  getChildInstancesForInstanceId: GetAllChildInstancesForParent<"Enhancement">;
25
25
  idMap: IdMap;
26
26
  }, import("../index.js").EntityDescription>;
@@ -1,9 +1,11 @@
1
+ import { mapNullable } from "@elyukai/utils/nullable";
1
2
  import { isNotNullish } from "@optolith/helpers/nullable";
2
3
  import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
4
  import { Case } from "tsondb/schema/gen";
4
5
  import { createEntityDescriptionCreator } from "../creator.js";
5
6
  import { renderEnhancements } from "./partial/enhancements.js";
6
7
  import { attributedInstance, attributedName } from "./partial/markdown.js";
8
+ import { getDerivedFocusRuleBadgeFromPrerequisites } from "./partial/prerequisites/index.js";
7
9
  import { renderOneTimeDuration } from "./partial/rated/activatable/duration.js";
8
10
  import { renderEffect } from "./partial/rated/activatable/effect.js";
9
11
  import { combineGeneratedTextWithStaticTranslation, renderFastPerformanceParameters, renderSlowPerformanceParameters, } from "./partial/rated/activatable/index.js";
@@ -173,6 +175,7 @@ export const getLiturgicalChantEntityDescription = createEntityDescriptionCreato
173
175
  return {
174
176
  title: translation.name,
175
177
  className: "liturgical-chant",
178
+ badge: mapNullable(entry.prerequisites, getDerivedFocusRuleBadgeFromPrerequisites)?.run(env),
176
179
  body: [
177
180
  {
178
181
  type: "definitionList",
@@ -237,6 +240,7 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator(({ ge
237
240
  return {
238
241
  title: translation.name,
239
242
  className: "ceremony",
243
+ badge: mapNullable(entry.prerequisites, getDerivedFocusRuleBadgeFromPrerequisites)?.run(env),
240
244
  body: [
241
245
  {
242
246
  type: "definitionList",
@@ -1,6 +1,7 @@
1
1
  import { Reader } from "@elyukai/utils/reader";
2
2
  import type { ActivatableIdentifier, AdvantageDisadvantagePrerequisites, AnimistPowerPrerequisites, ArcaneTraditionPrerequisites, DerivedCharacteristicPrerequisites, EnhancementPrerequisites, GeneralPrerequisites, GeodeRitualPrerequisites, InfluencePrerequisites, LanguagePrerequisites, LiturgyPrerequisites, PersonalityTraitPrerequisites, PlainGeneralPrerequisites, ProfessionPrerequisites, ProfessionVariantPrerequisites, PublicationPrerequisites, SpellworkPrerequisites } from "@optolith/database-schema/gen";
3
- import type { StdEnv } from "../../../env.js";
3
+ import type { StdEnv, StdReader } from "../../../env.js";
4
+ import type { RawEntityDescriptionBadge } from "../../../index.js";
4
5
  import { printAdvantageDisadvantagePrerequisiteGroup, printAnimistPowerPrerequisiteGroup, printArcaneTraditionPrerequisiteGroup, printDerivedCharacteristicPrerequisiteGroup, printEnhancementPrerequisiteGroup, printGeneralPrerequisiteGroup, printGeodeRitualPrerequisiteGroup, printInfluencePrerequisiteGroup, printLanguagePrerequisiteGroup, printLiturgyPrerequisiteGroup, printPersonalityTraitPrerequisiteGroup, printProfessionPrerequisiteGroup, printPublicationPrerequisiteGroup, printSpellworkPrerequisiteGroup } from "./prerequisiteGroups.js";
5
6
  type DeriveEnvF<T extends (...args: any[]) => any> = ReturnType<T> extends Reader<infer E, unknown> ? E : never;
6
7
  /**
@@ -70,4 +71,8 @@ export declare const printGeodeRitualPrerequisites: (value: GeodeRitualPrerequis
70
71
  * Print enhancement prerequisites as a string.
71
72
  */
72
73
  export declare const printEnhancementPrerequisites: (value: EnhancementPrerequisites) => Reader<DeriveEnvF<typeof printEnhancementPrerequisiteGroup> & StdEnv<"lj" | "lc">, string>;
74
+ /**
75
+ * Get the focus rule badge from prerequisites.
76
+ */
77
+ export declare const getDerivedFocusRuleBadgeFromPrerequisites: (prerequisites: AdvantageDisadvantagePrerequisites | GeneralPrerequisites | PlainGeneralPrerequisites) => StdReader<RawEntityDescriptionBadge | undefined, "ibi", "FocusRule">;
73
78
  export {};
@@ -7,7 +7,7 @@ import { isNotNullish } from "@optolith/helpers/nullable";
7
7
  import { romanize } from "@optolith/helpers/roman";
8
8
  import { assertExhaustive } from "@optolith/helpers/typeSafety";
9
9
  import { renderActivatableNameComponents, renderActivatableNameComponentsCombinedIfPossible, } from "../activatableNameChunks.js";
10
- import { localeJoinR, translateR } from "../reader.js";
10
+ import { getInstanceByIdR, localeJoinR, translateR } from "../reader.js";
11
11
  import { MISSING_VALUE } from "../unknown.js";
12
12
  import { printDisplayOption } from "./displayOption.js";
13
13
  import { hasPartValueObject, joinPrerequisiteParts } from "./part.js";
@@ -230,3 +230,26 @@ export const printGeodeRitualPrerequisites = (value) => printPlainPrerequisites(
230
230
  * Print enhancement prerequisites as a string.
231
231
  */
232
232
  export const printEnhancementPrerequisites = (value) => printPlainPrerequisites(printEnhancementPrerequisiteGroup, value);
233
+ const getDerivedFocusRuleBadgeFromPrerequisite = (prerequisite) => prerequisite.kind === "Single" &&
234
+ prerequisite.Single.kind === "Rule" &&
235
+ prerequisite.Single.Rule.id.kind === "FocusRule"
236
+ ? getInstanceByIdR(prerequisite.Single.Rule.id).map(focusRule => focusRule?.level)
237
+ : Reader.of(undefined);
238
+ /**
239
+ * Get the focus rule badge from prerequisites.
240
+ */
241
+ export const getDerivedFocusRuleBadgeFromPrerequisites = (prerequisites) => Reader.asks(env => {
242
+ for (const element of prerequisites) {
243
+ const actualPrerequisite = "level" in element ? (element.level === 1 ? element.prerequisite : undefined) : element;
244
+ if (actualPrerequisite !== undefined) {
245
+ const badge = getDerivedFocusRuleBadgeFromPrerequisite(actualPrerequisite).run(env);
246
+ if (badge !== undefined) {
247
+ return {
248
+ type: "level",
249
+ value: romanize(badge),
250
+ };
251
+ }
252
+ }
253
+ }
254
+ return undefined;
255
+ });
@@ -1,6 +1,7 @@
1
1
  import { assertExhaustive } from "@optolith/helpers/typeSafety";
2
2
  import { printActivatablePrerequisite } from "./single/activatable.js";
3
3
  import { printAnimistPowerPrerequisite } from "./single/animistPower.js";
4
+ import { printAnySpecialAbilityOfGroupPrerequisite } from "./single/anySpecialAbilityOfGroup.js";
4
5
  import { printBlessedTraditionPrerequisite } from "./single/blessedTradition.js";
5
6
  import { printCommonSuggestedByRCPPrerequisite } from "./single/commonSuggestedByRCP.js";
6
7
  import { printCulturePrerequisite } from "./single/culture.js";
@@ -82,7 +83,7 @@ export const printGeneralPrerequisiteGroup = (prerequisite) => {
82
83
  case "TinyActivatable":
83
84
  return printTinyActivatablePrerequisite(prerequisite.TinyActivatable);
84
85
  case "AnySpecialAbilityOfGroup":
85
- return printMagicalTraditionPrerequisite(prerequisite.AnySpecialAbilityOfGroup);
86
+ return printAnySpecialAbilityOfGroupPrerequisite(prerequisite.AnySpecialAbilityOfGroup);
86
87
  case "Rated":
87
88
  return printRatedPrerequisite(prerequisite.Rated);
88
89
  case "RatedMinimumNumber":
@@ -12,7 +12,7 @@ export declare const getCantripEntityDescription: import("../creator.js").Entity
12
12
  * Get a JSON representation of the rules text for a skill.
13
13
  */
14
14
  export declare const getSpellEntityDescription: import("../creator.js").EntityDescriptionCreator<"Spell", {
15
- getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Property" | "MagicalTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement">;
15
+ getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Property" | "MagicalTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement" | "FocusRule">;
16
16
  getChildInstancesForInstanceId: GetAllChildInstancesForParent<"Enhancement">;
17
17
  idMap: IdMap;
18
18
  }, import("../index.js").EntityDescription>;
@@ -20,7 +20,7 @@ export declare const getSpellEntityDescription: import("../creator.js").EntityDe
20
20
  * Get a JSON representation of the rules text for a ritual.
21
21
  */
22
22
  export declare const getRitualEntityDescription: import("../creator.js").EntityDescriptionCreator<"Ritual", {
23
- getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Property" | "MagicalTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement">;
23
+ getInstanceById: GetInstanceById<"Publication" | "Attribute" | "SkillModificationLevel" | "TargetCategory" | "Property" | "MagicalTradition" | "DerivedCharacteristic" | RatedIdentifier["kind"] | "Enhancement" | "FocusRule">;
24
24
  getChildInstancesForInstanceId: GetAllChildInstancesForParent<"Enhancement">;
25
25
  idMap: IdMap;
26
26
  }, import("../index.js").EntityDescription>;
@@ -12,7 +12,7 @@ import { createEntityDescriptionCreator } from "../creator.js";
12
12
  import { renderAnimalTypesSection } from "./partial/animalTypes.js";
13
13
  import { renderEnhancements } from "./partial/enhancements.js";
14
14
  import { attributedCustomName, attributedName } from "./partial/markdown.js";
15
- import { printAnimistPowerPrerequisites, printGeodeRitualPrerequisites, } from "./partial/prerequisites/index.js";
15
+ import { getDerivedFocusRuleBadgeFromPrerequisites, printAnimistPowerPrerequisites, printGeodeRitualPrerequisites, } from "./partial/prerequisites/index.js";
16
16
  import { renderCastingTime, renderFastSkillNonModifiableCastingTime, renderSlowSkillNonModifiableCastingTime, } from "./partial/rated/activatable/castingTime.js";
17
17
  import { renderMagicalActionCost, renderModifiableOneTimeCost, renderNonModifiableOneTimeCost, renderNonModifiableSustainedCost, renderStandaloneCostMap, } from "./partial/rated/activatable/cost.js";
18
18
  import { renderExpressionBasedDuration, renderMusicDuration, renderOneTimeDuration, renderSustainedDuration, } from "./partial/rated/activatable/duration.js";
@@ -162,6 +162,7 @@ export const getSpellEntityDescription = createEntityDescriptionCreator(({ getIn
162
162
  return {
163
163
  title: translation.name,
164
164
  className: "spell",
165
+ badge: mapNullable(entry.prerequisites, getDerivedFocusRuleBadgeFromPrerequisites)?.run(env),
165
166
  body: [
166
167
  {
167
168
  type: "definitionList",
@@ -221,6 +222,7 @@ export const getRitualEntityDescription = createEntityDescriptionCreator(({ getI
221
222
  return {
222
223
  title: translation.name,
223
224
  className: "ritual",
225
+ badge: mapNullable(entry.prerequisites, getDerivedFocusRuleBadgeFromPrerequisites)?.run(env),
224
226
  body: [
225
227
  {
226
228
  type: "definitionList",