@optolith/entity-descriptions 0.4.22 → 0.4.24

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,22 @@
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.4.24](https://github.com/Optolith/entity-descriptions/compare/v0.4.23...v0.4.24) (2026-06-20)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * only remove entry due to publication if publication is included ([3a97493](https://github.com/Optolith/entity-descriptions/commit/3a97493d515f6c0e0fdab2828dd9335611b3459f))
11
+
12
+ ## [0.4.23](https://github.com/Optolith/entity-descriptions/compare/v0.4.22...v0.4.23) (2026-06-20)
13
+
14
+
15
+ ### Features
16
+
17
+ * apply publication options to enhancements ([b4ba358](https://github.com/Optolith/entity-descriptions/commit/b4ba3583b4a7d7c989fc7b1e81d463ded6a50c54))
18
+ * apply publication options to whole entity description ([344c91f](https://github.com/Optolith/entity-descriptions/commit/344c91f2ba54af021d897540d9f074c674cbe0e2))
19
+ * publication options ([5cc4ce1](https://github.com/Optolith/entity-descriptions/commit/5cc4ce1e0a0df96747b162f8010a41d482f199f9))
20
+
5
21
  ## [0.4.22](https://github.com/Optolith/entity-descriptions/compare/v0.4.21...v0.4.22) (2026-06-14)
6
22
 
7
23
 
package/lib/creator.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { EntityMap } from "@optolith/database-schema/gen";
2
2
  import type { GetInstanceById } from "./helpers/getTypes.js";
3
3
  import type { LocaleEnvironment } from "./helpers/locale.js";
4
4
  import type { EntityDescription, RawEntityDescription } from "./index.js";
5
+ import { type PublicationOptions } from "./references/publicationOptions.js";
5
6
  /**
6
7
  * A union type of entities with their names as a discriminant property.
7
8
  */
@@ -29,4 +30,6 @@ export type EntityDescriptionCreator<ES extends keyof EntityMap = keyof EntityMa
29
30
  getInstanceById: GetInstanceById<"Publication">;
30
31
  } = {
31
32
  getInstanceById: GetInstanceById<"Publication">;
32
- }, R = EntityDescription> = (databaseAccessors: A, locale: LocaleEnvironment, entry: TaggedEntity<ES>) => R | undefined;
33
+ }, R = EntityDescription> = (databaseAccessors: A, locale: LocaleEnvironment, entry: TaggedEntity<ES>, options: {
34
+ publications: PublicationOptions;
35
+ }) => R | undefined;
package/lib/creator.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { isNotNullish } from "@elyukai/utils/nullable";
2
2
  import { assertExhaustive } from "@elyukai/utils/typeSafety";
3
3
  import { getReferencesTranslation } from "./references/index.js";
4
+ import { isEntryFromIncludedPublication, } from "./references/publicationOptions.js";
4
5
  const mapRawSectionContent = (mapDefinitionList, section) => {
5
6
  switch (section.type) {
6
7
  case "plain":
@@ -53,9 +54,10 @@ const mapRawSection = (section) => {
53
54
  * Creates a function that creates the JSON representation of the rules text for
54
55
  * a library entry.
55
56
  */
56
- export const createEntityDescriptionCreator = (fn) => (databaseAccessors, locale, entry) => {
57
- const rawEntry = fn(databaseAccessors, locale, entry);
58
- if (rawEntry === undefined) {
57
+ export const createEntityDescriptionCreator = (fn) => (databaseAccessors, locale, entry, options) => {
58
+ const rawEntry = fn(databaseAccessors, locale, entry, options);
59
+ if (rawEntry === undefined ||
60
+ !isEntryFromIncludedPublication({ src: rawEntry.references }, databaseAccessors.getInstanceById, locale.translateMap, options.publications)) {
59
61
  return undefined;
60
62
  }
61
63
  return {
@@ -67,6 +69,6 @@ export const createEntityDescriptionCreator = (fn) => (databaseAccessors, locale
67
69
  })),
68
70
  references: rawEntry.references === undefined
69
71
  ? undefined
70
- : getReferencesTranslation(databaseAccessors.getInstanceById, locale, rawEntry.references),
72
+ : getReferencesTranslation(databaseAccessors.getInstanceById, options.publications, locale, rawEntry.references),
71
73
  };
72
74
  };
@@ -46,7 +46,7 @@ export type BaseActivatableTranslation = {
46
46
  /**
47
47
  * Get a JSON representation of the rules text for a special ability.
48
48
  */
49
- 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" | "InstrumentEnchantment" | "KarmaSpecialAbility" | "Krallenkettenzauber" | "Kristallkugelzauber" | "LiturgicalStyleSpecialAbility" | "LycantropicGift" | "MagicalSign" | "MagicalSpecialAbility" | "MagicalTradition" | "MagicStyleSpecialAbility" | "OrbEnchantment" | "PactGift" | "ProtectiveWardingCircleSpecialAbility" | "RingEnchantment" | "Sermon" | "SexSpecialAbility" | "SickleRitual" | "SikaryanDrainSpecialAbility" | "SkillStyleSpecialAbility" | "SpellSwordEnchantment" | "StaffEnchantment" | "ToyEnchantment" | "Trinkhornzauber" | "VampiricGift" | "Vision" | "WandEnchantment" | "WeaponEnchantment", {
49
+ 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", {
50
50
  getInstanceById: GetInstanceById<"Publication" | "Subject" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "TradeSecret" | "Aspect" | "Property" | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Weapon" | "Patron" | "PersonalityTrait">;
51
51
  getAllInstances: GetAllInstances<"Script">;
52
52
  getResolvedSelectOptionById: GetResolvedSelectOptionById;
@@ -77,7 +77,7 @@ const getTextForTraditions = (deps, values) => {
77
77
  if (aspects.length === 0) {
78
78
  return attributedStringName;
79
79
  }
80
- return `${attributedStringName} (${aspects.join(" and ")})`;
80
+ return `${attributedStringName} (${deps.localeJoin(aspects, "conjunction")})`;
81
81
  }
82
82
  default:
83
83
  return assertExhaustive(trad);
@@ -134,8 +134,8 @@ export const getBlessingEntityDescription = createEntityDescriptionCreator(({ ge
134
134
  /**
135
135
  * Get a JSON representation of the rules text for a liturgical chant.
136
136
  */
137
- export const getLiturgicalChantEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }) => {
138
- const { translate, translateMap, compare: localeCompare } = locale;
137
+ export const getLiturgicalChantEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }, options) => {
138
+ const { translate, translateMap, compare: localeCompare, join: localeJoin } = locale;
139
139
  const translation = translateMap(entry.translations);
140
140
  if (translation === undefined) {
141
141
  return undefined;
@@ -161,6 +161,7 @@ export const getLiturgicalChantEntityDescription = createEntityDescriptionCreato
161
161
  return assertExhaustive(param);
162
162
  }
163
163
  },
164
+ publicationOptions: options.publications,
164
165
  };
165
166
  const { castingTime, cost, range, duration } = renderFastPerformanceParameters(entry.parameters).run(env);
166
167
  return {
@@ -181,6 +182,7 @@ export const getLiturgicalChantEntityDescription = createEntityDescriptionCreato
181
182
  translate,
182
183
  translateMap,
183
184
  localeCompare,
185
+ localeJoin,
184
186
  getInstanceById,
185
187
  }, entry.traditions),
186
188
  renderImprovementCost(entry.improvement_cost).run(env),
@@ -195,8 +197,8 @@ export const getLiturgicalChantEntityDescription = createEntityDescriptionCreato
195
197
  /**
196
198
  * Get a JSON representation of the rules text for a ceremony.
197
199
  */
198
- export const getCeremonyEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }) => {
199
- const { translate, translateMap, compare: localeCompare } = locale;
200
+ export const getCeremonyEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }, options) => {
201
+ const { translate, translateMap, compare: localeCompare, join: localeJoin } = locale;
200
202
  const translation = translateMap(entry.translations);
201
203
  if (translation === undefined) {
202
204
  return undefined;
@@ -222,6 +224,7 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator(({ ge
222
224
  return assertExhaustive(param);
223
225
  }
224
226
  },
227
+ publicationOptions: options.publications,
225
228
  };
226
229
  const { castingTime, cost, range, duration } = renderSlowPerformanceParameters(entry.parameters).run(env);
227
230
  return {
@@ -242,6 +245,7 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator(({ ge
242
245
  translate,
243
246
  translateMap,
244
247
  localeCompare,
248
+ localeJoin,
245
249
  getInstanceById,
246
250
  }, entry.traditions),
247
251
  renderImprovementCost(entry.improvement_cost).run(env),
@@ -4,4 +4,4 @@ import { type StdReader } from "./reader.js";
4
4
  /**
5
5
  * Render the enhancements section for an entity description, if applicable.
6
6
  */
7
- export declare const renderEnhancements: (parentId: SkillWithEnhancementsIdentifier, parentImprovementCost: ImprovementCost) => StdReader<RawEntityDescriptionSection | undefined, "t" | "tm" | "lc" | "lj" | "ibi" | "acibp", RatedIdentifier["kind"] | "Enhancement", "Enhancement">;
7
+ export declare const renderEnhancements: (parentId: SkillWithEnhancementsIdentifier, parentImprovementCost: ImprovementCost) => StdReader<RawEntityDescriptionSection | undefined, "t" | "tm" | "lc" | "lj" | "ibi" | "acibp" | "po", RatedIdentifier["kind"] | "Enhancement" | "Publication", "Enhancement">;
@@ -4,6 +4,7 @@ import { compareNumber } from "@elyukai/utils/ordering";
4
4
  import { Reader } from "@elyukai/utils/reader";
5
5
  import { assertExhaustive } from "@elyukai/utils/typeSafety";
6
6
  import { getAdventurePointsForActivation } from "@optolith/adventure-points/improvement-cost";
7
+ import { filterIncludedPublicationEntriesMapR } from "../../references/publicationOptions.js";
7
8
  import { printEnhancementPrerequisites } from "./prerequisites/index.js";
8
9
  import { getChildInstancesForInstanceIdR, translateMapR, translateR, } from "./reader.js";
9
10
  const getEnhancementAPValue = (adventurePoints, parentImprovementCost) => {
@@ -23,7 +24,9 @@ const renderEnhancement = (enhancement, parentImprovementCost) => translateMapR(
23
24
  /**
24
25
  * Render the enhancements section for an entity description, if applicable.
25
26
  */
26
- export const renderEnhancements = (parentId, parentImprovementCost) => getChildInstancesForInstanceIdR("Enhancement", parentId).thenW(enhancements => Reader.traverse(enhancements.toSorted(on(e => e.content.skill_rating, compareNumber)), enhancement => renderEnhancement(enhancement, parentImprovementCost)).thenW(enhancementDescriptions => {
27
+ export const renderEnhancements = (parentId, parentImprovementCost) => getChildInstancesForInstanceIdR("Enhancement", parentId).thenW(enhancements => filterIncludedPublicationEntriesMapR(enhancements, e => e.content)
28
+ .thenW(filteredEnhancements => Reader.traverse(filteredEnhancements.toSorted(on(e => e.content.skill_rating, compareNumber)), enhancement => renderEnhancement(enhancement, parentImprovementCost)))
29
+ .thenW(enhancementDescriptions => {
27
30
  const nonNullishDescriptions = enhancementDescriptions.filter(isNotNullish);
28
31
  if (nonNullishDescriptions.length === 0) {
29
32
  return Reader.of(undefined);
@@ -57,7 +57,7 @@ export declare const renderNonModifiableSustainedCost: (value: NonModifiableSust
57
57
  } & {
58
58
  translate: Translate;
59
59
  responsiveTextSize: ResponsiveTextSize;
60
- } & StdEnv<"t" | "rts" | "tm" | "eu", never, never, never>, string>;
60
+ } & StdEnv<"tm" | "t" | "rts" | "eu", never, never, never>, string>;
61
61
  /**
62
62
  * Returns the text for the cost of a sustained activatable skill.
63
63
  */
@@ -4,6 +4,7 @@ import type { IdArgsVariant } from "tsondb/schema/gen";
4
4
  import type { GetAllChildInstancesForParent, GetAllInstances, GetInstanceById } from "../../helpers/getTypes.js";
5
5
  import type { FormatNumber, LocaleCompare, LocaleJoin, LocaleJoinType } from "../../helpers/locale.js";
6
6
  import type { Format, LocaleMap, Translate, TranslateMap, TranslationKeyMatchingParamsOfKey, TranslationKeysWithoutParams, TranslationParamsInArray, Translations } from "../../helpers/translate.js";
7
+ import type { PublicationOptions } from "../../references/publicationOptions.js";
7
8
  import type { GetResolvedSelectOptionById } from "./prerequisites/single/activatable.js";
8
9
  import type { ModifiableParameter } from "./rated/activatable/nonModifiableSuffix.js";
9
10
  import { Speed } from "./rated/activatable/speed.js";
@@ -27,6 +28,7 @@ export type EnvMap<E extends keyof EntityMap = never, AE extends keyof EntityMap
27
28
  getAllInstances: GetAllInstances<AE>;
28
29
  getChildInstancesForInstanceId: GetAllChildInstancesForParent<CE>;
29
30
  getResolvedSelectOptionById: GetResolvedSelectOptionById;
31
+ publicationOptions: PublicationOptions;
30
32
  };
31
33
  /**
32
34
  * Shortcuts for selecting keys of the shared environment map type.
@@ -46,6 +48,7 @@ export type EnvMapAbbr = {
46
48
  ai: "getAllInstances";
47
49
  acibp: "getChildInstancesForInstanceId";
48
50
  rso: "getResolvedSelectOptionById";
51
+ po: "publicationOptions";
49
52
  };
50
53
  /**
51
54
  * The standard set of environment properties for readers in this project.
@@ -40,4 +40,4 @@ export declare const replaceTextIfNeeded: (translations: LocaleMap<{
40
40
  */
41
41
  export declare const appendNoteIfNeeded: (translations: LocaleMap<{
42
42
  note?: ResponsiveTextOptional;
43
- }> | undefined, valueToAppendTo: string) => Reader<StdEnv<"rts" | "tm">, string>;
43
+ }> | undefined, valueToAppendTo: string) => Reader<StdEnv<"tm" | "rts">, string>;
@@ -5,7 +5,7 @@ import { type ResponsiveTextSize } from "../responsiveText.js";
5
5
  /**
6
6
  * Possible units to use for time spans.
7
7
  */
8
- export type TimeSpanUnit = "Seconds" | "Minutes" | "Hours" | "Days" | "Weeks" | "Months" | "Years" | "Centuries" | "Actions" | "CombatRounds" | "SeductionActions" | "Rounds";
8
+ export type TimeSpanUnit = "Seconds" | "Minutes" | "Hours" | "Days" | "Weeks" | "Months" | "Years" | "Decades" | "Centuries" | "Actions" | "CombatRounds" | "SeductionActions" | "Rounds";
9
9
  /**
10
10
  * Returns the text for a time span unit.
11
11
  */
@@ -9,6 +9,7 @@ const timeSpanUnitTranslationKeys = {
9
9
  Weeks: [".input {$value :number} .input {$style :string} {{{$value} weeks}}", "{$value} weeks", ".input {$value :number} .input {$style :string} {{{$value} wks.}}", "{$value} wks."],
10
10
  Months: [".input {$value :number} .input {$style :string} {{{$value} months}}", "{$value} months", ".input {$value :number} .input {$style :string} {{{$value} mos.}}", "{$value} mos."],
11
11
  Years: [".input {$value :number} .input {$style :string} {{{$value} years}}", "{$value} years", ".input {$value :number} .input {$style :string} {{{$value} yrs.}}", "{$value} yrs."],
12
+ Decades: [".input {$value :number} .input {$style :string} {{{$value} decades}}", "{$value} decades", ".input {$value :number} .input {$style :string} {{{$value} dcs.}}", "{$value} dcs."],
12
13
  Centuries: [".input {$value :number} .input {$style :string} {{{$value} centuries}}", "{$value} centuries", ".input {$value :number} .input {$style :string} {{{$value} cent.}}", "{$value} cent."],
13
14
  Actions: [".input {$value :number} .input {$style :string} {{{$value} actions}}", "{$value} actions", ".input {$value :number} .input {$style :string} {{{$value} act}}", "{$value} act"],
14
15
  CombatRounds: [".input {$value :number} .input {$style :string} {{{$value} combat rounds}}", "{$value} combat rounds", ".input {$value :number} .input {$style :string} {{{$value} CR}}", "{$value} CR"],
@@ -127,7 +127,7 @@ export const getCantripEntityDescription = createEntityDescriptionCreator(({ get
127
127
  /**
128
128
  * Get a JSON representation of the rules text for a skill.
129
129
  */
130
- export const getSpellEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }) => {
130
+ export const getSpellEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }, options) => {
131
131
  const { translate, translateMap, compare: localeCompare } = locale;
132
132
  const translation = translateMap(entry.translations);
133
133
  if (translation === undefined) {
@@ -154,6 +154,7 @@ export const getSpellEntityDescription = createEntityDescriptionCreator(({ getIn
154
154
  return assertExhaustive(param);
155
155
  }
156
156
  },
157
+ publicationOptions: options.publications,
157
158
  };
158
159
  const { castingTime, cost, range, duration } = renderFastPerformanceParameters(entry.parameters).run(env);
159
160
  return {
@@ -184,7 +185,7 @@ export const getSpellEntityDescription = createEntityDescriptionCreator(({ getIn
184
185
  /**
185
186
  * Get a JSON representation of the rules text for a ritual.
186
187
  */
187
- export const getRitualEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }) => {
188
+ export const getRitualEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId, idMap }, locale, { content: entry, entity, id }, options) => {
188
189
  const { translate, translateMap, compare: localeCompare } = locale;
189
190
  const translation = translateMap(entry.translations);
190
191
  if (translation === undefined) {
@@ -211,6 +212,7 @@ export const getRitualEntityDescription = createEntityDescriptionCreator(({ getI
211
212
  return assertExhaustive(param);
212
213
  }
213
214
  },
215
+ publicationOptions: options.publications,
214
216
  };
215
217
  const { castingTime, cost, range, duration } = renderSlowPerformanceParameters(entry.parameters).run(env);
216
218
  return {